From dd4d9dd58e781998b6c438c56c36600440f29d26 Mon Sep 17 00:00:00 2001 From: Daniel <95646168+daniel-statsig@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:45:54 -0800 Subject: [PATCH 01/16] Remove Sorbet (#267) --- lib/client_initialize_helpers.rb | 8 +- lib/config_result.rb | 12 +- lib/diagnostics.rb | 64 +- lib/dynamic_config.rb | 42 +- lib/error_boundary.rb | 8 +- lib/evaluation_details.rb | 2 +- lib/evaluation_helpers.rb | 2 +- lib/evaluator.rb | 29 +- lib/feature_gate.rb | 44 +- lib/id_list.rb | 2 +- lib/interfaces/data_store.rb | 2 +- lib/interfaces/user_persistent_storage.rb | 2 +- lib/layer.rb | 36 +- lib/network.rb | 62 +- lib/spec_store.rb | 2 +- lib/statsig.rb | 144 +- lib/statsig_driver.rb | 70 +- lib/statsig_errors.rb | 2 +- lib/statsig_event.rb | 2 +- lib/statsig_logger.rb | 2 +- lib/statsig_options.rb | 98 +- lib/statsig_user.rb | 44 +- lib/ua_parser.rb | 2 +- lib/uri_helper.rb | 14 +- lib/user_persistent_storage_utils.rb | 30 +- sorbet/config | 4 - sorbet/rbi/annotations/webmock.rbi | 9 - sorbet/rbi/gems/addressable.rbi | 204 - sorbet/rbi/gems/concurrent-ruby.rbi | 1662 ----- sorbet/rbi/gems/connection_pool.rbi | 60 - sorbet/rbi/gems/crack.rbi | 62 - sorbet/rbi/gems/domain_name.rbi | 52 - sorbet/rbi/gems/ffi-compiler.rbi | 27 - sorbet/rbi/gems/ffi.rbi | 560 -- sorbet/rbi/gems/hashdiff.rbi | 66 - sorbet/rbi/gems/http-cookie.rbi | 93 - sorbet/rbi/gems/http-form_data.rbi | 76 - sorbet/rbi/gems/http.rbi | 637 -- sorbet/rbi/gems/ip3country.rbi | 23 - sorbet/rbi/gems/llhttp-ffi.rbi | 77 - sorbet/rbi/gems/minitest.rbi | 427 -- sorbet/rbi/gems/public_suffix.rbi | 105 - sorbet/rbi/gems/rexml.rbi | 612 -- sorbet/rbi/gems/spy.rbi | 166 - sorbet/rbi/gems/statsig.rbi | 28 - sorbet/rbi/gems/unf.rbi | 19 - sorbet/rbi/gems/user_agent_parser.rbi | 81 - sorbet/rbi/gems/webmock.rbi | 542 -- sorbet/rbi/hidden-definitions/hidden.rbi | 6491 ----------------- .../lib/minitest/all/minitest.rbi | 108 - sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi | 645 -- sorbet/rbi/sorbet-typed/lib/thor/all/thor.rbi | 905 --- sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi | 35 - sorbet/rbi/todo.rbi | 8 - sorbet/tapioca/config.yml | 13 - sorbet/tapioca/require.rb | 4 - test/data_adapter_test.rb | 2 +- test/dummy_data_adapter.rb | 2 +- test/dynamic_config_test.rb | 2 +- test/evaluation_details_test.rb | 2 +- test/layer_exposure_test.rb | 2 +- test/layer_test.rb | 2 +- test/local_overrides_test.rb | 2 +- test/manual_exposure_test.rb | 2 +- test/mock_server.rb | 2 +- test/sorbet_test.rb | 174 - test/statsig_e2e_test.rb | 2 +- test/test_concurrency.rb | 2 +- test/test_country_lookup.rb | 2 +- test/test_diagnostics.rb | 2 +- test/test_eval_user_provided_hashes.rb | 2 +- test/test_helper.rb | 2 +- test/test_logging.rb | 2 +- test/test_network.rb | 2 +- test/test_network_timeout.rb | 2 +- test/test_statsig.rb | 2 +- test/test_store.rb | 2 +- test/test_symbol_hashes.rb | 2 +- test/test_user_fields.rb | 2 +- 79 files changed, 383 insertions(+), 14361 deletions(-) delete mode 100644 sorbet/config delete mode 100644 sorbet/rbi/annotations/webmock.rbi delete mode 100644 sorbet/rbi/gems/addressable.rbi delete mode 100644 sorbet/rbi/gems/concurrent-ruby.rbi delete mode 100644 sorbet/rbi/gems/connection_pool.rbi delete mode 100644 sorbet/rbi/gems/crack.rbi delete mode 100644 sorbet/rbi/gems/domain_name.rbi delete mode 100644 sorbet/rbi/gems/ffi-compiler.rbi delete mode 100644 sorbet/rbi/gems/ffi.rbi delete mode 100644 sorbet/rbi/gems/hashdiff.rbi delete mode 100644 sorbet/rbi/gems/http-cookie.rbi delete mode 100644 sorbet/rbi/gems/http-form_data.rbi delete mode 100644 sorbet/rbi/gems/http.rbi delete mode 100644 sorbet/rbi/gems/ip3country.rbi delete mode 100644 sorbet/rbi/gems/llhttp-ffi.rbi delete mode 100644 sorbet/rbi/gems/minitest.rbi delete mode 100644 sorbet/rbi/gems/public_suffix.rbi delete mode 100644 sorbet/rbi/gems/rexml.rbi delete mode 100644 sorbet/rbi/gems/spy.rbi delete mode 100644 sorbet/rbi/gems/statsig.rbi delete mode 100644 sorbet/rbi/gems/unf.rbi delete mode 100644 sorbet/rbi/gems/user_agent_parser.rbi delete mode 100644 sorbet/rbi/gems/webmock.rbi delete mode 100644 sorbet/rbi/hidden-definitions/hidden.rbi delete mode 100644 sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi delete mode 100644 sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi delete mode 100644 sorbet/rbi/sorbet-typed/lib/thor/all/thor.rbi delete mode 100644 sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi delete mode 100644 sorbet/rbi/todo.rbi delete mode 100644 sorbet/tapioca/config.yml delete mode 100644 sorbet/tapioca/require.rb delete mode 100644 test/sorbet_test.rb diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index e9d535d..d95ff95 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -1,12 +1,12 @@ -# typed: true + require_relative 'hash_utils' -require 'sorbet-runtime' +# require 'sorbet-runtime' module ClientInitializeHelpers class ResponseFormatter - extend T::Sig + # extend T::Sig def initialize(evaluator, user, hash, client_sdk_key) @evaluator = evaluator @@ -24,7 +24,7 @@ def get_responses(key) private - sig { params(secondary_exposures: T::Array[T::Hash[String, String]]).returns(T::Array[T::Hash[String, String]]) } + # sig { params(secondary_exposures: T::Array[T::Hash[String, String]]).returns(T::Array[T::Hash[String, String]]) } def filter_segments_from_secondary_exposures(secondary_exposures) secondary_exposures.reject do |exposure| exposure['gate'].to_s.start_with?('segment:') diff --git a/lib/config_result.rb b/lib/config_result.rb index d0b64d4..381f61b 100644 --- a/lib/config_result.rb +++ b/lib/config_result.rb @@ -1,10 +1,10 @@ -# typed: true -require 'sorbet-runtime' + +# require 'sorbet-runtime' module Statsig class ConfigResult - extend T::Sig + # extend T::Sig attr_accessor :name attr_accessor :gate_value @@ -48,7 +48,7 @@ def initialize( @target_app_ids = target_app_ids end - sig { params(config_name: String, user_persisted_values: UserPersistedValues).returns(T.nilable(ConfigResult)) } + # sig { params(config_name: String, user_persisted_values: UserPersistedValues).returns(T.nilable(ConfigResult)) } def self.from_user_persisted_values(config_name, user_persisted_values) sticky_values = user_persisted_values[config_name] return nil if sticky_values.nil? @@ -56,7 +56,7 @@ def self.from_user_persisted_values(config_name, user_persisted_values) from_hash(config_name, sticky_values) end - sig { params(config_name: String, hash: Hash).returns(ConfigResult) } + # sig { params(config_name: String, hash: Hash).returns(ConfigResult) } def self.from_hash(config_name, hash) new( config_name, @@ -71,7 +71,7 @@ def self.from_hash(config_name, hash) ) end - sig { returns(Hash) } + # sig { returns(Hash) } def to_hash { json_value: @json_value, diff --git a/lib/diagnostics.rb b/lib/diagnostics.rb index d30608c..7a356bb 100644 --- a/lib/diagnostics.rb +++ b/lib/diagnostics.rb @@ -1,18 +1,18 @@ -# typed: true -require 'sorbet-runtime' + +# require 'sorbet-runtime' module Statsig class Diagnostics - extend T::Sig + # extend T::Sig - sig { returns(String) } + # sig { returns(String) } attr_accessor :context - sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) } + # sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) } attr_reader :markers - sig { returns(T::Hash[String, Numeric]) } + # sig { returns(T::Hash[String, Numeric]) } attr_accessor :sample_rates def initialize(context) @@ -21,14 +21,14 @@ def initialize(context) @sample_rates = {} end - sig do - params( - key: String, - action: String, - step: T.any(String, NilClass), - tags: T::Hash[Symbol, T.untyped] - ).void - end + # sig do + # params( + # key: String, + # action: String, + # step: T.any(String, NilClass), + # tags: T::Hash[Symbol, T.untyped] + # ).void + # end def mark(key, action, step, tags) marker = { @@ -47,20 +47,20 @@ def mark(key, action, step, tags) @markers.push(marker) end - sig do - params( - key: String, - step: T.any(String, NilClass), - tags: T::Hash[Symbol, T.untyped] - ).returns(Tracker) - end + # sig do + # params( + # key: String, + # step: T.any(String, NilClass), + # tags: T::Hash[Symbol, T.untyped] + # ).returns(Tracker) + # end def track(key, step = nil, tags = {}) tracker = Tracker.new(self, key, step, tags) tracker.start(**tags) tracker end - sig { returns(T::Hash[Symbol, T.untyped]) } + # sig { returns(T::Hash[Symbol, T.untyped]) } def serialize { @@ -101,16 +101,16 @@ class Context API_CALL_KEYS = %w[check_gate get_config get_experiment get_layer].freeze class Tracker - extend T::Sig - - sig do - params( - diagnostics: Diagnostics, - key: String, - step: T.any(String, NilClass), - tags: T::Hash[Symbol, T.untyped] - ).void - end + # extend T::Sig + + # sig do + # params( + # diagnostics: Diagnostics, + # key: String, + # step: T.any(String, NilClass), + # tags: T::Hash[Symbol, T.untyped] + # ).void + # end def initialize(diagnostics, key, step, tags = {}) @diagnostics = diagnostics @key = key diff --git a/lib/dynamic_config.rb b/lib/dynamic_config.rb index bc23aa1..a07a34d 100644 --- a/lib/dynamic_config.rb +++ b/lib/dynamic_config.rb @@ -1,6 +1,6 @@ -# typed: false -require 'sorbet-runtime' + +# require 'sorbet-runtime' ## # Contains the current experiment/dynamic config values from Statsig @@ -9,36 +9,36 @@ # # Experiments Documentation: https://docs.statsig.com/experiments-plus class DynamicConfig - extend T::Sig + # extend T::Sig - sig { returns(String) } + # sig { returns(String) } attr_accessor :name - sig { returns(T::Hash[String, T.untyped]) } + # sig { returns(T::Hash[String, T.untyped]) } attr_accessor :value - sig { returns(String) } + # sig { returns(String) } attr_accessor :rule_id - sig { returns(T.nilable(String)) } + # sig { returns(T.nilable(String)) } attr_accessor :group_name - sig { returns(String) } + # sig { returns(String) } attr_accessor :id_type - sig { returns(T.nilable(Statsig::EvaluationDetails)) } + # sig { returns(T.nilable(Statsig::EvaluationDetails)) } attr_accessor :evaluation_details - sig do - params( - name: String, - value: T::Hash[String, T.untyped], - rule_id: String, - group_name: T.nilable(String), - id_type: String, - evaluation_details: T.nilable(Statsig::EvaluationDetails) - ).void - end + # sig do + # params( + # name: String, + # value: T::Hash[String, T.untyped], + # rule_id: String, + # group_name: T.nilable(String), + # id_type: String, + # evaluation_details: T.nilable(Statsig::EvaluationDetails) + # ).void + # end def initialize(name, value = {}, rule_id = '', group_name = nil, id_type = '', evaluation_details = nil) @name = name @value = value @@ -48,7 +48,7 @@ def initialize(name, value = {}, rule_id = '', group_name = nil, id_type = '', e @evaluation_details = evaluation_details end - sig { params(index: String, default_value: T.untyped).returns(T.untyped) } + # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found. # @@ -59,7 +59,7 @@ def get(index, default_value) @value[index] end - sig { params(index: String, default_value: T.untyped).returns(T.untyped) } + # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found # or is found to have a different type from the default_value. diff --git a/lib/error_boundary.rb b/lib/error_boundary.rb index 3ef62ca..45e4de7 100644 --- a/lib/error_boundary.rb +++ b/lib/error_boundary.rb @@ -1,15 +1,15 @@ -# typed: true + require 'statsig_errors' -require 'sorbet-runtime' +# require 'sorbet-runtime' $endpoint = 'https://statsigapi.net/v1/sdk_exception' module Statsig class ErrorBoundary - extend T::Sig + # extend T::Sig - sig { params(sdk_key: String).void } + # sig { params(sdk_key: String).void } def initialize(sdk_key) @sdk_key = sdk_key @seen = Set.new diff --git a/lib/evaluation_details.rb b/lib/evaluation_details.rb index 30334aa..b20bda2 100644 --- a/lib/evaluation_details.rb +++ b/lib/evaluation_details.rb @@ -1,4 +1,4 @@ -# typed: true + module Statsig module EvaluationReason diff --git a/lib/evaluation_helpers.rb b/lib/evaluation_helpers.rb index 371514f..f8e246e 100644 --- a/lib/evaluation_helpers.rb +++ b/lib/evaluation_helpers.rb @@ -1,4 +1,4 @@ -# typed: true + require 'time' module EvaluationHelpers diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 526d4f2..d51a3f5 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -1,6 +1,6 @@ -# typed: false -require 'sorbet-runtime' + +# require 'sorbet-runtime' require 'config_result' require 'country_lookup' require 'digest' @@ -15,26 +15,25 @@ module Statsig class Evaluator - extend T::Sig + # extend T::Sig UNSUPPORTED_EVALUATION = :unsupported_eval - sig { returns(SpecStore) } attr_accessor :spec_store - sig { returns(StatsigOptions) } + # sig { returns(StatsigOptions) } attr_accessor :options - sig { returns(UserPersistentStorageUtils) } + # sig { returns(UserPersistentStorageUtils) } attr_accessor :persistent_storage_utils - sig do - params( - store: SpecStore, - options: StatsigOptions, - persistent_storage_utils: UserPersistentStorageUtils, - ).void - end + # sig do + # params( + # store: SpecStore, + # options: StatsigOptions, + # persistent_storage_utils: UserPersistentStorageUtils, + # ).void + # end def initialize(store, options, persistent_storage_utils) UAParser.initialize_async CountryLookup.initialize_async @@ -72,7 +71,7 @@ def check_gate(user, gate_name) eval_spec(user, @spec_store.get_gate(gate_name)) end - sig { params(user: StatsigUser, config_name: String, user_persisted_values: T.nilable(UserPersistedValues)).returns(ConfigResult) } + # sig { params(user: StatsigUser, config_name: String, user_persisted_values: T.nilable(UserPersistedValues)).returns(ConfigResult) } def get_config(user, config_name, user_persisted_values: nil) if @config_overrides.key?(config_name) id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)['idType'] : '' @@ -210,7 +209,7 @@ def override_config(config, value) @config_overrides[config] = value end - sig { params(user: StatsigUser, config: Hash).returns(ConfigResult) } + # sig { params(user: StatsigUser, config: Hash).returns(ConfigResult) } def eval_spec(user, config) default_rule_id = 'default' exposures = [] diff --git a/lib/feature_gate.rb b/lib/feature_gate.rb index 73d09a8..1468fd6 100644 --- a/lib/feature_gate.rb +++ b/lib/feature_gate.rb @@ -1,42 +1,42 @@ -# typed: false -require 'sorbet-runtime' + +# require 'sorbet-runtime' class FeatureGate - extend T::Sig + # extend T::Sig - sig { returns(String) } + # sig { returns(String) } attr_accessor :name - sig { returns(T::Boolean) } + # sig { returns(T::Boolean) } attr_accessor :value - sig { returns(String) } + # sig { returns(String) } attr_accessor :rule_id - sig { returns(T.nilable(String)) } + # sig { returns(T.nilable(String)) } attr_accessor :group_name - sig { returns(String) } + # sig { returns(String) } attr_accessor :id_type - sig { returns(T.nilable(Statsig::EvaluationDetails)) } + # sig { returns(T.nilable(Statsig::EvaluationDetails)) } attr_accessor :evaluation_details - sig { returns(T.nilable(T::Array[String])) } + # sig { returns(T.nilable(T::Array[String])) } attr_accessor :target_app_ids - sig do - params( - name: String, - value: T::Boolean, - rule_id: String, - group_name: T.nilable(String), - id_type: String, - evaluation_details: T.nilable(Statsig::EvaluationDetails), - target_app_ids: T.nilable(T::Array[String]) - ).void - end + # sig do + # params( + # name: String, + # value: T::Boolean, + # rule_id: String, + # group_name: T.nilable(String), + # id_type: String, + # evaluation_details: T.nilable(Statsig::EvaluationDetails), + # target_app_ids: T.nilable(T::Array[String]) + # ).void + # end def initialize( name, value: false, @@ -55,7 +55,7 @@ def initialize( @target_app_ids = target_app_ids end - sig { params(res: Statsig::ConfigResult).returns(FeatureGate) } + # sig { params(res: Statsig::ConfigResult).returns(FeatureGate) } def self.from_config_result(res) new( res.name, diff --git a/lib/id_list.rb b/lib/id_list.rb index 191748a..c106c58 100644 --- a/lib/id_list.rb +++ b/lib/id_list.rb @@ -1,4 +1,4 @@ -# typed: true + module Statsig class IDList attr_accessor :name diff --git a/lib/interfaces/data_store.rb b/lib/interfaces/data_store.rb index a8f9663..6aa4919 100644 --- a/lib/interfaces/data_store.rb +++ b/lib/interfaces/data_store.rb @@ -1,4 +1,4 @@ -# typed: true + module Statsig module Interfaces class IDataStore diff --git a/lib/interfaces/user_persistent_storage.rb b/lib/interfaces/user_persistent_storage.rb index 7dce208..5802566 100644 --- a/lib/interfaces/user_persistent_storage.rb +++ b/lib/interfaces/user_persistent_storage.rb @@ -1,4 +1,4 @@ -# typed: true + module Statsig module Interfaces class IUserPersistentStorage diff --git a/lib/layer.rb b/lib/layer.rb index b27356d..bf62919 100644 --- a/lib/layer.rb +++ b/lib/layer.rb @@ -1,6 +1,6 @@ -# typed: false -require 'sorbet-runtime' + +# require 'sorbet-runtime' ## # Contains the current values from Statsig. # Will contain layer default values for all shared parameters in that layer. @@ -9,27 +9,27 @@ # # Layers Documentation: https://docs.statsig.com/layers class Layer - extend T::Sig + # extend T::Sig - sig { returns(String) } + # sig { returns(String) } attr_accessor :name - sig { returns(String) } + # sig { returns(String) } attr_accessor :rule_id - sig { returns(String) } + # sig { returns(String) } attr_accessor :group_name - sig do - params( - name: String, - value: T::Hash[String, T.untyped], - rule_id: String, - group_name: T.nilable(String), - allocated_experiment: T.nilable(String), - exposure_log_func: T.any(Method, Proc, NilClass) - ).void - end + # sig do + # params( + # name: String, + # value: T::Hash[String, T.untyped], + # rule_id: String, + # group_name: T.nilable(String), + # allocated_experiment: T.nilable(String), + # exposure_log_func: T.any(Method, Proc, NilClass) + # ).void + # end def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_experiment = nil, exposure_log_func = nil) @name = name @value = value @@ -39,7 +39,7 @@ def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_exper @exposure_log_func = exposure_log_func end - sig { params(index: String, default_value: T.untyped).returns(T.untyped) } + # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found. # @@ -55,7 +55,7 @@ def get(index, default_value) @value[index] end - sig { params(index: String, default_value: T.untyped).returns(T.untyped) } + # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found # or is found to have a different type from the default_value. diff --git a/lib/network.rb b/lib/network.rb index 6ad2394..7d8010b 100644 --- a/lib/network.rb +++ b/lib/network.rb @@ -1,9 +1,9 @@ -# typed: true + require 'http' require 'json' require 'securerandom' -require 'sorbet-runtime' +# require 'sorbet-runtime' require 'uri_helper' require 'connection_pool' @@ -20,9 +20,9 @@ def initialize(msg = nil, http_code = nil) end class Network - extend T::Sig + # extend T::Sig - sig { params(server_secret: String, options: StatsigOptions, backoff_mult: Integer).void } + # sig { params(server_secret: String, options: StatsigOptions, backoff_mult: Integer).void } def initialize(server_secret, options, backoff_mult = 10) super() URIHelper.initialize(options) @@ -54,41 +54,41 @@ def initialize(server_secret, options, backoff_mult = 10) end end - sig do - params(since_time: Integer) - .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - end + # sig do + # params(since_time: Integer) + # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) + # end def download_config_specs(since_time) get("download_config_specs/#{@server_secret}.json?sinceTime=#{since_time}") end - class HttpMethod < T::Enum - enums do - GET = new - POST = new - end - end - - sig do - params(endpoint: String, retries: Integer, backoff: Integer) - .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - end + # class HttpMethod < T::Enum + # enums do + # GET = new + # POST = new + # end + # end + + # sig do + # params(endpoint: String, retries: Integer, backoff: Integer) + # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) + # end def get(endpoint, retries = 0, backoff = 1) - request(HttpMethod::GET, endpoint, nil, retries, backoff) + request(:GET, endpoint, nil, retries, backoff) end - sig do - params(endpoint: String, body: String, retries: Integer, backoff: Integer) - .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - end + # sig do + # params(endpoint: String, body: String, retries: Integer, backoff: Integer) + # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) + # end def post(endpoint, body, retries = 0, backoff = 1) - request(HttpMethod::POST, endpoint, body, retries, backoff) + request(:POST, endpoint, body, retries, backoff) end - sig do - params(method: HttpMethod, endpoint: String, body: T.nilable(String), retries: Integer, backoff: Integer) - .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - end + # sig do + # params(method: HttpMethod, endpoint: String, body: T.nilable(String), retries: Integer, backoff: Integer) + # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) + # end def request(method, endpoint, body, retries = 0, backoff = 1) if @local_mode return nil, nil @@ -107,9 +107,9 @@ def request(method, endpoint, body, retries = 0, backoff = 1) res = @connection_pool.with do |conn| request = conn.headers('STATSIG-CLIENT-TIME' => (Time.now.to_f * 1000).to_i.to_s) case method - when HttpMethod::GET + when :GET request.get(url) - when HttpMethod::POST + when :POST request.post(url, body: body) end end diff --git a/lib/spec_store.rb b/lib/spec_store.rb index 3e0f397..6ef3a56 100644 --- a/lib/spec_store.rb +++ b/lib/spec_store.rb @@ -1,4 +1,4 @@ -# typed: false + require 'net/http' require 'uri' require 'evaluation_details' diff --git a/lib/statsig.rb b/lib/statsig.rb index c133cb4..f816403 100644 --- a/lib/statsig.rb +++ b/lib/statsig.rb @@ -1,13 +1,11 @@ -# typed: true - require 'statsig_driver' -require 'sorbet-runtime' +# require 'sorbet-runtime' require 'statsig_errors' module Statsig - extend T::Sig + # extend T::Sig - sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void } + # sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void } ## # Initializes the Statsig SDK. # @@ -26,40 +24,40 @@ def self.initialize(secret_key, options = nil, error_callback = nil) @shared_instance = StatsigDriver.new(secret_key, options, error_callback) end - class GetGateOptions < T::Struct - prop :disable_log_exposure, T::Boolean, default: false - prop :skip_evaluation, T::Boolean, default: false - end + # class GetGateOptions < T::Struct + # prop :disable_log_exposure, T::Boolean, default: false + # prop :skip_evaluation, T::Boolean, default: false + # end - sig { params(user: StatsigUser, gate_name: String, options: GetGateOptions).returns(FeatureGate) } + # sig { params(user: StatsigUser, gate_name: String, options: GetGateOptions).returns(FeatureGate) } ## # Gets the gate, evaluated against the given user. An exposure event will automatically be logged for the gate. # # @param user A StatsigUser object used for the evaluation # @param gate_name The name of the gate being checked # @param options Additional options for evaluating the gate - def self.get_gate(user, gate_name, options = GetGateOptions.new) + def self.get_gate(user, gate_name, options) ensure_initialized @shared_instance&.get_gate(user, gate_name, options) end - class CheckGateOptions < T::Struct - prop :disable_log_exposure, T::Boolean, default: false - end + # class CheckGateOptions < T::Struct + # prop :disable_log_exposure, T::Boolean, default: false + # end - sig { params(user: StatsigUser, gate_name: String, options: CheckGateOptions).returns(T::Boolean) } + # sig { params(user: StatsigUser, gate_name: String, options: CheckGateOptions).returns(T::Boolean) } ## # Gets the boolean result of a gate, evaluated against the given user. An exposure event will automatically be logged for the gate. # # @param user A StatsigUser object used for the evaluation # @param gate_name The name of the gate being checked # @param options Additional options for evaluating the gate - def self.check_gate(user, gate_name, options = CheckGateOptions.new) + def self.check_gate(user, gate_name, options) ensure_initialized @shared_instance&.check_gate(user, gate_name, options) end - sig { params(user: StatsigUser, gate_name: String).returns(T::Boolean) } + # sig { params(user: StatsigUser, gate_name: String).returns(T::Boolean) } ## # Gets the boolean result of a gate, evaluated against the given user. # @@ -67,10 +65,10 @@ def self.check_gate(user, gate_name, options = CheckGateOptions.new) # @param gate_name The name of the gate being checked def self.check_gate_with_exposure_logging_disabled(user, gate_name) ensure_initialized - @shared_instance&.check_gate(user, gate_name, CheckGateOptions.new(disable_log_exposure: true)) + @shared_instance&.check_gate(user, gate_name, { disable_log_exposure: true }) end - sig { params(user: StatsigUser, gate_name: String).void } + # sig { params(user: StatsigUser, gate_name: String).void } ## # Logs an exposure event for the gate # @@ -81,23 +79,23 @@ def self.manually_log_gate_exposure(user, gate_name) @shared_instance&.manually_log_gate_exposure(user, gate_name) end - class GetConfigOptions < T::Struct - prop :disable_log_exposure, T::Boolean, default: false - end + # class GetConfigOptions < T::Struct + # prop :disable_log_exposure, T::Boolean, default: false + # end - sig { params(user: StatsigUser, dynamic_config_name: String, options: GetConfigOptions).returns(DynamicConfig) } + # sig { params(user: StatsigUser, dynamic_config_name: String, options: GetConfigOptions).returns(DynamicConfig) } ## # Get the values of a dynamic config, evaluated against the given user. An exposure event will automatically be logged for the dynamic config. # # @param user A StatsigUser object used for the evaluation # @param dynamic_config_name The name of the dynamic config # @param options Additional options for evaluating the config - def self.get_config(user, dynamic_config_name, options = GetConfigOptions.new) + def self.get_config(user, dynamic_config_name, options) ensure_initialized @shared_instance&.get_config(user, dynamic_config_name, options) end - sig { params(user: StatsigUser, dynamic_config_name: String).returns(DynamicConfig) } + # sig { params(user: StatsigUser, dynamic_config_name: String).returns(DynamicConfig) } ## # Get the values of a dynamic config, evaluated against the given user. # @@ -105,10 +103,10 @@ def self.get_config(user, dynamic_config_name, options = GetConfigOptions.new) # @param dynamic_config_name The name of the dynamic config def self.get_config_with_exposure_logging_disabled(user, dynamic_config_name) ensure_initialized - @shared_instance&.get_config(user, dynamic_config_name, GetConfigOptions.new(disable_log_exposure: true)) + @shared_instance&.get_config(user, dynamic_config_name, {disable_log_exposure: true}) end - sig { params(user: StatsigUser, dynamic_config: String).void } + # sig { params(user: StatsigUser, dynamic_config: String).void } ## # Logs an exposure event for the dynamic config # @@ -119,24 +117,24 @@ def self.manually_log_config_exposure(user, dynamic_config) @shared_instance&.manually_log_config_exposure(user, dynamic_config) end - class GetExperimentOptions < T::Struct - prop :disable_log_exposure, T::Boolean, default: false - prop :user_persisted_values, T.nilable(T::Hash[String, Hash]), default: nil - end + # class GetExperimentOptions < T::Struct + # prop :disable_log_exposure, T::Boolean, default: false + # prop :user_persisted_values, T.nilable(T::Hash[String, Hash]), default: nil + # end - sig { params(user: StatsigUser, experiment_name: String, options: GetExperimentOptions).returns(DynamicConfig) } + # sig { params(user: StatsigUser, experiment_name: String, options: GetExperimentOptions).returns(DynamicConfig) } ## # Get the values of an experiment, evaluated against the given user. An exposure event will automatically be logged for the experiment. # # @param user A StatsigUser object used for the evaluation # @param experiment_name The name of the experiment # @param options Additional options for evaluating the experiment - def self.get_experiment(user, experiment_name, options = GetExperimentOptions.new) + def self.get_experiment(user, experiment_name, options) ensure_initialized @shared_instance&.get_experiment(user, experiment_name, options) end - sig { params(user: StatsigUser, experiment_name: String).returns(DynamicConfig) } + # sig { params(user: StatsigUser, experiment_name: String).returns(DynamicConfig) } ## # Get the values of an experiment, evaluated against the given user. # @@ -144,10 +142,10 @@ def self.get_experiment(user, experiment_name, options = GetExperimentOptions.ne # @param experiment_name The name of the experiment def self.get_experiment_with_exposure_logging_disabled(user, experiment_name) ensure_initialized - @shared_instance&.get_experiment(user, experiment_name, GetExperimentOptions.new(disable_log_exposure: true)) + @shared_instance&.get_experiment(user, experiment_name, {disable_log_exposure: true}) end - sig { params(user: StatsigUser, experiment_name: String).void } + # sig { params(user: StatsigUser, experiment_name: String).void } ## # Logs an exposure event for the experiment # @@ -158,17 +156,17 @@ def self.manually_log_experiment_exposure(user, experiment_name) @shared_instance&.manually_log_config_exposure(user, experiment_name) end - sig { params(user: StatsigUser, id_type: String).returns(UserPersistedValues) } + # sig { params(user: StatsigUser, id_type: String).returns(UserPersistedValues) } def self.get_user_persisted_values(user, id_type) ensure_initialized @shared_instance&.get_user_persisted_values(user, id_type) end - class GetLayerOptions < T::Struct - prop :disable_log_exposure, T::Boolean, default: false - end + # class GetLayerOptions < T::Struct + # prop :disable_log_exposure, T::Boolean, default: false + # end - sig { params(user: StatsigUser, layer_name: String, options: GetLayerOptions).returns(Layer) } + # sig { params(user: StatsigUser, layer_name: String, options: GetLayerOptions).returns(Layer) } ## # Get the values of a layer, evaluated against the given user. # Exposure events will be fired when get or get_typed is called on the resulting Layer class. @@ -180,7 +178,7 @@ def self.get_layer(user, layer_name, options = GetLayerOptions.new) @shared_instance&.get_layer(user, layer_name, options) end - sig { params(user: StatsigUser, layer_name: String).returns(Layer) } + # sig { params(user: StatsigUser, layer_name: String).returns(Layer) } ## # Get the values of a layer, evaluated against the given user. # @@ -191,7 +189,7 @@ def self.get_layer_with_exposure_logging_disabled(user, layer_name) @shared_instance&.get_layer(user, layer_name, GetLayerOptions.new(disable_log_exposure: true)) end - sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void } + # sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void } ## # Logs an exposure event for the parameter in the given layer # @@ -203,10 +201,10 @@ def self.manually_log_layer_parameter_exposure(user, layer_name, parameter_name) @shared_instance&.manually_log_layer_parameter_exposure(user, layer_name, parameter_name) end - sig { params(user: StatsigUser, - event_name: String, - value: T.any(String, Integer, Float, NilClass), - metadata: T.any(T::Hash[String, T.untyped], NilClass)).void } + # sig { params(user: StatsigUser, + # event_name: String, + # value: T.any(String, Integer, Float, NilClass), + # metadata: T.any(T::Hash[String, T.untyped], NilClass)).void } ## # Logs an event to Statsig with the provided values. # @@ -229,7 +227,7 @@ def self.sync_idlists @shared_instance&.manually_sync_idlists end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } ## # Returns a list of all gate names # @@ -238,7 +236,7 @@ def self.list_gates @shared_instance&.list_gates end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } ## # Returns a list of all config names # @@ -247,7 +245,7 @@ def self.list_configs @shared_instance&.list_configs end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } ## # Returns a list of all experiment names # @@ -256,7 +254,7 @@ def self.list_experiments @shared_instance&.list_experiments end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } ## # Returns a list of all autotune names # @@ -265,7 +263,7 @@ def self.list_autotunes @shared_instance&.list_autotunes end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } ## # Returns a list of all layer names # @@ -274,7 +272,7 @@ def self.list_layers @shared_instance&.list_layers end - sig { void } + # sig { void } ## # Stops all Statsig activity and flushes any pending events. def self.shutdown @@ -284,7 +282,7 @@ def self.shutdown @shared_instance = nil end - sig { params(gate_name: String, gate_value: T::Boolean).void } + # sig { params(gate_name: String, gate_value: T::Boolean).void } ## # Sets a value to be returned for the given gate instead of the actual evaluated value. # @@ -295,7 +293,7 @@ def self.override_gate(gate_name, gate_value) @shared_instance&.override_gate(gate_name, gate_value) end - sig { params(config_name: String, config_value: Hash).void } + # sig { params(config_name: String, config_value: Hash).void } ## # Sets a value to be returned for the given dynamic config/experiment instead of the actual evaluated value. # @@ -306,7 +304,7 @@ def self.override_config(config_name, config_value) @shared_instance&.override_config(config_name, config_value) end - sig { params(user: StatsigUser, hash: String, client_sdk_key: T.any(String, NilClass)).returns(T.any(T::Hash[String, T.untyped], NilClass)) } + # sig { params(user: StatsigUser, hash: String, client_sdk_key: T.any(String, NilClass)).returns(T.any(T::Hash[String, T.untyped], NilClass)) } ## # Gets all evaluated values for the given user. # These values can then be given to a Statsig Client SDK via bootstrapping. @@ -321,7 +319,7 @@ def self.get_client_initialize_response(user, hash: 'sha256', client_sdk_key: ni @shared_instance&.get_client_initialize_response(user, hash, client_sdk_key) end - sig { returns(T::Hash[String, String]) } + # sig { returns(T::Hash[String, String]) } ## # Internal Statsig metadata for this SDK def self.get_statsig_metadata @@ -340,27 +338,27 @@ def self.ensure_initialized end end - sig { params(options: T.any(StatsigOptions, NilClass)).void } + # sig { params(options: T.any(StatsigOptions, NilClass)).void } def self.bind_sorbet_loggers(options) if options&.disable_sorbet_logging_handlers == true return end - T::Configuration.call_validation_error_handler = lambda do |signature, opts| - puts "[Type Error] " + opts[:pretty_message] - end - - T::Configuration.inline_type_error_handler = lambda do |error, opts| - puts "[Type Error] " + error.message - end - - T::Configuration.sig_builder_error_handler = lambda do |error, location| - puts "[Type Error] " + error.message - end - - T::Configuration.sig_validation_error_handler = lambda do |error, opts| - puts "[Type Error] " + error.message - end + # T::Configuration.call_validation_error_handler = lambda do |signature, opts| + # puts "[Type Error] " + opts[:pretty_message] + # end + # + # T::Configuration.inline_type_error_handler = lambda do |error, opts| + # puts "[Type Error] " + error.message + # end + # + # T::Configuration.sig_builder_error_handler = lambda do |error, location| + # puts "[Type Error] " + error.message + # end + # + # T::Configuration.sig_validation_error_handler = lambda do |error, opts| + # puts "[Type Error] " + error.message + # end return end diff --git a/lib/statsig_driver.rb b/lib/statsig_driver.rb index c726b6a..7146ad9 100644 --- a/lib/statsig_driver.rb +++ b/lib/statsig_driver.rb @@ -1,4 +1,4 @@ -# typed: true + require 'config_result' require 'evaluator' @@ -13,13 +13,13 @@ require 'feature_gate' require 'error_boundary' require 'layer' -require 'sorbet-runtime' +# require 'sorbet-runtime' require 'diagnostics' class StatsigDriver - extend T::Sig + # extend T::Sig - sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void } + # sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void } def initialize(secret_key, options = nil, error_callback = nil) unless secret_key.start_with?('secret-') raise Statsig::ValueError.new('Invalid secret key provided. Provide your project secret key from the Statsig console') @@ -47,14 +47,14 @@ def initialize(secret_key, options = nil, error_callback = nil) }, caller: __method__.to_s) end - sig do - params( - user: StatsigUser, - gate_name: String, - disable_log_exposure: T::Boolean, - skip_evaluation: T::Boolean - ).returns(FeatureGate) - end + # sig do + # params( + # user: StatsigUser, + # gate_name: String, + # disable_log_exposure: T::Boolean, + # skip_evaluation: T::Boolean + # ).returns(FeatureGate) + # end def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: false) if skip_evaluation gate = @store.get_gate(gate_name) @@ -76,7 +76,7 @@ def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: FeatureGate.from_config_result(res) end - sig { params(user: StatsigUser, gate_name: String, options: Statsig::GetGateOptions).returns(FeatureGate) } + # sig { params(user: StatsigUser, gate_name: String, options: Statsig::GetGateOptions).returns(FeatureGate) } def get_gate(user, gate_name, options = Statsig::GetGateOptions.new) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { @@ -85,7 +85,7 @@ def get_gate(user, gate_name, options = Statsig::GetGateOptions.new) }, recover: -> { false }, caller: __method__.to_s) end - sig { params(user: StatsigUser, gate_name: String, options: Statsig::CheckGateOptions).returns(T::Boolean) } + # sig { params(user: StatsigUser, gate_name: String, options: Statsig::CheckGateOptions).returns(T::Boolean) } def check_gate(user, gate_name, options = Statsig::CheckGateOptions.new) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { @@ -94,7 +94,7 @@ def check_gate(user, gate_name, options = Statsig::CheckGateOptions.new) }, recover: -> { false }, caller: __method__.to_s) end - sig { params(user: StatsigUser, gate_name: String).void } + # sig { params(user: StatsigUser, gate_name: String).void } def manually_log_gate_exposure(user, gate_name) @err_boundary.capture(task: lambda { res = @evaluator.check_gate(user, gate_name) @@ -103,7 +103,7 @@ def manually_log_gate_exposure(user, gate_name) }) end - sig { params(user: StatsigUser, dynamic_config_name: String, options: Statsig::GetConfigOptions).returns(DynamicConfig) } + # sig { params(user: StatsigUser, dynamic_config_name: String, options: Statsig::GetConfigOptions).returns(DynamicConfig) } def get_config(user, dynamic_config_name, options = Statsig::GetConfigOptions.new) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { @@ -113,7 +113,7 @@ def get_config(user, dynamic_config_name, options = Statsig::GetConfigOptions.ne }, recover: -> { DynamicConfig.new(dynamic_config_name) }, caller: __method__.to_s) end - sig { params(user: StatsigUser, experiment_name: String, options: Statsig::GetExperimentOptions).returns(DynamicConfig) } + # sig { params(user: StatsigUser, experiment_name: String, options: Statsig::GetExperimentOptions).returns(DynamicConfig) } def get_experiment(user, experiment_name, options = Statsig::GetExperimentOptions.new) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { @@ -123,7 +123,7 @@ def get_experiment(user, experiment_name, options = Statsig::GetExperimentOption }, recover: -> { DynamicConfig.new(experiment_name) }, caller: __method__.to_s) end - sig { params(user: StatsigUser, config_name: String).void } + # sig { params(user: StatsigUser, config_name: String).void } def manually_log_config_exposure(user, config_name) @err_boundary.capture(task: lambda { res = @evaluator.get_config(user, config_name) @@ -132,7 +132,7 @@ def manually_log_config_exposure(user, config_name) }, caller: __method__.to_s) end - sig { params(user: StatsigUser, id_type: String).returns(Statsig::UserPersistedValues) } + # sig { params(user: StatsigUser, id_type: String).returns(Statsig::UserPersistedValues) } def get_user_persisted_values(user, id_type) @err_boundary.capture(task: lambda { persisted_values = @persistent_storage_utils.get_user_persisted_values(user, id_type) @@ -142,7 +142,7 @@ def get_user_persisted_values(user, id_type) }, caller: __method__.to_s) end - sig { params(user: StatsigUser, layer_name: String, options: Statsig::GetLayerOptions).returns(Layer) } + # sig { params(user: StatsigUser, layer_name: String, options: Statsig::GetLayerOptions).returns(Layer) } def get_layer(user, layer_name, options = Statsig::GetLayerOptions.new) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { @@ -161,7 +161,7 @@ def get_layer(user, layer_name, options = Statsig::GetLayerOptions.new) }, recover: lambda { Layer.new(layer_name) }, caller: __method__.to_s) end - sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void } + # sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void } def manually_log_layer_parameter_exposure(user, layer_name, parameter_name) @err_boundary.capture(task: lambda { res = @evaluator.get_layer(user, layer_name) @@ -200,35 +200,35 @@ def manually_sync_idlists }, caller: __method__.to_s) end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } def list_gates @err_boundary.capture(task: lambda { @evaluator.list_gates }, caller: __method__.to_s) end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } def list_configs @err_boundary.capture(task: lambda { @evaluator.list_configs }, caller: __method__.to_s) end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } def list_experiments @err_boundary.capture(task: lambda { @evaluator.list_experiments }, caller: __method__.to_s) end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } def list_autotunes @err_boundary.capture(task: lambda { @evaluator.list_autotunes }, caller: __method__.to_s) end - sig { returns(T::Array[String]) } + # sig { returns(T::Array[String]) } def list_layers @err_boundary.capture(task: lambda { @evaluator.list_layers @@ -297,7 +297,7 @@ def run_with_diagnostics(task:, caller:) return res end - sig { params(user: StatsigUser, config_name: String, variable_name: String).returns(StatsigUser) } + # sig { params(user: StatsigUser, config_name: String, variable_name: String).returns(StatsigUser) } def verify_inputs(user, config_name, variable_name) validate_user(user) if !config_name.is_a?(String) || config_name.empty? @@ -309,14 +309,14 @@ def verify_inputs(user, config_name, variable_name) normalize_user(user) end - sig do - params( - user: StatsigUser, - config_name: String, - disable_log_exposure: T::Boolean, - user_persisted_values: T.nilable(Statsig::UserPersistedValues) - ).returns(DynamicConfig) - end + # sig do + # params( + # user: StatsigUser, + # config_name: String, + # disable_log_exposure: T::Boolean, + # user_persisted_values: T.nilable(Statsig::UserPersistedValues) + # ).returns(DynamicConfig) + # end def get_config_impl(user, config_name, disable_log_exposure, user_persisted_values: nil) res = @evaluator.get_config(user, config_name, user_persisted_values: user_persisted_values) if res.nil? diff --git a/lib/statsig_errors.rb b/lib/statsig_errors.rb index c40c763..8c052e6 100644 --- a/lib/statsig_errors.rb +++ b/lib/statsig_errors.rb @@ -1,4 +1,4 @@ -# typed: true + module Statsig class UninitializedError < StandardError def initialize(msg="Must call initialize first.") diff --git a/lib/statsig_event.rb b/lib/statsig_event.rb index 4590c49..a9079a8 100644 --- a/lib/statsig_event.rb +++ b/lib/statsig_event.rb @@ -1,4 +1,4 @@ -# typed: true + class StatsigEvent attr_accessor :value, :metadata, :statsig_metadata, :secondary_exposures attr_reader :user diff --git a/lib/statsig_logger.rb b/lib/statsig_logger.rb index a950048..0c5a9ab 100644 --- a/lib/statsig_logger.rb +++ b/lib/statsig_logger.rb @@ -1,4 +1,4 @@ -# typed: true + require 'statsig_event' require 'concurrent-ruby' diff --git a/lib/statsig_options.rb b/lib/statsig_options.rb index 050f25c..9497ba1 100644 --- a/lib/statsig_options.rb +++ b/lib/statsig_options.rb @@ -1,142 +1,142 @@ -# typed: true -require 'sorbet-runtime' + +# require 'sorbet-runtime' require_relative 'interfaces/data_store' require_relative 'interfaces/user_persistent_storage' ## # Configuration options for the Statsig SDK. class StatsigOptions - extend T::Sig + # extend T::Sig - sig { returns(T.any(T::Hash[String, String], NilClass)) } + # sig { returns(T.any(T::Hash[String, String], NilClass)) } # Hash you can use to set environment variables that apply to all of your users in # the same session and will be used for targeting purposes. # eg. { "tier" => "development" } attr_accessor :environment - sig { returns(String) } + # sig { returns(String) } # The base url used to make network calls to Statsig. # default: https://statsigapi.net/v1 attr_accessor :api_url_base # The base url used specifically to call download_config_specs. # Takes precedence over api_url_base - sig { returns(String) } + # sig { returns(String) } attr_accessor :api_url_download_config_specs - sig { returns(T.any(Float, Integer)) } + # sig { returns(T.any(Float, Integer)) } # The interval (in seconds) to poll for changes to your Statsig configuration # default: 10s attr_accessor :rulesets_sync_interval - sig { returns(T.any(Float, Integer)) } + # sig { returns(T.any(Float, Integer)) } # The interval (in seconds) to poll for changes to your id lists # default: 60s attr_accessor :idlists_sync_interval # Disable background syncing for rulesets - sig { returns(T::Boolean) } + # sig { returns(T::Boolean) } attr_accessor :disable_rulesets_sync # Disable background syncing for id lists - sig { returns(T::Boolean) } + # sig { returns(T::Boolean) } attr_accessor :disable_idlists_sync - sig { returns(T.any(Float, Integer)) } + # sig { returns(T.any(Float, Integer)) } # How often to flush logs to Statsig # default: 60s attr_accessor :logging_interval_seconds - sig { returns(Integer) } + # sig { returns(Integer) } # The maximum number of events to batch before flushing logs to the server # default: 1000 attr_accessor :logging_max_buffer_size - sig { returns(T::Boolean) } + # sig { returns(T::Boolean) } # Restricts the SDK to not issue any network requests and only respond with default values (or local overrides) # default: false attr_accessor :local_mode - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # A string that represents all rules for all feature gates, dynamic configs and experiments. # It can be provided to bootstrap the Statsig server SDK at initialization in case your server runs # into network issue or Statsig is down temporarily. attr_accessor :bootstrap_values - sig { returns(T.any(Method, Proc, NilClass)) } + # sig { returns(T.any(Method, Proc, NilClass)) } # A callback function that will be called anytime the rulesets are updated. attr_accessor :rules_updated_callback - sig { returns(T.any(Statsig::Interfaces::IDataStore, NilClass)) } + # sig { returns(T.any(Statsig::Interfaces::IDataStore, NilClass)) } # A class that extends IDataStore. Can be used to provide values from a # common data store (like Redis) to initialize the Statsig SDK. attr_accessor :data_store - sig { returns(Integer) } + # sig { returns(Integer) } # The number of threads allocated to syncing IDLists. # default: 3 attr_accessor :idlist_threadpool_size - sig { returns(Integer) } + # sig { returns(Integer) } # The number of threads allocated to posting event logs. # default: 3 attr_accessor :logger_threadpool_size - sig { returns(T::Boolean) } + # sig { returns(T::Boolean) } # Should diagnostics be logged. These include performance metrics for initialize. # default: false attr_accessor :disable_diagnostics_logging - sig { returns(T::Boolean) } + # sig { returns(T::Boolean) } # Statsig utilizes Sorbet (https://sorbet.org) to ensure type safety of the SDK. This includes logging # to console when errors are detected. You can disable this logging by setting this flag to true. # default: false attr_accessor :disable_sorbet_logging_handlers - sig { returns(T.any(Integer, NilClass)) } + # sig { returns(T.any(Integer, NilClass)) } # Number of seconds before a network call is timed out attr_accessor :network_timeout - sig { returns(Integer) } + # sig { returns(Integer) } # Number of times to retry sending a batch of failed log events attr_accessor :post_logs_retry_limit - sig { returns(T.any(Method, Proc, Integer, NilClass)) } + # sig { returns(T.any(Method, Proc, Integer, NilClass)) } # The number of seconds, or a function that returns the number of seconds based on the number of retries remaining # which overrides the default backoff time between retries attr_accessor :post_logs_retry_backoff - sig { returns(T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass)) } + # sig { returns(T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass)) } # A storage adapter for persisted values. Can be used for sticky bucketing users in experiments. # Implements Statsig::Interfaces::IUserPersistentStorage. attr_accessor :user_persistent_storage - sig do - params( - environment: T.any(T::Hash[String, String], NilClass), - api_url_base: T.nilable(String), - api_url_download_config_specs: T.any(String, NilClass), - rulesets_sync_interval: T.any(Float, Integer), - idlists_sync_interval: T.any(Float, Integer), - disable_rulesets_sync: T::Boolean, - disable_idlists_sync: T::Boolean, - logging_interval_seconds: T.any(Float, Integer), - logging_max_buffer_size: Integer, - local_mode: T::Boolean, - bootstrap_values: T.any(String, NilClass), - rules_updated_callback: T.any(Method, Proc, NilClass), - data_store: T.any(Statsig::Interfaces::IDataStore, NilClass), - idlist_threadpool_size: Integer, - logger_threadpool_size: Integer, - disable_diagnostics_logging: T::Boolean, - disable_sorbet_logging_handlers: T::Boolean, - network_timeout: T.any(Integer, NilClass), - post_logs_retry_limit: Integer, - post_logs_retry_backoff: T.any(Method, Proc, Integer, NilClass), - user_persistent_storage: T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass) - ).void - end + # sig do + # params( + # environment: T.any(T::Hash[String, String], NilClass), + # api_url_base: T.nilable(String), + # api_url_download_config_specs: T.any(String, NilClass), + # rulesets_sync_interval: T.any(Float, Integer), + # idlists_sync_interval: T.any(Float, Integer), + # disable_rulesets_sync: T::Boolean, + # disable_idlists_sync: T::Boolean, + # logging_interval_seconds: T.any(Float, Integer), + # logging_max_buffer_size: Integer, + # local_mode: T::Boolean, + # bootstrap_values: T.any(String, NilClass), + # rules_updated_callback: T.any(Method, Proc, NilClass), + # data_store: T.any(Statsig::Interfaces::IDataStore, NilClass), + # idlist_threadpool_size: Integer, + # logger_threadpool_size: Integer, + # disable_diagnostics_logging: T::Boolean, + # disable_sorbet_logging_handlers: T::Boolean, + # network_timeout: T.any(Integer, NilClass), + # post_logs_retry_limit: Integer, + # post_logs_retry_backoff: T.any(Method, Proc, Integer, NilClass), + # user_persistent_storage: T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass) + # ).void + # end def initialize( environment = nil, api_url_base = nil, diff --git a/lib/statsig_user.rb b/lib/statsig_user.rb index d5bf997..945cc76 100644 --- a/lib/statsig_user.rb +++ b/lib/statsig_user.rb @@ -1,65 +1,65 @@ -# typed: true -require 'sorbet-runtime' + +# require 'sorbet-runtime' require 'json' ## # The user object to be evaluated against your Statsig configurations (gates/experiments/dynamic configs). class StatsigUser - extend T::Sig + # extend T::Sig - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # An identifier for this user. Evaluated against the User ID criteria. (https://docs.statsig.com/feature-gates/conditions#userid) attr_accessor :user_id - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # An identifier for this user. Evaluated against the Email criteria. (https://docs.statsig.com/feature-gates/conditions#email) attr_accessor :email - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # An IP address associated with this user. Evaluated against the IP Address criteria. (https://docs.statsig.com/feature-gates/conditions#ip) attr_accessor :ip - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # A user agent string associated with this user. Evaluated against Browser Version and Name (https://docs.statsig.com/feature-gates/conditions#browser-version) attr_accessor :user_agent - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # The country code associated with this user (e.g New Zealand => NZ). Evaluated against the Country criteria. (https://docs.statsig.com/feature-gates/conditions#country) attr_accessor :country - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # An locale for this user. attr_accessor :locale - sig { returns(T.any(String, NilClass)) } + # sig { returns(T.any(String, NilClass)) } # The current app version the user is interacting with. Evaluated against the App Version criteria. (https://docs.statsig.com/feature-gates/conditions#app-version) attr_accessor :app_version - sig { returns(T.any(T::Hash[String, String], NilClass)) } + # sig { returns(T.any(T::Hash[String, String], NilClass)) } # A Hash you can use to set environment variables that apply to this user. e.g. { "tier" => "development" } attr_accessor :statsig_environment - sig { returns(T.any(T::Hash[String, String], NilClass)) } + # sig { returns(T.any(T::Hash[String, String], NilClass)) } # Any Custom IDs to associated with the user. (See https://docs.statsig.com/guides/experiment-on-custom-id-types) attr_accessor :custom_ids - sig { returns(T.any(T::Hash[String, String], NilClass)) } + # sig { returns(T.any(T::Hash[String, String], NilClass)) } # Any value you wish to use in evaluation, but do not want logged with events, can be stored in this field. attr_accessor :private_attributes - sig { returns(T.any(T::Hash[String, T.untyped], NilClass)) } + # sig { returns(T.any(T::Hash[String, T.untyped], NilClass)) } def custom @custom end - sig { params(value: T.any(T::Hash[String, T.untyped], NilClass)).void } + # sig { params(value: T.any(T::Hash[String, T.untyped], NilClass)).void } # Any custom fields for this user. Evaluated against the Custom criteria. (https://docs.statsig.com/feature-gates/conditions#custom) def custom=(value) @custom = value.is_a?(Hash) ? value : Hash.new end - sig { params(user_hash: T.any(T::Hash[T.any(String, Symbol), T.untyped], NilClass)).void } + # sig { params(user_hash: T.any(T::Hash[T.any(String, Symbol), T.untyped], NilClass)).void } def initialize(user_hash) the_hash = user_hash begin @@ -175,12 +175,12 @@ def get_unit_id(id_type) private - sig { - params(user_hash: T.any(T::Hash[T.any(String, Symbol), T.untyped], NilClass), - keys: T::Array[Symbol], - type: T.untyped) - .returns(T.untyped) - } + # sig { + # params(user_hash: T.any(T::Hash[T.any(String, Symbol), T.untyped], NilClass), + # keys: T::Array[Symbol], + # type: T.untyped) + # .returns(T.untyped) + # } # Pulls fields from the user hash via Symbols and Strings def from_hash(user_hash, keys, type) if user_hash.nil? diff --git a/lib/ua_parser.rb b/lib/ua_parser.rb index 19720a8..6db9c7f 100644 --- a/lib/ua_parser.rb +++ b/lib/ua_parser.rb @@ -1,4 +1,4 @@ -# typed: true + require 'user_agent_parser' module UAParser diff --git a/lib/uri_helper.rb b/lib/uri_helper.rb index edaeaa4..0b14aae 100644 --- a/lib/uri_helper.rb +++ b/lib/uri_helper.rb @@ -1,24 +1,24 @@ -# typed: true -require 'sorbet-runtime' + +# require 'sorbet-runtime' class URIHelper class URIBuilder - extend T::Sig + # extend T::Sig - sig { returns(StatsigOptions) } + # sig { returns(StatsigOptions) } attr_accessor :options - sig { params(options: StatsigOptions).void } + # sig { params(options: StatsigOptions).void } def initialize(options) @options = options end - sig { params(endpoint: String).returns(String) } + # sig { params(endpoint: String).returns(String) } def build_url(endpoint) api = @options.api_url_base if endpoint.include?('download_config_specs') - api = T.must(@options.api_url_download_config_specs) + api = @options.api_url_download_config_specs end unless api.end_with?('/') api += '/' diff --git a/lib/user_persistent_storage_utils.rb b/lib/user_persistent_storage_utils.rb index a095a7b..c8f268f 100644 --- a/lib/user_persistent_storage_utils.rb +++ b/lib/user_persistent_storage_utils.rb @@ -1,27 +1,27 @@ -# typed: false -require 'sorbet-runtime' + +# require 'sorbet-runtime' require 'statsig_options' module Statsig - UserPersistedValues = T.type_alias { T::Hash[String, Hash] } + # UserPersistedValues = T.type_alias { T::Hash[String, Hash] } class UserPersistentStorageUtils - extend T::Sig + # extend T::Sig - sig { returns(T::Hash[String, UserPersistedValues]) } + # sig { returns(T::Hash[String, UserPersistedValues]) } attr_accessor :cache - sig { returns(T.nilable(Interfaces::IUserPersistentStorage)) } + # sig { returns(T.nilable(Interfaces::IUserPersistentStorage)) } attr_accessor :storage - sig { params(options: StatsigOptions).void } + # sig { params(options: StatsigOptions).void } def initialize(options) @storage = options.user_persistent_storage @cache = {} end - sig { params(user: StatsigUser, id_type: String).returns(T.nilable(UserPersistedValues)) } + # sig { params(user: StatsigUser, id_type: String).returns(T.nilable(UserPersistedValues)) } def get_user_persisted_values(user, id_type) key = self.class.get_storage_key(user, id_type) return @cache[key] unless @cache[key].nil? @@ -29,7 +29,7 @@ def get_user_persisted_values(user, id_type) return load_from_storage(key) end - sig { params(key: String).returns(T.nilable(UserPersistedValues)) } + # sig { params(key: String).returns(T.nilable(UserPersistedValues)) } def load_from_storage(key) return if @storage.nil? @@ -50,7 +50,7 @@ def load_from_storage(key) return nil end - sig { params(user: StatsigUser, id_type: String, user_persisted_values: UserPersistedValues).void } + # sig { params(user: StatsigUser, id_type: String, user_persisted_values: UserPersistedValues).void } def save_to_storage(user, id_type, user_persisted_values) return if @storage.nil? @@ -65,7 +65,7 @@ def save_to_storage(user, id_type, user_persisted_values) end end - sig { params(user: StatsigUser, id_type: String, config_name: String).void } + # sig { params(user: StatsigUser, id_type: String, config_name: String).void } def remove_experiment_from_storage(user, id_type, config_name) persisted_values = get_user_persisted_values(user, id_type) unless persisted_values.nil? @@ -74,7 +74,7 @@ def remove_experiment_from_storage(user, id_type, config_name) end end - sig { params(user_persisted_values: T.nilable(UserPersistedValues), config_name: String, evaluation: ConfigResult).void } + # sig { params(user_persisted_values: T.nilable(UserPersistedValues), config_name: String, evaluation: ConfigResult).void } def add_evaluation_to_user_persisted_values(user_persisted_values, config_name, evaluation) if user_persisted_values.nil? user_persisted_values = {} @@ -84,21 +84,21 @@ def add_evaluation_to_user_persisted_values(user_persisted_values, config_name, private - sig { params(values_string: String).returns(T.nilable(UserPersistedValues)) } + # sig { params(values_string: String).returns(T.nilable(UserPersistedValues)) } def self.parse(values_string) return JSON.parse(values_string) rescue JSON::ParserError return nil end - sig { params(values_object: UserPersistedValues).returns(T.nilable(String)) } + # sig { params(values_object: UserPersistedValues).returns(T.nilable(String)) } def self.stringify(values_object) return JSON.generate(values_object) rescue StandardError return nil end - sig { params(user: StatsigUser, id_type: String).returns(String) } + # sig { params(user: StatsigUser, id_type: String).returns(String) } def self.get_storage_key(user, id_type) "#{user.get_unit_id(id_type)}:#{id_type}" end diff --git a/sorbet/config b/sorbet/config deleted file mode 100644 index 9e768f2..0000000 --- a/sorbet/config +++ /dev/null @@ -1,4 +0,0 @@ ---dir -. ---ignore -vendor/,test/ diff --git a/sorbet/rbi/annotations/webmock.rbi b/sorbet/rbi/annotations/webmock.rbi deleted file mode 100644 index f6b9c03..0000000 --- a/sorbet/rbi/annotations/webmock.rbi +++ /dev/null @@ -1,9 +0,0 @@ -# typed: strict - -# DO NOT EDIT MANUALLY -# This file was pulled from a central RBI files repository. -# Please run `bin/tapioca annotations` to update it. - -class Minitest::Test - include WebMock::API -end diff --git a/sorbet/rbi/gems/addressable.rbi b/sorbet/rbi/gems/addressable.rbi deleted file mode 100644 index 5e12ae4..0000000 --- a/sorbet/rbi/gems/addressable.rbi +++ /dev/null @@ -1,204 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/addressable/all/addressable.rbi -# -# addressable-2.8.1 - -module Addressable -end -module Addressable::VERSION -end -module Addressable::IDNA - def self.lookup_unicode_combining_class(codepoint); end - def self.lookup_unicode_compatibility(codepoint); end - def self.lookup_unicode_composition(unpacked); end - def self.lookup_unicode_lowercase(codepoint); end - def self.punycode_adapt(delta, numpoints, firsttime); end - def self.punycode_basic?(codepoint); end - def self.punycode_decode(punycode); end - def self.punycode_decode_digit(codepoint); end - def self.punycode_delimiter?(codepoint); end - def self.punycode_encode(unicode); end - def self.punycode_encode_digit(d); end - def self.to_ascii(input); end - def self.to_unicode(input); end - def self.ucs4_to_utf8(char, buffer); end - def self.unicode_compose(unpacked); end - def self.unicode_compose_pair(ch_one, ch_two); end - def self.unicode_decompose(unpacked); end - def self.unicode_decompose_hangul(codepoint); end - def self.unicode_downcase(input); end - def self.unicode_normalize_kc(input); end - def self.unicode_sort_canonical(unpacked); end -end -class Addressable::IDNA::PunycodeBadInput < StandardError -end -class Addressable::IDNA::PunycodeBigOutput < StandardError -end -class Addressable::IDNA::PunycodeOverflow < StandardError -end -class Addressable::URI - def +(uri); end - def ==(uri); end - def ===(uri); end - def absolute?; end - def authority; end - def authority=(new_authority); end - def basename; end - def default_port; end - def defer_validation; end - def display_uri; end - def domain; end - def dup; end - def empty?; end - def eql?(uri); end - def extname; end - def force_utf8_encoding_if_needed(str); end - def fragment; end - def fragment=(new_fragment); end - def freeze; end - def hash; end - def host; end - def host=(new_host); end - def hostname; end - def hostname=(new_hostname); end - def inferred_port; end - def initialize(options = nil); end - def inspect; end - def ip_based?; end - def join!(uri); end - def join(uri); end - def merge!(uri); end - def merge(hash); end - def normalize!; end - def normalize; end - def normalized_authority; end - def normalized_fragment; end - def normalized_host; end - def normalized_password; end - def normalized_path; end - def normalized_port; end - def normalized_query(*flags); end - def normalized_scheme; end - def normalized_site; end - def normalized_user; end - def normalized_userinfo; end - def omit!(*components); end - def omit(*components); end - def origin; end - def origin=(new_origin); end - def password; end - def password=(new_password); end - def path; end - def path=(new_path); end - def port; end - def port=(new_port); end - def query; end - def query=(new_query); end - def query_values(return_type = nil); end - def query_values=(new_query_values); end - def relative?; end - def remove_composite_values; end - def replace_self(uri); end - def request_uri; end - def request_uri=(new_request_uri); end - def route_from(uri); end - def route_to(uri); end - def scheme; end - def scheme=(new_scheme); end - def self.convert_path(path); end - def self.encode(uri, return_type = nil); end - def self.encode_component(component, character_class = nil, upcase_encoded = nil); end - def self.escape(uri, return_type = nil); end - def self.escape_component(component, character_class = nil, upcase_encoded = nil); end - def self.form_encode(form_values, sort = nil); end - def self.form_unencode(encoded_value); end - def self.heuristic_parse(uri, hints = nil); end - def self.ip_based_schemes; end - def self.join(*uris); end - def self.normalize_component(component, character_class = nil, leave_encoded = nil); end - def self.normalize_path(path); end - def self.normalized_encode(uri, return_type = nil); end - def self.parse(uri); end - def self.port_mapping; end - def self.unencode(uri, return_type = nil, leave_encoded = nil); end - def self.unencode_component(uri, return_type = nil, leave_encoded = nil); end - def self.unescape(uri, return_type = nil, leave_encoded = nil); end - def self.unescape_component(uri, return_type = nil, leave_encoded = nil); end - def site; end - def site=(new_site); end - def split_path(path); end - def tld; end - def tld=(new_tld); end - def to_hash; end - def to_s; end - def to_str; end - def user; end - def user=(new_user); end - def userinfo; end - def userinfo=(new_userinfo); end - def validate; end -end -class Addressable::URI::InvalidURIError < StandardError -end -module Addressable::URI::CharacterClasses -end -module Addressable::URI::NormalizeCharacterClasses -end -class Addressable::Template - def ==(template); end - def eql?(template); end - def expand(mapping, processor = nil, normalize_values = nil); end - def extract(uri, processor = nil); end - def freeze; end - def initialize(pattern); end - def inspect; end - def join_values(operator, return_value); end - def keys; end - def match(uri, processor = nil); end - def named_captures; end - def names; end - def normalize_keys(mapping); end - def normalize_value(value); end - def ordered_variable_defaults; end - def parse_new_template_pattern(pattern, processor = nil); end - def parse_template_pattern(pattern, processor = nil); end - def partial_expand(mapping, processor = nil, normalize_values = nil); end - def pattern; end - def source; end - def to_regexp; end - def transform_capture(mapping, capture, processor = nil, normalize_values = nil); end - def transform_partial_capture(mapping, capture, processor = nil, normalize_values = nil); end - def variable_defaults; end - def variables; end -end -class Addressable::Template::InvalidTemplateValueError < StandardError -end -class Addressable::Template::InvalidTemplateOperatorError < StandardError -end -class Addressable::Template::TemplateOperatorAbortedError < StandardError -end -class Addressable::Template::MatchData - def [](key, len = nil); end - def captures; end - def initialize(uri, template, mapping); end - def inspect; end - def keys; end - def mapping; end - def names; end - def post_match; end - def pre_match; end - def string; end - def template; end - def to_a; end - def to_s; end - def uri; end - def values; end - def values_at(*indexes); end - def variables; end -end diff --git a/sorbet/rbi/gems/concurrent-ruby.rbi b/sorbet/rbi/gems/concurrent-ruby.rbi deleted file mode 100644 index 2aa4dd8..0000000 --- a/sorbet/rbi/gems/concurrent-ruby.rbi +++ /dev/null @@ -1,1662 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: true -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/concurrent-ruby/all/concurrent-ruby.rbi -# -# concurrent-ruby-1.1.10 - -module Concurrent - def abort_transaction; end - def atomically; end - def call_dataflow(method, executor, *inputs, &block); end - def dataflow!(*inputs, &block); end - def dataflow(*inputs, &block); end - def dataflow_with!(executor, *inputs, &block); end - def dataflow_with(executor, *inputs, &block); end - def leave_transaction; end - def monotonic_time(unit = nil); end - def self.abort_transaction; end - def self.atomically; end - def self.call_dataflow(method, executor, *inputs, &block); end - def self.create_simple_logger(level = nil, output = nil); end - def self.create_stdlib_logger(level = nil, output = nil); end - def self.dataflow!(*inputs, &block); end - def self.dataflow(*inputs, &block); end - def self.dataflow_with!(executor, *inputs, &block); end - def self.dataflow_with(executor, *inputs, &block); end - def self.disable_at_exit_handlers!; end - def self.executor(executor_identifier); end - def self.global_fast_executor; end - def self.global_immediate_executor; end - def self.global_io_executor; end - def self.global_logger; end - def self.global_logger=(value); end - def self.global_timer_set; end - def self.leave_transaction; end - def self.monotonic_time(unit = nil); end - def self.new_fast_executor(opts = nil); end - def self.new_io_executor(opts = nil); end - def self.physical_processor_count; end - def self.processor_count; end - def self.processor_counter; end - def self.use_simple_logger(level = nil, output = nil); end - def self.use_stdlib_logger(level = nil, output = nil); end - extend Concurrent::Concern::Deprecation - extend Concurrent::Concern::Logging - extend Concurrent::Utility::EngineDetector - extend Concurrent::Utility::NativeExtensionLoader -end -class Concurrent::Error < StandardError -end -class Concurrent::ConfigurationError < Concurrent::Error -end -class Concurrent::CancelledOperationError < Concurrent::Error -end -class Concurrent::LifecycleError < Concurrent::Error -end -class Concurrent::ImmutabilityError < Concurrent::Error -end -class Concurrent::IllegalOperationError < Concurrent::Error -end -class Concurrent::InitializationError < Concurrent::Error -end -class Concurrent::MaxRestartFrequencyError < Concurrent::Error -end -class Concurrent::MultipleAssignmentError < Concurrent::Error - def initialize(message = nil, inspection_data = nil); end - def inspect; end - def inspection_data; end -end -class Concurrent::RejectedExecutionError < Concurrent::Error -end -class Concurrent::ResourceLimitError < Concurrent::Error -end -class Concurrent::TimeoutError < Concurrent::Error -end -class Concurrent::MultipleErrors < Concurrent::Error - def errors; end - def initialize(errors, message = nil); end -end -module Concurrent::Utility -end -module Concurrent::Utility::EngineDetector - def on_cruby?; end - def on_jruby?; end - def on_jruby_9000?; end - def on_linux?; end - def on_osx?; end - def on_rbx?; end - def on_truffleruby?; end - def on_windows?; end - def ruby_engine; end - def ruby_version(version = nil, comparison, major, minor, patch); end -end -module Concurrent::Synchronization -end -class Concurrent::Synchronization::AbstractObject - def full_memory_barrier; end - def initialize; end - def self.attr_volatile(*names); end -end -module Concurrent::Utility::NativeExtensionLoader - def allow_c_extensions?; end - def c_extensions_loaded?; end - def java_extensions_loaded?; end - def load_error_path(error); end - def load_native_extensions; end - def set_c_extensions_loaded; end - def set_java_extensions_loaded; end - def try_load_c_extension(path); end -end -module Concurrent::Synchronization::MriAttrVolatile - def full_memory_barrier; end - def self.included(base); end -end -module Concurrent::Synchronization::MriAttrVolatile::ClassMethods - def attr_volatile(*names); end -end -class Concurrent::Synchronization::MriObject < Concurrent::Synchronization::AbstractObject - def initialize; end - extend Concurrent::Synchronization::MriAttrVolatile::ClassMethods - include Concurrent::Synchronization::MriAttrVolatile -end -module Concurrent::Synchronization::RbxAttrVolatile - def full_memory_barrier; end - def self.included(base); end -end -module Concurrent::Synchronization::RbxAttrVolatile::ClassMethods - def attr_volatile(*names); end -end -class Concurrent::Synchronization::RbxObject < Concurrent::Synchronization::AbstractObject - def initialize; end - extend Concurrent::Synchronization::RbxAttrVolatile::ClassMethods - include Concurrent::Synchronization::RbxAttrVolatile -end -module Concurrent::Synchronization::TruffleRubyAttrVolatile - def full_memory_barrier; end - def self.included(base); end -end -module Concurrent::Synchronization::TruffleRubyAttrVolatile::ClassMethods - def attr_volatile(*names); end -end -class Concurrent::Synchronization::TruffleRubyObject < Concurrent::Synchronization::AbstractObject - def initialize; end - extend Concurrent::Synchronization::TruffleRubyAttrVolatile::ClassMethods - include Concurrent::Synchronization::TruffleRubyAttrVolatile -end -class Concurrent::Synchronization::Object < Concurrent::Synchronization::MriObject - def __initialize_atomic_fields__; end - def initialize; end - def self.atomic_attribute?(name); end - def self.atomic_attributes(inherited = nil); end - def self.attr_atomic(*names); end - def self.define_initialize_atomic_fields; end - def self.ensure_safe_initialization_when_final_fields_are_present; end - def self.safe_initialization!; end - def self.safe_initialization?; end -end -class Concurrent::Synchronization::AbstractLockableObject < Concurrent::Synchronization::Object - def ns_broadcast; end - def ns_signal; end - def ns_wait(timeout = nil); end - def ns_wait_until(timeout = nil, &condition); end - def synchronize; end -end -module Concurrent::Synchronization::ConditionSignalling - def ns_broadcast; end - def ns_signal; end -end -class Concurrent::Synchronization::MutexLockableObject < Concurrent::Synchronization::AbstractLockableObject - def initialize(*defaults); end - def initialize_copy(other); end - def ns_wait(timeout = nil); end - def self.new(*args, &block); end - def synchronize; end - include Concurrent::Synchronization::ConditionSignalling -end -class Concurrent::Synchronization::MonitorLockableObject < Concurrent::Synchronization::AbstractLockableObject - def initialize(*defaults); end - def initialize_copy(other); end - def ns_wait(timeout = nil); end - def self.new(*args, &block); end - def synchronize; end - include Concurrent::Synchronization::ConditionSignalling -end -class Concurrent::Synchronization::RbxLockableObject < Concurrent::Synchronization::AbstractLockableObject - def initialize(*defaults); end - def initialize_copy(other); end - def ns_broadcast; end - def ns_signal; end - def ns_wait(timeout = nil); end - def self.new(*args, &block); end - def synchronize(&block); end -end -class Concurrent::Synchronization::LockableObject < Concurrent::Synchronization::MutexLockableObject - def new_condition; end -end -class Concurrent::Synchronization::Condition < Concurrent::Synchronization::LockableObject - def broadcast; end - def initialize(lock); end - def ns_broadcast; end - def ns_signal; end - def ns_wait(timeout = nil); end - def ns_wait_until(timeout = nil, &condition); end - def self.new(*args, &block); end - def self.private_new(*args, &block); end - def signal; end - def wait(timeout = nil); end - def wait_until(timeout = nil, &condition); end -end -class Concurrent::Synchronization::Lock < Concurrent::Synchronization::LockableObject - def broadcast; end - def ns_broadcast; end - def ns_signal; end - def ns_wait(timeout = nil); end - def ns_wait_until(timeout = nil, &condition); end - def signal; end - def synchronize; end - def wait(timeout = nil); end - def wait_until(timeout = nil, &condition); end -end -class Concurrent::Event < Concurrent::Synchronization::LockableObject - def initialize; end - def ns_initialize; end - def ns_set; end - def reset; end - def set; end - def set?; end - def try?; end - def wait(timeout = nil); end -end -module Concurrent::Concern -end -module Concurrent::Concern::Dereferenceable - def apply_deref_options(value); end - def deref; end - def ns_set_deref_options(opts); end - def set_deref_options(opts = nil); end - def value; end - def value=(value); end -end -module Concurrent::Concern::Obligation - def compare_and_set_state(next_state, *expected_current); end - def complete?; end - def event; end - def exception(*args); end - def fulfilled?; end - def get_arguments_from(opts = nil); end - def if_state(*expected_states); end - def incomplete?; end - def init_obligation; end - def no_error!(timeout = nil); end - def ns_check_state?(expected); end - def ns_set_state(value); end - def pending?; end - def realized?; end - def reason; end - def rejected?; end - def set_state(success, value, reason); end - def state; end - def state=(value); end - def unscheduled?; end - def value!(timeout = nil); end - def value(timeout = nil); end - def wait!(timeout = nil); end - def wait(timeout = nil); end - include Concurrent::Concern::Dereferenceable -end -module Concurrent::Concern::Logging - def log(level, progname, message = nil, &block); end - include Logger::Severity -end -module Concurrent::Concern::Deprecation - def deprecated(message, strip = nil); end - def deprecated_method(old_name, new_name); end - extend Concurrent::Concern::Deprecation - include Concurrent::Concern::Logging -end -module Concurrent::ExecutorService - def <<(task); end - def can_overflow?; end - def post(*args, &task); end - def serialized?; end - include Concurrent::Concern::Logging -end -class Concurrent::AbstractExecutorService < Concurrent::Synchronization::LockableObject - def auto_terminate=(value); end - def auto_terminate?; end - def fallback_action(*args); end - def fallback_policy; end - def initialize(opts = nil, &block); end - def kill; end - def name; end - def ns_auto_terminate?; end - def ns_execute(*args, &task); end - def ns_kill_execution; end - def ns_shutdown_execution; end - def running?; end - def shutdown; end - def shutdown?; end - def shuttingdown?; end - def to_s; end - def wait_for_termination(timeout = nil); end - include Concurrent::Concern::Deprecation - include Concurrent::ExecutorService -end -module Concurrent::SerialExecutorService - def serialized?; end - include Concurrent::ExecutorService -end -class Concurrent::ImmediateExecutor < Concurrent::AbstractExecutorService - def <<(task); end - def initialize; end - def kill; end - def post(*args, &task); end - def running?; end - def shutdown; end - def shutdown?; end - def shuttingdown?; end - def wait_for_termination(timeout = nil); end - include Concurrent::SerialExecutorService -end -class Concurrent::Delay < Concurrent::Synchronization::LockableObject - def execute_task_once; end - def initialize(opts = nil, &block); end - def ns_initialize(opts, &block); end - def reconfigure(&block); end - def value!(timeout = nil); end - def value(timeout = nil); end - def wait(timeout = nil); end - include Concurrent::Concern::Obligation -end -module Concurrent::AtomicNumericCompareAndSetWrapper - def compare_and_set(old_value, new_value); end -end -class Concurrent::MutexAtomicReference < Concurrent::Synchronization::LockableObject - def _compare_and_set(old_value, new_value); end - def compare_and_swap(old_value, new_value); end - def get; end - def get_and_set(new_value); end - def initialize(value = nil); end - def ns_initialize(value); end - def set(new_value); end - def swap(new_value); end - def value; end - def value=(new_value); end - include Concurrent::AtomicDirectUpdate - include Concurrent::AtomicNumericCompareAndSetWrapper -end -module Concurrent::AtomicDirectUpdate - def try_update!; end - def try_update; end - def update; end -end -class Concurrent::ConcurrentUpdateError < ThreadError -end -class Concurrent::AtomicReference < Concurrent::MutexAtomicReference - def inspect; end - def to_s; end -end -class Concurrent::RubyExecutorService < Concurrent::AbstractExecutorService - def initialize(*args, &block); end - def kill; end - def ns_running?; end - def ns_shutdown?; end - def ns_shutdown_execution; end - def ns_shuttingdown?; end - def post(*args, &task); end - def shutdown; end - def stop_event; end - def stopped_event; end - def wait_for_termination(timeout = nil); end -end -class Concurrent::RubyThreadPoolExecutor < Concurrent::RubyExecutorService - def can_overflow?; end - def completed_task_count; end - def idletime; end - def initialize(opts = nil); end - def largest_length; end - def length; end - def max_length; end - def max_queue; end - def min_length; end - def ns_add_busy_worker; end - def ns_assign_worker(*args, &task); end - def ns_enqueue(*args, &task); end - def ns_execute(*args, &task); end - def ns_initialize(opts); end - def ns_kill_execution; end - def ns_limited_queue?; end - def ns_prune_pool; end - def ns_ready_worker(worker, last_message, success = nil); end - def ns_remove_busy_worker(worker); end - def ns_reset_if_forked; end - def ns_shutdown_execution; end - def ns_worker_died(worker); end - def prune_pool; end - def queue_length; end - def ready_worker(worker, last_message); end - def remaining_capacity; end - def remove_busy_worker(worker); end - def scheduled_task_count; end - def synchronous; end - def worker_died(worker); end - def worker_task_completed; end -end -class Concurrent::RubyThreadPoolExecutor::Worker - def <<(message); end - def create_worker(queue, pool, idletime); end - def initialize(pool, id); end - def kill; end - def run_task(pool, task, args); end - def stop; end - include Concurrent::Concern::Logging -end -class Concurrent::ThreadPoolExecutor < Concurrent::RubyThreadPoolExecutor -end -class Concurrent::CachedThreadPool < Concurrent::ThreadPoolExecutor - def initialize(opts = nil); end - def ns_initialize(opts); end -end -class Concurrent::Utility::ProcessorCounter - def compute_physical_processor_count; end - def compute_processor_count; end - def initialize; end - def physical_processor_count; end - def processor_count; end -end -class Concurrent::MutexAtomicBoolean < Concurrent::Synchronization::LockableObject - def false?; end - def initialize(initial = nil); end - def make_false; end - def make_true; end - def ns_initialize(initial); end - def ns_make_value(value); end - def true?; end - def value; end - def value=(value); end -end -class Concurrent::AtomicBoolean < Concurrent::MutexAtomicBoolean - def inspect; end - def to_s; end -end -module Concurrent::Utility::NativeInteger - def ensure_integer(value); end - def ensure_integer_and_bounds(value); end - def ensure_lower_bound(value); end - def ensure_positive(value); end - def ensure_positive_and_no_zero(value); end - def ensure_upper_bound(value); end - extend Concurrent::Utility::NativeInteger -end -class Concurrent::MutexAtomicFixnum < Concurrent::Synchronization::LockableObject - def compare_and_set(expect, update); end - def decrement(delta = nil); end - def down(delta = nil); end - def increment(delta = nil); end - def initialize(initial = nil); end - def ns_initialize(initial); end - def ns_set(value); end - def up(delta = nil); end - def update; end - def value; end - def value=(value); end -end -class Concurrent::AtomicFixnum < Concurrent::MutexAtomicFixnum - def inspect; end - def to_s; end -end -class Concurrent::CyclicBarrier < Concurrent::Synchronization::LockableObject - def broken?; end - def initialize(parties, &block); end - def ns_generation_done(generation, status, continue = nil); end - def ns_initialize(parties, &block); end - def ns_next_generation; end - def number_waiting; end - def parties; end - def reset; end - def wait(timeout = nil); end -end -class Concurrent::CyclicBarrier::Generation < Struct - def self.[](*arg0); end - def self.inspect; end - def self.keyword_init?; end - def self.members; end - def self.new(*arg0); end - def status; end - def status=(_); end -end -class Concurrent::MutexCountDownLatch < Concurrent::Synchronization::LockableObject - def count; end - def count_down; end - def initialize(count = nil); end - def ns_initialize(count); end - def wait(timeout = nil); end -end -class Concurrent::CountDownLatch < Concurrent::MutexCountDownLatch -end -class Concurrent::ReadWriteLock < Concurrent::Synchronization::Object - def acquire_read_lock; end - def acquire_write_lock; end - def has_waiters?; end - def initialize; end - def max_readers?(c = nil); end - def max_writers?(c = nil); end - def release_read_lock; end - def release_write_lock; end - def running_readers(c = nil); end - def running_readers?(c = nil); end - def running_writer?(c = nil); end - def self.new(*args, &block); end - def waiting_writer?(c = nil); end - def waiting_writers(c = nil); end - def with_read_lock; end - def with_write_lock; end - def write_locked?; end -end -class Concurrent::AbstractThreadLocalVar - def allocate_storage; end - def bind(value, &block); end - def default; end - def initialize(default = nil, &default_block); end - def value; end - def value=(value); end -end -class Concurrent::RubyThreadLocalVar < Concurrent::AbstractThreadLocalVar - def allocate_storage; end - def get_default; end - def get_threadlocal_array(thread = nil); end - def next_index; end - def self.semi_sync(&block); end - def self.thread_finalizer(id); end - def self.thread_local_finalizer(index); end - def set_threadlocal_array(array, thread = nil); end - def value; end - def value=(value); end - def value_for(thread); end -end -class Concurrent::ThreadLocalVar < Concurrent::RubyThreadLocalVar -end -class Concurrent::ReentrantReadWriteLock < Concurrent::Synchronization::Object - def acquire_read_lock; end - def acquire_write_lock; end - def initialize; end - def max_readers?(c = nil); end - def max_writers?(c = nil); end - def release_read_lock; end - def release_write_lock; end - def running_readers(c = nil); end - def running_readers?(c = nil); end - def running_writer?(c = nil); end - def self.new(*args, &block); end - def try_read_lock; end - def try_write_lock; end - def waiting_or_running_writer?(c = nil); end - def waiting_writers(c = nil); end - def with_read_lock; end - def with_write_lock; end -end -class Concurrent::MutexSemaphore < Concurrent::Synchronization::LockableObject - def acquire(permits = nil); end - def available_permits; end - def drain_permits; end - def initialize(count); end - def ns_initialize(count); end - def reduce_permits(reduction); end - def release(permits = nil); end - def try_acquire(permits = nil, timeout = nil); end - def try_acquire_now(permits); end - def try_acquire_timed(permits, timeout); end -end -class Concurrent::Semaphore < Concurrent::MutexSemaphore -end -class Concurrent::FixedThreadPool < Concurrent::ThreadPoolExecutor - def initialize(num_threads, opts = nil); end -end -class Concurrent::SimpleExecutorService < Concurrent::RubyExecutorService - def <<(task); end - def kill; end - def ns_initialize(*args); end - def post(*args, &task); end - def running?; end - def self.<<(task); end - def self.post(*args); end - def shutdown; end - def shutdown?; end - def shuttingdown?; end - def wait_for_termination(timeout = nil); end -end -class Concurrent::IndirectImmediateExecutor < Concurrent::ImmediateExecutor - def initialize; end - def post(*args, &task); end -end -class Concurrent::RubySingleThreadExecutor < Concurrent::RubyThreadPoolExecutor - def initialize(opts = nil); end -end -class Concurrent::SafeTaskExecutor < Concurrent::Synchronization::LockableObject - def execute(*args); end - def initialize(task, opts = nil); end -end -class Concurrent::SerializedExecution < Concurrent::Synchronization::LockableObject - def call_job(job); end - def initialize; end - def ns_initialize; end - def post(executor, *args, &task); end - def posts(posts); end - def work(job); end - include Concurrent::Concern::Logging -end -class Concurrent::SerializedExecution::Job < Struct - def args; end - def args=(_); end - def block; end - def block=(_); end - def call; end - def executor; end - def executor=(_); end - def self.[](*arg0); end - def self.inspect; end - def self.keyword_init?; end - def self.members; end - def self.new(*arg0); end -end -class Concurrent::SerializedExecutionDelegator < SimpleDelegator - def initialize(executor); end - def post(*args, &task); end - include Concurrent::SerialExecutorService -end -class Concurrent::SingleThreadExecutor < Concurrent::RubySingleThreadExecutor -end -module Concurrent::Collection -end -class Concurrent::Collection::CopyOnWriteObserverSet < Concurrent::Synchronization::LockableObject - def add_observer(observer = nil, func = nil, &block); end - def clear_observers_and_return_old; end - def count_observers; end - def delete_observer(observer); end - def delete_observers; end - def initialize; end - def notify_and_delete_observers(*args, &block); end - def notify_observers(*args, &block); end - def notify_to(observers, *args); end - def ns_initialize; end - def observers; end - def observers=(new_set); end -end -class Concurrent::Collection::CopyOnNotifyObserverSet < Concurrent::Synchronization::LockableObject - def add_observer(observer = nil, func = nil, &block); end - def count_observers; end - def delete_observer(observer); end - def delete_observers; end - def duplicate_and_clear_observers; end - def duplicate_observers; end - def initialize; end - def notify_and_delete_observers(*args, &block); end - def notify_observers(*args, &block); end - def notify_to(observers, *args); end - def ns_initialize; end -end -module Concurrent::Concern::Observable - def add_observer(observer = nil, func = nil, &block); end - def count_observers; end - def delete_observer(observer); end - def delete_observers; end - def observers; end - def observers=(arg0); end - def with_observer(observer = nil, func = nil, &block); end -end -class Concurrent::IVar < Concurrent::Synchronization::LockableObject - def add_observer(observer = nil, func = nil, &block); end - def check_for_block_or_value!(block_given, value); end - def complete(success, value, reason); end - def complete_without_notification(success, value, reason); end - def fail(reason = nil); end - def initialize(value = nil, opts = nil, &block); end - def notify_observers(value, reason); end - def ns_complete_without_notification(success, value, reason); end - def ns_initialize(value, opts); end - def safe_execute(task, args = nil); end - def set(value = nil); end - def try_set(value = nil, &block); end - include Concurrent::Concern::Obligation - include Concurrent::Concern::Observable -end -module Concurrent::Options - def self.executor(executor_identifier); end - def self.executor_from_options(opts = nil); end -end -class Concurrent::ScheduledTask < Concurrent::IVar - def <=>(other); end - def cancel; end - def cancelled?; end - def execute; end - def executor; end - def fail(reason = nil); end - def initial_delay; end - def initialize(delay, opts = nil, &task); end - def ns_reschedule(delay); end - def ns_schedule(delay); end - def process_task; end - def processing?; end - def reschedule(delay); end - def reset; end - def schedule_time; end - def self.execute(delay, opts = nil, &task); end - def set(value = nil); end - def try_set(value = nil, &block); end - include Comparable -end -class Concurrent::Collection::RubyNonConcurrentPriorityQueue - def <<(item); end - def clear; end - def delete(item); end - def deq; end - def empty?; end - def enq(item); end - def has_priority?(item); end - def include?(item); end - def initialize(opts = nil); end - def length; end - def ordered?(x, y); end - def peek; end - def pop; end - def push(item); end - def self.from_list(list, opts = nil); end - def shift; end - def sink(k); end - def size; end - def swap(x, y); end - def swim(k); end -end -class Concurrent::Collection::NonConcurrentPriorityQueue < Concurrent::Collection::RubyNonConcurrentPriorityQueue - def <<(item); end - def deq; end - def enq(item); end - def has_priority?(item); end - def shift; end - def size; end -end -class Concurrent::TimerSet < Concurrent::RubyExecutorService - def <<(task); end - def initialize(opts = nil); end - def kill; end - def ns_initialize(opts); end - def ns_post_task(task); end - def ns_reset_if_forked; end - def ns_shutdown_execution; end - def post(delay, *args, &task); end - def post_task(task); end - def process_tasks; end - def remove_task(task); end -end -class Concurrent::AtomicMarkableReference < Concurrent::Synchronization::Object - def __initialize_atomic_fields__; end - def compare_and_set(expected_val, new_val, expected_mark, new_mark); end - def compare_and_set_reference(expected, value); end - def compare_and_swap(expected_val, new_val, expected_mark, new_mark); end - def get; end - def immutable_array(*args); end - def initialize(value = nil, mark = nil); end - def mark; end - def marked?; end - def reference; end - def reference=(value); end - def self.new(*args, &block); end - def set(new_val, new_mark); end - def swap_reference(value); end - def try_update!; end - def try_update; end - def update; end - def update_reference(&block); end - def value; end -end -class Concurrent::Agent < Concurrent::Synchronization::LockableObject - def <<(action); end - def await; end - def await_for!(timeout); end - def await_for(timeout); end - def deref; end - def enqueue_action_job(action, args, executor); end - def enqueue_await_job(latch); end - def error; end - def error_mode; end - def execute_next_job; end - def failed?; end - def handle_error(error); end - def initialize(initial, opts = nil); end - def ns_enqueue_job(job, index = nil); end - def ns_find_last_job_for_thread; end - def ns_initialize(initial, opts); end - def ns_post_next_job; end - def ns_validate(value); end - def post(*args, &action); end - def reason; end - def restart(new_value, opts = nil); end - def self.await(*agents); end - def self.await_for!(timeout, *agents); end - def self.await_for(timeout, *agents); end - def send!(*args, &action); end - def send(*args, &action); end - def send_off!(*args, &action); end - def send_off(*args, &action); end - def send_via!(executor, *args, &action); end - def send_via(executor, *args, &action); end - def stopped?; end - def value; end - def wait(timeout = nil); end - include Concurrent::Concern::Observable -end -class Concurrent::Agent::Job < Struct - def action; end - def action=(_); end - def args; end - def args=(_); end - def caller; end - def caller=(_); end - def executor; end - def executor=(_); end - def self.[](*arg0); end - def self.inspect; end - def self.keyword_init?; end - def self.members; end - def self.new(*arg0); end -end -class Concurrent::Agent::Error < StandardError - def initialize(message = nil); end -end -class Concurrent::Agent::ValidationError < Concurrent::Agent::Error - def initialize(message = nil); end -end -class Concurrent::Atom < Concurrent::Synchronization::Object - def __initialize_atomic_fields__; end - def compare_and_set(old_value, new_value); end - def compare_and_set_value(expected, value); end - def deref; end - def initialize(value, opts = nil); end - def reset(new_value); end - def self.new(*args, &block); end - def swap(*args); end - def swap_value(value); end - def update_value(&block); end - def valid?(new_value); end - def value; end - def value=(value); end - include Concurrent::Concern::Observable -end -module Concurrent::ThreadSafe -end -module Concurrent::ThreadSafe::Util - def self.make_synchronized_on_cruby(klass); end - def self.make_synchronized_on_rbx(klass); end - def self.make_synchronized_on_truffleruby(klass); end -end -class Concurrent::Array < Array -end -class Concurrent::Hash < Hash -end -class Concurrent::CRubySet < Set - def &(*args); end - def +(*args); end - def -(*args); end - def <(*args); end - def <<(*args); end - def <=(*args); end - def <=>(*args); end - def ==(*args); end - def ===(*args); end - def >(*args); end - def >=(*args); end - def ^(*args); end - def add(*args); end - def add?(*args); end - def classify(*args); end - def clear(*args); end - def collect!(*args); end - def compare_by_identity(*args); end - def compare_by_identity?(*args); end - def delete(*args); end - def delete?(*args); end - def delete_if(*args); end - def difference(*args); end - def disjoint?(*args); end - def divide(*args); end - def each(*args); end - def empty?(*args); end - def eql?(*args); end - def filter!(*args); end - def flatten!(*args); end - def flatten(*args); end - def flatten_merge(*args); end - def freeze(*args); end - def hash(*args); end - def include?(*args); end - def initialize(*args, &block); end - def initialize_copy(other); end - def inspect(*args); end - def intersect?(*args); end - def intersection(*args); end - def join(*args); end - def keep_if(*args); end - def length(*args); end - def map!(*args); end - def member?(*args); end - def merge(*args); end - def pretty_print(*args); end - def pretty_print_cycle(*args); end - def proper_subset?(*args); end - def proper_superset?(*args); end - def reject!(*args); end - def replace(*args); end - def reset(*args); end - def select!(*args); end - def size(*args); end - def subset?(*args); end - def subtract(*args); end - def superset?(*args); end - def to_a(*args); end - def to_s(*args); end - def to_set(*args); end - def union(*args); end - def |(*args); end -end -class Concurrent::Set < Concurrent::CRubySet -end -class Concurrent::Collection::NonConcurrentMapBackend - def [](key); end - def []=(key, value); end - def _get(key); end - def _set(key, value); end - def clear; end - def compute(key); end - def compute_if_absent(key); end - def compute_if_present(key); end - def delete(key); end - def delete_pair(key, value); end - def dupped_backend; end - def each_pair; end - def get_and_set(key, value); end - def get_or_default(key, default_value); end - def initialize(options = nil); end - def initialize_copy(other); end - def key?(key); end - def merge_pair(key, value); end - def pair?(key, expected_value); end - def replace_if_exists(key, new_value); end - def replace_pair(key, old_value, new_value); end - def size; end - def store_computed_value(key, new_value); end -end -class Concurrent::Collection::MriMapBackend < Concurrent::Collection::NonConcurrentMapBackend - def []=(key, value); end - def clear; end - def compute(key); end - def compute_if_absent(key); end - def compute_if_present(key); end - def delete(key); end - def delete_pair(key, value); end - def get_and_set(key, value); end - def initialize(options = nil); end - def merge_pair(key, value); end - def replace_if_exists(key, new_value); end - def replace_pair(key, old_value, new_value); end -end -class Concurrent::Map < Concurrent::Collection::MriMapBackend - def [](key); end - def []=(key, value); end - def each; end - def each_key; end - def each_pair; end - def each_value; end - def empty?; end - def fetch(key, default_value = nil); end - def fetch_or_store(key, default_value = nil); end - def get(key); end - def initialize(options = nil, &block); end - def initialize_copy(other); end - def inspect; end - def key(value); end - def keys; end - def marshal_dump; end - def marshal_load(hash); end - def populate_from(hash); end - def put(key, value); end - def put_if_absent(key, value); end - def raise_fetch_no_key; end - def validate_options_hash!(options); end - def value?(value); end - def values; end -end -class Concurrent::Tuple - def cas(i, old_value, new_value); end - def compare_and_set(i, old_value, new_value); end - def each; end - def get(i); end - def initialize(size); end - def set(i, value); end - def size; end - def volatile_get(i); end - def volatile_set(i, value); end - include Enumerable -end -module Concurrent::Async - def async; end - def await; end - def call; end - def cast; end - def init_synchronization; end - def self.included(base); end - def self.validate_argc(obj, method, *args); end -end -module Concurrent::Async::ClassMethods - def new(*args, **, &block); end -end -class Concurrent::Async::AsyncDelegator < Concurrent::Synchronization::LockableObject - def initialize(delegate); end - def method_missing(method, *args, &block); end - def perform; end - def reset_if_forked; end - def respond_to_missing?(method, include_private = nil); end -end -class Concurrent::Async::AwaitDelegator - def initialize(delegate); end - def method_missing(method, *args, &block); end - def respond_to_missing?(method, include_private = nil); end -end -class Concurrent::Future < Concurrent::IVar - def cancel; end - def cancelled?; end - def execute; end - def initialize(opts = nil, &block); end - def ns_initialize(value, opts); end - def self.execute(opts = nil, &block); end - def set(value = nil, &block); end - def wait_or_cancel(timeout); end -end -class Concurrent::DependencyCounter - def initialize(count, &block); end - def update(time, value, reason); end -end -class Concurrent::Maybe < Concurrent::Synchronization::Object - def <=>(other); end - def fulfilled?; end - def initialize(just, nothing); end - def just; end - def just?; end - def nothing; end - def nothing?; end - def or(other); end - def reason; end - def rejected?; end - def self.from(*args); end - def self.just(value); end - def self.new(*args, &block); end - def self.nothing(error = nil); end - def value; end - include Comparable -end -class Concurrent::AbstractExchanger < Concurrent::Synchronization::Object - def do_exchange(value, timeout); end - def exchange!(value, timeout = nil); end - def exchange(value, timeout = nil); end - def initialize; end - def try_exchange(value, timeout = nil); end -end -class Concurrent::RubyExchanger < Concurrent::AbstractExchanger - def __initialize_atomic_fields__; end - def compare_and_set_slot(expected, value); end - def do_exchange(value, timeout); end - def initialize; end - def self.new(*args, &block); end - def slot; end - def slot=(value); end - def swap_slot(value); end - def update_slot(&block); end -end -class Concurrent::RubyExchanger::Node < Concurrent::Synchronization::Object - def __initialize_atomic_fields__; end - def compare_and_set_value(expected, value); end - def initialize(item); end - def item; end - def latch; end - def self.new(*args, &block); end - def swap_value(value); end - def update_value(&block); end - def value; end - def value=(value); end -end -class Concurrent::Exchanger < Concurrent::RubyExchanger -end -module Concurrent::Synchronization::AbstractStruct - def initialize(*values); end - def length; end - def members; end - def ns_each; end - def ns_each_pair; end - def ns_equality(other); end - def ns_get(member); end - def ns_initialize_copy; end - def ns_inspect; end - def ns_merge(other, &block); end - def ns_select; end - def ns_to_h; end - def ns_values; end - def ns_values_at(indexes); end - def pr_underscore(clazz); end - def self.define_struct_class(parent, base, name, members, &block); end - def size; end -end -module Concurrent::ImmutableStruct - def ==(other); end - def [](member); end - def each(&block); end - def each_pair(&block); end - def initialize_copy(original); end - def inspect; end - def merge(other, &block); end - def select(&block); end - def self.included(base); end - def self.new(*args, &block); end - def to_a; end - def to_h; end - def to_s; end - def values; end - def values_at(*indexes); end - include Concurrent::Synchronization::AbstractStruct -end -module Concurrent::MutableStruct - def ==(other); end - def [](member); end - def []=(member, value); end - def each(&block); end - def each_pair(&block); end - def initialize_copy(original); end - def inspect; end - def merge(other, &block); end - def select(&block); end - def self.new(*args, &block); end - def to_a; end - def to_h; end - def to_s; end - def values; end - def values_at(*indexes); end - include Concurrent::Synchronization::AbstractStruct -end -class Concurrent::MVar < Concurrent::Synchronization::Object - def borrow(timeout = nil); end - def empty?; end - def full?; end - def initialize(value = nil, opts = nil); end - def modify!; end - def modify(timeout = nil); end - def put(value, timeout = nil); end - def self.new(*args, &block); end - def set!(value); end - def synchronize(&block); end - def take(timeout = nil); end - def try_put!(value); end - def try_take!; end - def unlocked_empty?; end - def unlocked_full?; end - def wait_for_empty(timeout); end - def wait_for_full(timeout); end - def wait_while(condition, timeout); end - include Concurrent::Concern::Dereferenceable -end -class Concurrent::PromiseExecutionError < StandardError -end -class Concurrent::Promise < Concurrent::IVar - def catch(&block); end - def complete(success, value, reason); end - def execute; end - def fail(reason = nil); end - def flat_map(&block); end - def initialize(opts = nil, &block); end - def notify_child(child); end - def ns_initialize(value, opts); end - def on_error(&block); end - def on_fulfill(result); end - def on_reject(reason); end - def on_success(&block); end - def realize(task); end - def rescue(&block); end - def root?; end - def self.aggregate(method, *promises); end - def self.all?(*promises); end - def self.any?(*promises); end - def self.execute(opts = nil, &block); end - def self.fulfill(value, opts = nil); end - def self.reject(reason, opts = nil); end - def self.zip(*promises); end - def set(value = nil, &block); end - def set_pending; end - def set_state!(success, value, reason); end - def synchronized_set_state!(success, value, reason); end - def then(*args, &block); end - def zip(*others); end -end -module Concurrent::SettableStruct - def ==(other); end - def [](member); end - def []=(member, value); end - def each(&block); end - def each_pair(&block); end - def initialize_copy(original); end - def inspect; end - def merge(other, &block); end - def select(&block); end - def self.new(*args, &block); end - def to_a; end - def to_h; end - def to_s; end - def values; end - def values_at(*indexes); end - include Concurrent::Synchronization::AbstractStruct -end -class Concurrent::TimerTask < Concurrent::RubyExecutorService - def <<(task); end - def execute; end - def execute_task(completion); end - def execution_interval; end - def execution_interval=(value); end - def initialize(opts = nil, &task); end - def ns_initialize(opts, &task); end - def ns_kill_execution; end - def ns_shutdown_execution; end - def post(*args, &task); end - def running?; end - def schedule_next_task(interval = nil); end - def self.execute(opts = nil, &task); end - def timeout_interval; end - def timeout_interval=(value); end - include Concurrent::Concern::Dereferenceable - include Concurrent::Concern::Observable -end -class Concurrent::TVar < Concurrent::Synchronization::Object - def initialize(value); end - def self.new(*args, &block); end - def unsafe_lock; end - def unsafe_value; end - def unsafe_value=(value); end - def value; end - def value=(value); end -end -class Concurrent::Transaction - def abort; end - def commit; end - def initialize; end - def open(tvar); end - def read(tvar); end - def self.current; end - def self.current=(transaction); end - def unlock; end - def write(tvar, value); end -end -class Concurrent::Transaction::OpenEntry < Struct - def modified; end - def modified=(_); end - def self.[](*arg0); end - def self.inspect; end - def self.keyword_init?; end - def self.members; end - def self.new(*arg0); end - def value; end - def value=(_); end -end -class Concurrent::Transaction::AbortError < StandardError -end -class Concurrent::Transaction::LeaveError < StandardError -end -class Concurrent::LockFreeStack < Concurrent::Synchronization::Object - def __initialize_atomic_fields__; end - def clear; end - def clear_each(&block); end - def clear_if(head); end - def compare_and_clear(head); end - def compare_and_pop(head); end - def compare_and_push(head, value); end - def compare_and_set_head(expected, value); end - def each(head = nil); end - def empty?(head = nil); end - def head; end - def head=(value); end - def initialize(head = nil); end - def inspect; end - def peek; end - def pop; end - def push(value); end - def replace_if(head, new_head); end - def self.new(*args, &block); end - def self.of1(value); end - def self.of2(value1, value2); end - def swap_head(value); end - def to_s; end - def update_head(&block); end - include Enumerable -end -class Concurrent::LockFreeStack::Node - def initialize(value, next_node); end - def next_node; end - def self.[](*arg0, **); end - def value; end - def value=(arg0); end -end -module Concurrent::ReInclude - def extended(base); end - def include(*modules); end - def included(base); end -end -module Concurrent::Promises - extend Concurrent::Promises::FactoryMethods -end -module Concurrent::Promises::FactoryMethods - def any(*futures_and_or_events); end - def any_event(*futures_and_or_events); end - def any_event_on(default_executor, *futures_and_or_events); end - def any_fulfilled_future(*futures_and_or_events); end - def any_fulfilled_future_on(default_executor, *futures_and_or_events); end - def any_resolved_future(*futures_and_or_events); end - def any_resolved_future_on(default_executor, *futures_and_or_events); end - def delay(*args, &task); end - def delay_on(default_executor, *args, &task); end - def fulfilled_future(value, default_executor = nil); end - def future(*args, &task); end - def future_on(default_executor, *args, &task); end - def make_future(argument = nil, default_executor = nil); end - def rejected_future(reason, default_executor = nil); end - def resolvable_event; end - def resolvable_event_on(default_executor = nil); end - def resolvable_future; end - def resolvable_future_on(default_executor = nil); end - def resolved_event(default_executor = nil); end - def resolved_future(fulfilled, value, reason, default_executor = nil); end - def schedule(intended_time, *args, &task); end - def schedule_on(default_executor, intended_time, *args, &task); end - def zip(*futures_and_or_events); end - def zip_events(*futures_and_or_events); end - def zip_events_on(default_executor, *futures_and_or_events); end - def zip_futures(*futures_and_or_events); end - def zip_futures_on(default_executor, *futures_and_or_events); end - extend Concurrent::Promises::FactoryMethods - extend Concurrent::Promises::FactoryMethods::Configuration - extend Concurrent::ReInclude - include Concurrent::Promises::FactoryMethods::Configuration -end -module Concurrent::Promises::FactoryMethods::Configuration - def default_executor; end -end -module Concurrent::Promises::InternalStates -end -class Concurrent::Promises::InternalStates::State - def resolved?; end - def to_sym; end -end -class Concurrent::Promises::InternalStates::Pending < Concurrent::Promises::InternalStates::State - def resolved?; end - def to_sym; end -end -class Concurrent::Promises::InternalStates::Reserved < Concurrent::Promises::InternalStates::Pending -end -class Concurrent::Promises::InternalStates::ResolvedWithResult < Concurrent::Promises::InternalStates::State - def apply; end - def fulfilled?; end - def reason; end - def resolved?; end - def result; end - def to_sym; end - def value; end -end -class Concurrent::Promises::InternalStates::Fulfilled < Concurrent::Promises::InternalStates::ResolvedWithResult - def apply(args, block); end - def fulfilled?; end - def initialize(value); end - def reason; end - def to_sym; end - def value; end -end -class Concurrent::Promises::InternalStates::FulfilledArray < Concurrent::Promises::InternalStates::Fulfilled - def apply(args, block); end -end -class Concurrent::Promises::InternalStates::Rejected < Concurrent::Promises::InternalStates::ResolvedWithResult - def apply(args, block); end - def fulfilled?; end - def initialize(reason); end - def reason; end - def to_sym; end - def value; end -end -class Concurrent::Promises::InternalStates::PartiallyRejected < Concurrent::Promises::InternalStates::ResolvedWithResult - def apply(args, block); end - def fulfilled?; end - def initialize(value, reason); end - def reason; end - def to_sym; end - def value; end -end -class Concurrent::Promises::AbstractEventFuture < Concurrent::Synchronization::Object - def __initialize_atomic_fields__; end - def add_callback(method, *args); end - def add_callback_clear_delayed_node(node); end - def add_callback_notify_blocked(promise, index); end - def async_callback_on_resolution(state, executor, args, callback); end - def blocks; end - def call_callback(method, state, args); end - def call_callbacks(state); end - def callback_clear_delayed_node(state, node); end - def callback_notify_blocked(state, promise, index); end - def callbacks; end - def chain(*args, &task); end - def chain_on(executor, *args, &task); end - def chain_resolvable(resolvable); end - def compare_and_set_internal_state(expected, value); end - def default_executor; end - def initialize(promise, default_executor); end - def inspect; end - def internal_state; end - def internal_state=(value); end - def on_resolution!(*args, &callback); end - def on_resolution(*args, &callback); end - def on_resolution_using(executor, *args, &callback); end - def pending?; end - def promise; end - def resolve_with(state, raise_on_reassign = nil, reserved = nil); end - def resolved?; end - def self.new(*args, &block); end - def state; end - def swap_internal_state(value); end - def tangle(resolvable); end - def to_s; end - def touch; end - def touched?; end - def update_internal_state(&block); end - def wait(timeout = nil); end - def wait_until_resolved(timeout); end - def waiting_threads; end - def with_async(executor, *args, &block); end - def with_default_executor(executor); end - def with_hidden_resolvable; end - include Concurrent::Promises::InternalStates -end -class Concurrent::Promises::Event < Concurrent::Promises::AbstractEventFuture - def &(other); end - def any(event_or_future); end - def callback_on_resolution(state, args, callback); end - def delay; end - def rejected_resolution(raise_on_reassign, state); end - def schedule(intended_time); end - def then(*args, &task); end - def to_event; end - def to_future; end - def with_default_executor(executor); end - def zip(other); end - def |(event_or_future); end -end -class Concurrent::Promises::Future < Concurrent::Promises::AbstractEventFuture - def &(other); end - def any(event_or_future); end - def apply(args, block); end - def async_callback_on_fulfillment(state, executor, args, callback); end - def async_callback_on_rejection(state, executor, args, callback); end - def callback_on_fulfillment(state, args, callback); end - def callback_on_rejection(state, args, callback); end - def callback_on_resolution(state, args, callback); end - def delay; end - def exception(*args); end - def flat(level = nil); end - def flat_event; end - def flat_future(level = nil); end - def fulfilled?; end - def inspect; end - def on_fulfillment!(*args, &callback); end - def on_fulfillment(*args, &callback); end - def on_fulfillment_using(executor, *args, &callback); end - def on_rejection!(*args, &callback); end - def on_rejection(*args, &callback); end - def on_rejection_using(executor, *args, &callback); end - def reason(timeout = nil, timeout_value = nil); end - def rejected?; end - def rejected_resolution(raise_on_reassign, state); end - def rescue(*args, &task); end - def rescue_on(executor, *args, &task); end - def result(timeout = nil); end - def run(run_test = nil); end - def run_test(v); end - def schedule(intended_time); end - def then(*args, &task); end - def then_on(executor, *args, &task); end - def to_event; end - def to_future; end - def to_s; end - def value!(timeout = nil, timeout_value = nil); end - def value(timeout = nil, timeout_value = nil); end - def wait!(timeout = nil); end - def wait_until_resolved!(timeout = nil); end - def with_default_executor(executor); end - def zip(other); end - def |(event_or_future); end -end -module Concurrent::Promises::Resolvable - include Concurrent::Promises::InternalStates -end -class Concurrent::Promises::ResolvableEvent < Concurrent::Promises::Event - def resolve(raise_on_reassign = nil, reserved = nil); end - def wait(timeout = nil, resolve_on_timeout = nil); end - def with_hidden_resolvable; end - include Concurrent::Promises::Resolvable -end -class Concurrent::Promises::ResolvableFuture < Concurrent::Promises::Future - def evaluate_to!(*args, &block); end - def evaluate_to(*args, &block); end - def fulfill(value, raise_on_reassign = nil, reserved = nil); end - def reason(timeout = nil, timeout_value = nil, resolve_on_timeout = nil); end - def reject(reason, raise_on_reassign = nil, reserved = nil); end - def resolve(fulfilled = nil, value = nil, reason = nil, raise_on_reassign = nil, reserved = nil); end - def result(timeout = nil, resolve_on_timeout = nil); end - def value!(timeout = nil, timeout_value = nil, resolve_on_timeout = nil); end - def value(timeout = nil, timeout_value = nil, resolve_on_timeout = nil); end - def wait!(timeout = nil, resolve_on_timeout = nil); end - def wait(timeout = nil, resolve_on_timeout = nil); end - def with_hidden_resolvable; end - include Concurrent::Promises::Resolvable -end -class Concurrent::Promises::AbstractPromise < Concurrent::Synchronization::Object - def default_executor; end - def delayed_because; end - def evaluate_to(*args, block); end - def event; end - def future; end - def initialize(future); end - def inspect; end - def resolve_with(new_state, raise_on_reassign = nil); end - def self.new(*args, &block); end - def state; end - def to_s; end - def touch; end - include Concurrent::Promises::InternalStates -end -class Concurrent::Promises::ResolvableEventPromise < Concurrent::Promises::AbstractPromise - def initialize(default_executor); end -end -class Concurrent::Promises::ResolvableFuturePromise < Concurrent::Promises::AbstractPromise - def evaluate_to(*args, block); end - def initialize(default_executor); end -end -class Concurrent::Promises::InnerPromise < Concurrent::Promises::AbstractPromise -end -class Concurrent::Promises::BlockedPromise < Concurrent::Promises::InnerPromise - def blocked_by; end - def clear_and_propagate_touch(stack_or_element = nil); end - def delayed_because; end - def initialize(delayed, blockers_count, future); end - def on_blocker_resolution(future, index); end - def on_resolvable(resolved_future, index); end - def process_on_blocker_resolution(future, index); end - def resolvable?(countdown, future, index); end - def self.add_delayed(delayed1, delayed2); end - def self.new(*args, &block); end - def self.new_blocked_by(blockers, *args, &block); end - def self.new_blocked_by1(blocker, *args, &block); end - def self.new_blocked_by2(blocker1, blocker2, *args, &block); end - def touch; end -end -class Concurrent::Promises::BlockedTaskPromise < Concurrent::Promises::BlockedPromise - def executor; end - def initialize(delayed, blockers_count, default_executor, executor, args, &task); end -end -class Concurrent::Promises::ThenPromise < Concurrent::Promises::BlockedTaskPromise - def initialize(delayed, blockers_count, default_executor, executor, args, &task); end - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::RescuePromise < Concurrent::Promises::BlockedTaskPromise - def initialize(delayed, blockers_count, default_executor, executor, args, &task); end - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::ChainPromise < Concurrent::Promises::BlockedTaskPromise - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::ImmediateEventPromise < Concurrent::Promises::InnerPromise - def initialize(default_executor); end -end -class Concurrent::Promises::ImmediateFuturePromise < Concurrent::Promises::InnerPromise - def initialize(default_executor, fulfilled, value, reason); end -end -class Concurrent::Promises::AbstractFlatPromise < Concurrent::Promises::BlockedPromise - def add_delayed_of(future); end - def initialize(delayed_because, blockers_count, event_or_future); end - def on_resolvable(resolved_future, index); end - def resolvable?(countdown, future, index); end - def touch; end - def touched?; end -end -class Concurrent::Promises::FlatEventPromise < Concurrent::Promises::AbstractFlatPromise - def initialize(delayed, blockers_count, default_executor); end - def process_on_blocker_resolution(future, index); end -end -class Concurrent::Promises::FlatFuturePromise < Concurrent::Promises::AbstractFlatPromise - def initialize(delayed, blockers_count, levels, default_executor); end - def process_on_blocker_resolution(future, index); end -end -class Concurrent::Promises::RunFuturePromise < Concurrent::Promises::AbstractFlatPromise - def initialize(delayed, blockers_count, default_executor, run_test); end - def process_on_blocker_resolution(future, index); end -end -class Concurrent::Promises::ZipEventEventPromise < Concurrent::Promises::BlockedPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::ZipFutureEventPromise < Concurrent::Promises::BlockedPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end - def process_on_blocker_resolution(future, index); end -end -class Concurrent::Promises::EventWrapperPromise < Concurrent::Promises::BlockedPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::FutureWrapperPromise < Concurrent::Promises::BlockedPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::ZipFuturesPromise < Concurrent::Promises::BlockedPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end - def process_on_blocker_resolution(future, index); end -end -class Concurrent::Promises::ZipEventsPromise < Concurrent::Promises::BlockedPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end -end -class Concurrent::Promises::AbstractAnyPromise < Concurrent::Promises::BlockedPromise -end -class Concurrent::Promises::AnyResolvedEventPromise < Concurrent::Promises::AbstractAnyPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end - def resolvable?(countdown, future, index); end -end -class Concurrent::Promises::AnyResolvedFuturePromise < Concurrent::Promises::AbstractAnyPromise - def initialize(delayed, blockers_count, default_executor); end - def on_resolvable(resolved_future, index); end - def resolvable?(countdown, future, index); end -end -class Concurrent::Promises::AnyFulfilledFuturePromise < Concurrent::Promises::AnyResolvedFuturePromise - def resolvable?(countdown, future, index); end -end -class Concurrent::Promises::DelayPromise < Concurrent::Promises::InnerPromise - def delayed_because; end - def initialize(default_executor); end - def touch; end -end -class Concurrent::Promises::ScheduledPromise < Concurrent::Promises::InnerPromise - def initialize(default_executor, intended_time); end - def inspect; end - def intended_time; end -end -class Concurrent::SynchronizedDelegator < SimpleDelegator - def initialize(obj); end - def method_missing(method, *args, &block); end - def setup; end - def teardown; end -end diff --git a/sorbet/rbi/gems/connection_pool.rbi b/sorbet/rbi/gems/connection_pool.rbi deleted file mode 100644 index 859194f..0000000 --- a/sorbet/rbi/gems/connection_pool.rbi +++ /dev/null @@ -1,60 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/connection_pool/all/connection_pool.rbi -# -# connection_pool-2.4.1 - -class ConnectionPool - def auto_reload_after_fork; end - def available; end - def checkin(force: nil); end - def checkout(options = nil); end - def initialize(options = nil, &block); end - def reload(&block); end - def self.after_fork; end - def self.wrap(options, &block); end - def shutdown(&block); end - def size; end - def then(options = nil); end - def with(options = nil); end -end -class ConnectionPool::TimedStack - def <<(obj, options = nil); end - def connection_stored?(options = nil); end - def current_time; end - def empty?; end - def fetch_connection(options = nil); end - def initialize(size = nil, &block); end - def length; end - def max; end - def pop(timeout = nil, options = nil); end - def push(obj, options = nil); end - def shutdown(reload: nil, &block); end - def shutdown_connections(options = nil); end - def store_connection(obj, options = nil); end - def try_create(options = nil); end -end -class ConnectionPool::Wrapper < BasicObject - def initialize(options = nil, &block); end - def method_missing(name, *args, **kwargs, &block); end - def pool_available; end - def pool_shutdown(&block); end - def pool_size; end - def respond_to?(id, *args); end - def with(&block); end - def wrapped_pool; end -end -class ConnectionPool::Error < RuntimeError -end -class ConnectionPool::PoolShuttingDownError < ConnectionPool::Error -end -class ConnectionPool::TimeoutError < Timeout::Error -end -module ConnectionPool::ForkTracker - def _fork; end -end diff --git a/sorbet/rbi/gems/crack.rbi b/sorbet/rbi/gems/crack.rbi deleted file mode 100644 index 5e7c8ce..0000000 --- a/sorbet/rbi/gems/crack.rbi +++ /dev/null @@ -1,62 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/crack/all/crack.rbi -# -# crack-0.4.5 - -module Crack -end -module Crack::Util - def snake_case(str); end - def to_xml_attributes(hash); end - extend Crack::Util -end -class Crack::JSON - def self.convert_json_to_yaml(json); end - def self.format_dates(output, date_starts, date_ends); end - def self.parse(json); end - def self.parser_exceptions; end - def self.unescape(str); end -end -class REXMLUtiliyNodeString < String - def attributes; end - def attributes=(arg0); end -end -class REXMLUtilityNode - def add_node(node); end - def attributes; end - def attributes=(arg0); end - def children; end - def children=(arg0); end - def initialize(name, normalized_attributes = nil); end - def inner_html; end - def name; end - def name=(arg0); end - def self.available_typecasts; end - def self.available_typecasts=(obj); end - def self.typecasts; end - def self.typecasts=(obj); end - def to_hash; end - def to_html; end - def to_s; end - def type; end - def type=(arg0); end - def typecast_value(value); end - def undasherize_keys(params); end - def unnormalize_xml_entities(value); end -end -class Crack::REXMLParser - def self.parse(xml); end -end -class Crack::XML - def self.parse(xml); end - def self.parser; end - def self.parser=(parser); end -end -class Crack::ParseError < StandardError -end diff --git a/sorbet/rbi/gems/domain_name.rbi b/sorbet/rbi/gems/domain_name.rbi deleted file mode 100644 index 8c88653..0000000 --- a/sorbet/rbi/gems/domain_name.rbi +++ /dev/null @@ -1,52 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/domain_name/all/domain_name.rbi -# -# domain_name-0.5.20190701 - -class DomainName - def <(other); end - def <=(other); end - def <=>(other); end - def ==(other); end - def >(other); end - def >=(other); end - def canonical?; end - def canonical_tld?; end - def cookie_domain?(domain, host_only = nil); end - def domain; end - def domain_idn; end - def hostname; end - def hostname_idn; end - def idn; end - def initialize(hostname); end - def inspect; end - def ipaddr; end - def ipaddr?; end - def self.etld_data; end - def self.normalize(domain); end - def superdomain; end - def tld; end - def tld_idn; end - def to_s; end - def to_str; end - def uri_host; end -end -module DomainName::Punycode - def self.decode(string); end - def self.decode_hostname(hostname); end - def self.encode(string); end - def self.encode_hostname(hostname); end -end -class DomainName::Punycode::ArgumentError < ArgumentError -end -class DomainName::Punycode::BufferOverflowError < DomainName::Punycode::ArgumentError -end -class Object < BasicObject - def DomainName(hostname); end -end diff --git a/sorbet/rbi/gems/ffi-compiler.rbi b/sorbet/rbi/gems/ffi-compiler.rbi deleted file mode 100644 index beb34ba..0000000 --- a/sorbet/rbi/gems/ffi-compiler.rbi +++ /dev/null @@ -1,27 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/ffi-compiler/all/ffi-compiler.rbi -# -# ffi-compiler-1.0.1 - -module FFI::Compiler -end -class FFI::Compiler::Platform - def arch; end - def mac?; end - def map_library_name(name); end - def name; end - def os; end - def self.system; end -end -module FFI -end -module FFI::Compiler::Loader - def self.caller_path(line = nil); end - def self.find(name, start_path = nil); end -end diff --git a/sorbet/rbi/gems/ffi.rbi b/sorbet/rbi/gems/ffi.rbi deleted file mode 100644 index c5ebd29..0000000 --- a/sorbet/rbi/gems/ffi.rbi +++ /dev/null @@ -1,560 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: true -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/ffi/all/ffi.rbi -# -# ffi-1.15.5 - -class FFI::Type - def alignment; end - def initialize(arg0); end - def inspect; end - def size; end -end -class FFI::Type::Builtin < FFI::Type - def inspect; end -end -class FFI::ArrayType < FFI::Type - def elem_type; end - def initialize(arg0, arg1); end - def length; end -end -module FFI::LastError - def error; end - def error=(arg0); end - def self.error; end - def self.error=(arg0); end -end -class FFI::AbstractMemory - def [](arg0); end - def __copy_from__(arg0, arg1); end - def clear; end - def get(arg0, arg1); end - def get_array_of_char(arg0, arg1); end - def get_array_of_double(arg0, arg1); end - def get_array_of_float(arg0, arg1); end - def get_array_of_float32(arg0, arg1); end - def get_array_of_float64(arg0, arg1); end - def get_array_of_int(arg0, arg1); end - def get_array_of_int16(arg0, arg1); end - def get_array_of_int32(arg0, arg1); end - def get_array_of_int64(arg0, arg1); end - def get_array_of_int8(arg0, arg1); end - def get_array_of_long(arg0, arg1); end - def get_array_of_long_long(arg0, arg1); end - def get_array_of_pointer(arg0, arg1); end - def get_array_of_short(arg0, arg1); end - def get_array_of_string(*arg0); end - def get_array_of_uchar(arg0, arg1); end - def get_array_of_uint(arg0, arg1); end - def get_array_of_uint16(arg0, arg1); end - def get_array_of_uint32(arg0, arg1); end - def get_array_of_uint64(arg0, arg1); end - def get_array_of_uint8(arg0, arg1); end - def get_array_of_ulong(arg0, arg1); end - def get_array_of_ulong_long(arg0, arg1); end - def get_array_of_ushort(arg0, arg1); end - def get_bytes(arg0, arg1); end - def get_char(arg0); end - def get_double(arg0); end - def get_float(arg0); end - def get_float32(arg0); end - def get_float64(arg0); end - def get_int(arg0); end - def get_int16(arg0); end - def get_int32(arg0); end - def get_int64(arg0); end - def get_int8(arg0); end - def get_long(arg0); end - def get_long_long(arg0); end - def get_pointer(arg0); end - def get_short(arg0); end - def get_string(*arg0); end - def get_uchar(arg0); end - def get_uint(arg0); end - def get_uint16(arg0); end - def get_uint32(arg0); end - def get_uint64(arg0); end - def get_uint8(arg0); end - def get_ulong(arg0); end - def get_ulong_long(arg0); end - def get_ushort(arg0); end - def put(arg0, arg1, arg2); end - def put_array_of_char(arg0, arg1); end - def put_array_of_double(arg0, arg1); end - def put_array_of_float(arg0, arg1); end - def put_array_of_float32(arg0, arg1); end - def put_array_of_float64(arg0, arg1); end - def put_array_of_int(arg0, arg1); end - def put_array_of_int16(arg0, arg1); end - def put_array_of_int32(arg0, arg1); end - def put_array_of_int64(arg0, arg1); end - def put_array_of_int8(arg0, arg1); end - def put_array_of_long(arg0, arg1); end - def put_array_of_long_long(arg0, arg1); end - def put_array_of_pointer(arg0, arg1); end - def put_array_of_short(arg0, arg1); end - def put_array_of_uchar(arg0, arg1); end - def put_array_of_uint(arg0, arg1); end - def put_array_of_uint16(arg0, arg1); end - def put_array_of_uint32(arg0, arg1); end - def put_array_of_uint64(arg0, arg1); end - def put_array_of_uint8(arg0, arg1); end - def put_array_of_ulong(arg0, arg1); end - def put_array_of_ulong_long(arg0, arg1); end - def put_array_of_ushort(arg0, arg1); end - def put_bytes(*arg0); end - def put_char(arg0, arg1); end - def put_double(arg0, arg1); end - def put_float(arg0, arg1); end - def put_float32(arg0, arg1); end - def put_float64(arg0, arg1); end - def put_int(arg0, arg1); end - def put_int16(arg0, arg1); end - def put_int32(arg0, arg1); end - def put_int64(arg0, arg1); end - def put_int8(arg0, arg1); end - def put_long(arg0, arg1); end - def put_long_long(arg0, arg1); end - def put_pointer(arg0, arg1); end - def put_short(arg0, arg1); end - def put_string(arg0, arg1); end - def put_uchar(arg0, arg1); end - def put_uint(arg0, arg1); end - def put_uint16(arg0, arg1); end - def put_uint32(arg0, arg1); end - def put_uint64(arg0, arg1); end - def put_uint8(arg0, arg1); end - def put_ulong(arg0, arg1); end - def put_ulong_long(arg0, arg1); end - def put_ushort(arg0, arg1); end - def read_array_of_char(arg0); end - def read_array_of_double(arg0); end - def read_array_of_float(arg0); end - def read_array_of_int(arg0); end - def read_array_of_int16(arg0); end - def read_array_of_int32(arg0); end - def read_array_of_int64(arg0); end - def read_array_of_int8(arg0); end - def read_array_of_long(arg0); end - def read_array_of_long_long(arg0); end - def read_array_of_pointer(arg0); end - def read_array_of_short(arg0); end - def read_array_of_uchar(arg0); end - def read_array_of_uint(arg0); end - def read_array_of_uint16(arg0); end - def read_array_of_uint32(arg0); end - def read_array_of_uint64(arg0); end - def read_array_of_uint8(arg0); end - def read_array_of_ulong(arg0); end - def read_array_of_ulong_long(arg0); end - def read_array_of_ushort(arg0); end - def read_bytes(arg0); end - def read_char; end - def read_double; end - def read_float; end - def read_int16; end - def read_int32; end - def read_int64; end - def read_int8; end - def read_int; end - def read_long; end - def read_long_long; end - def read_pointer; end - def read_short; end - def read_uchar; end - def read_uint16; end - def read_uint32; end - def read_uint64; end - def read_uint8; end - def read_uint; end - def read_ulong; end - def read_ulong_long; end - def read_ushort; end - def size; end - def size_limit?; end - def total; end - def type_size; end - def write_array_of_char(arg0); end - def write_array_of_double(arg0); end - def write_array_of_float(arg0); end - def write_array_of_int(arg0); end - def write_array_of_int16(arg0); end - def write_array_of_int32(arg0); end - def write_array_of_int64(arg0); end - def write_array_of_int8(arg0); end - def write_array_of_long(arg0); end - def write_array_of_long_long(arg0); end - def write_array_of_pointer(arg0); end - def write_array_of_short(arg0); end - def write_array_of_uchar(arg0); end - def write_array_of_uint(arg0); end - def write_array_of_uint16(arg0); end - def write_array_of_uint32(arg0); end - def write_array_of_uint64(arg0); end - def write_array_of_uint8(arg0); end - def write_array_of_ulong(arg0); end - def write_array_of_ulong_long(arg0); end - def write_array_of_ushort(arg0); end - def write_bytes(*arg0); end - def write_char(arg0); end - def write_double(arg0); end - def write_float(arg0); end - def write_int(arg0); end - def write_int16(arg0); end - def write_int32(arg0); end - def write_int64(arg0); end - def write_int8(arg0); end - def write_long(arg0); end - def write_long_long(arg0); end - def write_pointer(arg0); end - def write_short(arg0); end - def write_uchar(arg0); end - def write_uint(arg0); end - def write_uint16(arg0); end - def write_uint32(arg0); end - def write_uint64(arg0); end - def write_uint8(arg0); end - def write_ulong(arg0); end - def write_ulong_long(arg0); end - def write_ushort(arg0); end -end -class FFI::Pointer < FFI::AbstractMemory - def +(arg0); end - def ==(arg0); end - def address; end - def autorelease=(arg0); end - def autorelease?; end - def free; end - def initialize(*arg0); end - def initialize_copy(arg0); end - def inspect; end - def null?; end - def order(*arg0); end - def read(type); end - def read_array_of_type(type, reader, length); end - def read_string(len = nil); end - def read_string_length(len); end - def read_string_to_null; end - def self.size; end - def slice(arg0, arg1); end - def to_i; end - def to_ptr; end - def to_s; end - def type_size; end - def write(type, value); end - def write_array_of_type(type, writer, ary); end - def write_string(str, len = nil); end - def write_string_length(str, len); end -end -class FFI::FunctionType < FFI::Type - def initialize(*arg0); end - def param_types; end - def result_type; end -end -class FFI::Function < FFI::Pointer - def attach(arg0, arg1); end - def autorelease; end - def autorelease=(arg0); end - def autorelease?; end - def call(*arg0); end - def free; end - def initialize(*arg0); end - def initialize_copy(arg0); end -end -class FFI::MemoryPointer < FFI::Pointer - def initialize(*arg0); end - def self.from_string(arg0); end -end -class FFI::Buffer < FFI::AbstractMemory - def +(arg0); end - def initialize(*arg0); end - def initialize_copy(arg0); end - def inspect; end - def length; end - def order(*arg0); end - def self.alloc_in(*arg0); end - def self.alloc_inout(*arg0); end - def self.alloc_out(*arg0); end - def self.new_in(*arg0); end - def self.new_inout(*arg0); end - def self.new_out(*arg0); end - def slice(arg0, arg1); end -end -class FFI::StructByValue < FFI::Type - def initialize(arg0); end - def layout; end - def struct_class; end -end -class FFI::StructLayout::Field - def alignment; end - def get(arg0); end - def initialize(*arg0); end - def name; end - def offset; end - def put(arg0, arg1); end - def size; end - def type; end -end -class FFI::StructLayout::Function < FFI::StructLayout::Field - def get(arg0); end - def put(arg0, arg1); end -end -class FFI::StructLayout::Array < FFI::StructLayout::Field - def get(arg0); end - def put(arg0, arg1); end -end -class FFI::StructLayout < FFI::Type - def [](arg0); end - def __union!; end - def fields; end - def initialize(arg0, arg1, arg2); end - def members; end - def offset_of(field_name); end - def offsets; end - def to_a; end -end -class FFI::Struct - def [](arg0); end - def []=(arg0, arg1); end - def align; end - def alignment; end - def clear; end - def initialize(*arg0); end - def initialize_copy(arg0); end - def layout; end - def layout=(arg0); end - def members; end - def null?; end - def offset_of(name); end - def offsets; end - def order(*arg0); end - def pointer; end - def pointer=(arg0); end - def self.align(alignment = nil); end - def self.aligned(alignment = nil); end - def self.alignment; end - def self.alloc_in(*arg0, **); end - def self.alloc_inout(*arg0, **); end - def self.alloc_out(*arg0, **); end - def self.array_layout(builder, spec); end - def self.auto_ptr; end - def self.by_ref(flags = nil); end - def self.by_value; end - def self.callback(params, ret); end - def self.enclosing_module; end - def self.find_field_type(type, mod = nil); end - def self.find_type(type, mod = nil); end - def self.hash_layout(builder, spec); end - def self.in; end - def self.layout(*spec); end - def self.members; end - def self.new_in(*arg0, **); end - def self.new_inout(*arg0, **); end - def self.new_out(*arg0, **); end - def self.offset_of(name); end - def self.offsets; end - def self.out; end - def self.pack(packed = nil); end - def self.packed(packed = nil); end - def self.ptr(flags = nil); end - def self.size; end - def self.size=(size); end - def self.val; end - def size; end - def to_ptr; end - def values; end -end -class FFI::Struct::InlineArray - def [](arg0); end - def []=(arg0, arg1); end - def each; end - def initialize(arg0, arg1); end - def size; end - def to_a; end - def to_ptr; end -end -class FFI::StructLayout::CharArray < FFI::Struct::InlineArray - def to_s; end - def to_str; end -end -class FFI::DynamicLibrary - def find_function(arg0); end - def find_symbol(arg0); end - def find_variable(arg0); end - def initialize(arg0, arg1); end - def last_error; end - def name; end - def self.last_error; end - def self.open(arg0, arg1); end -end -class FFI::DynamicLibrary::Symbol < FFI::Pointer - def initialize_copy(arg0); end - def inspect; end -end -class FFI::VariadicInvoker - def attach(mod, mname); end - def call(*args, &block); end - def initialize(arg0, arg1, arg2, arg3); end - def invoke(arg0, arg1); end -end -class FFI::Type::Mapped < FFI::Type - def from_native(*arg0); end - def initialize(arg0); end - def native_type; end - def to_native(*arg0); end - def type; end -end -module FFI - def self.add_typedef(old, add); end - def self.errno; end - def self.errno=(error); end - def self.find_type(name, type_map = nil); end - def self.map_library_name(lib); end - def self.type_size(type); end - def self.typedef(old, add); end -end -class FFI::PlatformError < LoadError -end -module FFI::Platform - def self.bsd?; end - def self.is_os(os); end - def self.mac?; end - def self.solaris?; end - def self.unix?; end - def self.windows?; end -end -module FFI::DataConverter - def from_native(value, ctx); end - def native_type(type = nil); end - def to_native(value, ctx); end -end -class FFI::StrPtrConverter - def self.from_native(val, ctx); end - extend FFI::DataConverter -end -class FFI::NotFoundError < LoadError - def initialize(function, *libraries); end -end -module FFI::Library - def attach_function(name, func, args, returns = nil, options = nil); end - def attach_variable(mname, a1, a2 = nil); end - def bitmask(*args); end - def callback(*args); end - def enum(*args); end - def enum_type(name); end - def enum_value(symbol); end - def ffi_convention(convention = nil); end - def ffi_lib(*names); end - def ffi_lib_flags(*flags); end - def ffi_libraries; end - def find_type(t); end - def function_names(name, arg_types); end - def generic_enum(klass, *args); end - def self.extended(mod); end - def typedef(old, add, info = nil); end -end -class FFI::StructLayout::Enum < FFI::StructLayout::Field - def get(ptr); end - def put(ptr, value); end -end -class FFI::StructLayout::InnerStruct < FFI::StructLayout::Field - def get(ptr); end - def put(ptr, value); end -end -class FFI::StructLayout::Mapped < FFI::StructLayout::Field - def get(ptr); end - def initialize(name, offset, type, orig_field); end - def put(ptr, value); end -end -class FFI::StructLayoutBuilder - def add(name, type, offset = nil); end - def add_array(name, type, count, offset = nil); end - def add_field(name, type, offset = nil); end - def add_struct(name, type, offset = nil); end - def align(offset, align); end - def alignment; end - def alignment=(align); end - def build; end - def field_for_type(name, offset, type); end - def initialize; end - def packed=(packed); end - def size; end - def size=(size); end - def union=(is_union); end - def union?; end -end -class FFI::StructByReference - def from_native(value, ctx); end - def initialize(struct_class); end - def native_type; end - def struct_class; end - def to_native(value, ctx); end - include FFI::DataConverter -end -class FFI::Struct::ManagedStructConverter < FFI::StructByReference - def from_native(ptr, ctx); end - def initialize(struct_class); end -end -class FFI::Union < FFI::Struct - def self.builder; end -end -class FFI::ManagedStruct < FFI::Struct - def initialize(pointer = nil); end -end -module FFI::IO - def self.for_fd(fd, mode = nil); end - def self.native_read(io, buf, len); end -end -class FFI::AutoPointer < FFI::Pointer - def autorelease=(autorelease); end - def autorelease?; end - def free; end - def initialize(ptr, proc = nil, &block); end - def self.from_native(val, ctx); end - def self.native_type; end - extend FFI::DataConverter -end -class FFI::AutoPointer::Releaser - def autorelease; end - def autorelease=(arg0); end - def call(*args); end - def free; end - def initialize(ptr, proc); end -end -class FFI::AutoPointer::DefaultReleaser < FFI::AutoPointer::Releaser - def release(ptr); end -end -class FFI::AutoPointer::CallableReleaser < FFI::AutoPointer::Releaser - def release(ptr); end -end -class FFI::Enums - def <<(enum); end - def __map_symbol(symbol); end - def find(query); end - def initialize; end -end -class FFI::Enum - def [](query); end - def find(query); end - def from_native(val, ctx); end - def initialize(*args); end - def native_type; end - def symbol_map; end - def symbols; end - def tag; end - def to_h; end - def to_hash; end - def to_native(val, ctx); end - include FFI::DataConverter -end -class FFI::Bitmask < FFI::Enum - def [](*query); end - def from_native(val, ctx); end - def initialize(*args); end - def to_native(query, ctx); end -end diff --git a/sorbet/rbi/gems/hashdiff.rbi b/sorbet/rbi/gems/hashdiff.rbi deleted file mode 100644 index 0756353..0000000 --- a/sorbet/rbi/gems/hashdiff.rbi +++ /dev/null @@ -1,66 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/hashdiff/all/hashdiff.rbi -# -# hashdiff-1.0.1 - -module Hashdiff - def self.any_hash_or_array?(obja, objb); end - def self.best_diff(obj1, obj2, options = nil, &block); end - def self.comparable?(obj1, obj2, strict = nil); end - def self.compare_values(obj1, obj2, options = nil); end - def self.count_diff(diffs); end - def self.count_nodes(obj); end - def self.custom_compare(method, key, obj1, obj2); end - def self.decode_property_path(path, delimiter = nil); end - def self.diff(obj1, obj2, options = nil, &block); end - def self.diff_array_lcs(arraya, arrayb, options = nil); end - def self.lcs(arraya, arrayb, options = nil); end - def self.node(hash, parts); end - def self.patch!(obj, changes, options = nil); end - def self.prefix_append_array_index(prefix, array_index, opts); end - def self.prefix_append_key(prefix, key, opts); end - def self.similar?(obja, objb, options = nil); end - def self.unpatch!(obj, changes, options = nil); end -end -class Hashdiff::CompareHashes - def self.call(obj1, obj2, opts = nil); end -end -class Hashdiff::LcsCompareArrays - def self.call(obj1, obj2, opts = nil); end -end -class Hashdiff::LinearCompareArray - def additions; end - def append_addition(item, index); end - def append_addititions_before_match(match_index); end - def append_deletion(item, index); end - def append_deletions_before_match(match_index); end - def append_differences(difference); end - def call; end - def changes; end - def compare_at_index; end - def deletions; end - def differences; end - def expected_additions; end - def expected_additions=(arg0); end - def extra_items_in_new_array?; end - def extra_items_in_old_array?; end - def index_of_match_after_additions; end - def index_of_match_after_deletions; end - def initialize(old_array, new_array, options); end - def item_difference(old_item, new_item, item_index); end - def iterated_through_both_arrays?; end - def new_array; end - def new_index; end - def new_index=(arg0); end - def old_array; end - def old_index; end - def old_index=(arg0); end - def options; end - def self.call(old_array, new_array, options = nil); end -end diff --git a/sorbet/rbi/gems/http-cookie.rbi b/sorbet/rbi/gems/http-cookie.rbi deleted file mode 100644 index d512700..0000000 --- a/sorbet/rbi/gems/http-cookie.rbi +++ /dev/null @@ -1,93 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: true -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/http-cookie/all/http-cookie.rbi -# -# http-cookie-1.0.5 - -module HTTP -end -class HTTP::Cookie - def <=>(other); end - def acceptable?; end - def acceptable_from_uri?(uri); end - def accessed_at; end - def accessed_at=(arg0); end - def cookie_value; end - def created_at; end - def created_at=(arg0); end - def domain; end - def domain=(domain); end - def domain_name; end - def dot_domain; end - def encode_with(coder); end - def expire!; end - def expired?(time = nil); end - def expires; end - def expires=(t); end - def expires_at; end - def expires_at=(t); end - def for_domain; end - def for_domain=(arg0); end - def for_domain?; end - def httponly; end - def httponly=(arg0); end - def httponly?; end - def init_with(coder); end - def initialize(*args); end - def inspect; end - def max_age; end - def max_age=(sec); end - def name; end - def name=(name); end - def origin; end - def origin=(origin); end - def path; end - def path=(path); end - def secure; end - def secure=(arg0); end - def secure?; end - def self.cookie_value(cookies); end - def self.cookie_value_to_hash(cookie_value); end - def self.parse(set_cookie, origin, options = nil, &block); end - def self.path_match?(base_path, target_path); end - def session; end - def session?; end - def set_cookie_value; end - def to_s; end - def to_yaml_properties; end - def valid_for_uri?(uri); end - def value; end - def value=(value); end - def yaml_initialize(tag, map); end - include Comparable -end -class Array -end -class Hash -end -class String -end -class HTTP::CookieJar - def <<(cookie); end - def add(cookie); end - def cleanup(session = nil); end - def clear; end - def cookies(url = nil); end - def delete(cookie); end - def each(uri = nil, &block); end - def empty?(url = nil); end - def get_impl(base, value, *args); end - def initialize(options = nil); end - def initialize_copy(other); end - def load(readable, *options); end - def parse(set_cookie, origin, options = nil); end - def save(writable, *options); end - def self.const_missing(name); end - def store; end - include Enumerable -end diff --git a/sorbet/rbi/gems/http-form_data.rbi b/sorbet/rbi/gems/http-form_data.rbi deleted file mode 100644 index 171b618..0000000 --- a/sorbet/rbi/gems/http-form_data.rbi +++ /dev/null @@ -1,76 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/http-form_data/all/http-form_data.rbi -# -# http-form_data-2.3.0 - -module HTTP -end -module HTTP::FormData - def self.create(data, encoder: nil); end - def self.ensure_hash(obj); end - def self.multipart?(data); end -end -module HTTP::FormData::Readable - def read(length = nil, outbuf = nil); end - def rewind; end - def size; end - def to_s; end -end -class HTTP::FormData::Part - def content_type; end - def filename; end - def initialize(body, content_type: nil, filename: nil); end - include HTTP::FormData::Readable -end -class HTTP::FormData::File < HTTP::FormData::Part - def filename_for(io); end - def initialize(path_or_io, opts = nil); end - def make_io(path_or_io); end - def mime_type; end -end -class HTTP::FormData::CompositeIO - def advance_io; end - def current_io; end - def initialize(ios); end - def read(length = nil, outbuf = nil); end - def read_chunks(length = nil); end - def readpartial(max_length = nil); end - def rewind; end - def size; end -end -class HTTP::FormData::Multipart - def boundary; end - def content_length; end - def content_type; end - def glue; end - def initialize(data, boundary: nil); end - def self.generate_boundary; end - def tail; end - include HTTP::FormData::Readable -end -class HTTP::FormData::Multipart::Param - def content_type; end - def filename; end - def footer; end - def header; end - def initialize(name, value); end - def parameters; end - def self.coerce(data); end - include HTTP::FormData::Readable -end -class HTTP::FormData::Urlencoded - def content_length; end - def content_type; end - def initialize(data, encoder: nil); end - def self.encoder; end - def self.encoder=(implementation); end - include HTTP::FormData::Readable -end -class HTTP::FormData::Error < StandardError -end diff --git a/sorbet/rbi/gems/http.rbi b/sorbet/rbi/gems/http.rbi deleted file mode 100644 index b880a44..0000000 --- a/sorbet/rbi/gems/http.rbi +++ /dev/null @@ -1,637 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: true -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/http/all/http.rbi -# -# http-5.1.0 - -module HTTP - def self.[](headers); end - extend HTTP::Chainable -end -class HTTP::Error < StandardError -end -class HTTP::ConnectionError < HTTP::Error -end -class HTTP::RequestError < HTTP::Error -end -class HTTP::ResponseError < HTTP::Error -end -class HTTP::StateError < HTTP::ResponseError -end -class HTTP::TimeoutError < HTTP::Error -end -class HTTP::ConnectTimeoutError < HTTP::TimeoutError -end -class HTTP::HeaderError < HTTP::Error -end -module HTTP::Timeout -end -class HTTP::Timeout::Null - def <<(data); end - def close(*args, **, &block); end - def closed?(*args, **, &block); end - def connect(socket_class, host, port, nodelay = nil); end - def connect_ssl; end - def initialize(options = nil); end - def options; end - def readpartial(size, buffer = nil); end - def rescue_readable(timeout = nil); end - def rescue_writable(timeout = nil); end - def socket; end - def start_tls(host, ssl_socket_class, ssl_context); end - def write(data); end - extend Forwardable -end -class HTTP::Timeout::PerOperation < HTTP::Timeout::Null - def connect(socket_class, host, port, nodelay = nil); end - def connect_ssl; end - def initialize(*args); end - def readpartial(size, buffer = nil); end - def write(data); end -end -class HTTP::Timeout::Global < HTTP::Timeout::Null - def <<(data); end - def connect(socket_class, host, port, nodelay = nil); end - def connect_ssl; end - def initialize(*args); end - def log_time; end - def perform_io; end - def read_nonblock(size, buffer = nil); end - def readpartial(size, buffer = nil); end - def reset_counter; end - def reset_timer; end - def wait_readable_or_timeout; end - def wait_writable_or_timeout; end - def write(data); end - def write_nonblock(data); end -end -class HTTP::Headers - def ==(other); end - def [](name); end - def []=(name, value); end - def add(name, value); end - def delete(name); end - def each; end - def empty?(*args, **, &block); end - def get(name); end - def hash(*args, **, &block); end - def include?(name); end - def initialize; end - def initialize_copy(orig); end - def inspect; end - def keys; end - def merge!(other); end - def merge(other); end - def normalize_header(name); end - def self.[](object); end - def self.coerce(object); end - def set(name, value); end - def to_a; end - def to_h; end - def to_hash; end - def validate_value(value); end - extend Forwardable - include Enumerable -end -module HTTP::Headers::Mixin - def [](*args, **, &block); end - def []=(*args, **, &block); end - def headers; end - extend Forwardable -end -module HTTP::Chainable - def accept(type); end - def auth(value); end - def basic_auth(opts); end - def branch(options); end - def build_request(*args); end - def connect(uri, options = nil); end - def cookies(cookies); end - def default_options; end - def default_options=(opts); end - def delete(uri, options = nil); end - def encoding(encoding); end - def follow(options = nil); end - def get(uri, options = nil); end - def head(uri, options = nil); end - def headers(headers); end - def nodelay; end - def options(uri, options = nil); end - def patch(uri, options = nil); end - def persistent(host, timeout: nil); end - def post(uri, options = nil); end - def put(uri, options = nil); end - def request(*args); end - def through(*proxy); end - def timeout(options); end - def trace(uri, options = nil); end - def use(*features); end - def via(*proxy); end -end -class HTTP::URI - def ==(other); end - def authority(*args, **, &block); end - def authority=(*args, **, &block); end - def dup; end - def eql?(other); end - def fragment(*args, **, &block); end - def fragment=(*args, **, &block); end - def hash; end - def host(*args, **, &block); end - def host=(*args, **, &block); end - def http?; end - def https?; end - def initialize(options_or_uri = nil); end - def inspect; end - def join(*args, **, &block); end - def normalize(*args, **, &block); end - def normalized_authority(*args, **, &block); end - def normalized_fragment(*args, **, &block); end - def normalized_host(*args, **, &block); end - def normalized_password(*args, **, &block); end - def normalized_path(*args, **, &block); end - def normalized_port(*args, **, &block); end - def normalized_query(*args, **, &block); end - def normalized_scheme(*args, **, &block); end - def normalized_user(*args, **, &block); end - def omit(*args, **, &block); end - def origin(*args, **, &block); end - def origin=(*args, **, &block); end - def password(*args, **, &block); end - def password=(*args, **, &block); end - def path(*args, **, &block); end - def path=(*args, **, &block); end - def port; end - def port=(*args, **, &block); end - def query(*args, **, &block); end - def query=(*args, **, &block); end - def query_values(*args, **, &block); end - def query_values=(*args, **, &block); end - def request_uri(*args, **, &block); end - def request_uri=(*args, **, &block); end - def scheme(*args, **, &block); end - def scheme=(*args, **, &block); end - def self.form_encode(form_values, sort = nil); end - def self.parse(uri); end - def to_s; end - def to_str; end - def user(*args, **, &block); end - def user=(*args, **, &block); end - extend Forwardable -end -class HTTP::Options - def []=(option, val); end - def argument_error!(message); end - def body; end - def body=(arg0); end - def cookies; end - def cookies=(arg0); end - def dup; end - def encoding; end - def encoding=(arg0); end - def feature(name); end - def features; end - def features=(features); end - def follow; end - def follow=(value); end - def form; end - def form=(arg0); end - def headers; end - def headers=(arg0); end - def initialize(options = nil); end - def json; end - def json=(arg0); end - def keep_alive_timeout; end - def keep_alive_timeout=(arg0); end - def merge(other); end - def nodelay; end - def nodelay=(arg0); end - def params; end - def params=(arg0); end - def persistent; end - def persistent=(value); end - def persistent?; end - def proxy; end - def proxy=(arg0); end - def response; end - def response=(arg0); end - def self.available_features; end - def self.def_option(name, reader_only: nil, &interpreter); end - def self.default_socket_class; end - def self.default_socket_class=(arg0); end - def self.default_ssl_socket_class; end - def self.default_ssl_socket_class=(arg0); end - def self.default_timeout_class; end - def self.default_timeout_class=(arg0); end - def self.defined_options; end - def self.new(options = nil); end - def self.register_feature(name, impl); end - def socket_class; end - def socket_class=(arg0); end - def ssl; end - def ssl=(arg0); end - def ssl_context; end - def ssl_context=(arg0); end - def ssl_socket_class; end - def ssl_socket_class=(arg0); end - def timeout_class; end - def timeout_class=(arg0); end - def timeout_options; end - def timeout_options=(arg0); end - def to_hash; end - def with_body(value); end - def with_cookies(value); end - def with_encoding(value); end - def with_features(value); end - def with_follow(value); end - def with_form(value); end - def with_headers(value); end - def with_json(value); end - def with_keep_alive_timeout(value); end - def with_nodelay(value); end - def with_params(value); end - def with_persistent(value); end - def with_proxy(value); end - def with_response(value); end - def with_socket_class(value); end - def with_ssl(value); end - def with_ssl_context(value); end - def with_ssl_socket_class(value); end - def with_timeout_class(value); end - def with_timeout_options(value); end -end -module HTTP::Features -end -class HTTP::Features::AutoInflate < HTTP::Feature - def stream_for(connection); end - def supported_encoding?(response); end - def wrap_response(response); end -end -class HTTP::Request - def body; end - def connect_using_proxy(socket); end - def default_host_header_value; end - def headline; end - def host(*args, **, &block); end - def include_proxy_authorization_header; end - def include_proxy_headers; end - def initialize(opts); end - def inspect; end - def port; end - def prepare_body(body); end - def prepare_headers(headers); end - def proxy; end - def proxy_authorization_header; end - def proxy_connect_header; end - def proxy_connect_headers; end - def redirect(uri, verb = nil); end - def scheme; end - def socket_host; end - def socket_port; end - def stream(socket); end - def uri; end - def uri_normalizer; end - def using_authenticated_proxy?; end - def using_proxy?; end - def verb; end - def version; end - extend Forwardable - include HTTP::Headers::Mixin -end -class HTTP::Request::Body - def ==(other); end - def each(&block); end - def initialize(source); end - def rewind(io); end - def size; end - def source; end - def validate_source_type!; end -end -class HTTP::Request::Body::ProcIO - def initialize(block); end - def write(data); end -end -class HTTP::Features::AutoDeflate < HTTP::Feature - def deflated_body(body); end - def initialize(**arg0); end - def method; end - def wrap_request(request); end -end -class HTTP::Features::AutoDeflate::CompressedBody < HTTP::Request::Body - def compress_all!; end - def compressed_each; end - def each(&block); end - def initialize(uncompressed_body); end - def size; end -end -class HTTP::Features::AutoDeflate::GzippedBody < HTTP::Features::AutoDeflate::CompressedBody - def compress(&block); end -end -class HTTP::Features::AutoDeflate::GzippedBody::BlockIO - def initialize(block); end - def write(data); end -end -class HTTP::Features::AutoDeflate::DeflatedBody < HTTP::Features::AutoDeflate::CompressedBody - def compress; end -end -class HTTP::Features::Logging < HTTP::Feature - def initialize(logger: nil); end - def logger; end - def stringify_headers(headers); end - def wrap_request(request); end - def wrap_response(response); end -end -class HTTP::Features::Logging::NullLogger - def debug(*_args); end - def debug?; end - def error(*_args); end - def error?; end - def fatal(*_args); end - def fatal?; end - def info(*_args); end - def info?; end - def warn(*_args); end - def warn?; end -end -class HTTP::Features::Instrumentation < HTTP::Feature - def initialize(instrumenter: nil, namespace: nil); end - def instrumenter; end - def name; end - def wrap_request(request); end - def wrap_response(response); end -end -class HTTP::Features::Instrumentation::NullInstrumenter - def finish(_name, _payload); end - def instrument(name, payload = nil); end - def start(_name, _payload); end -end -class HTTP::Features::NormalizeUri < HTTP::Feature - def initialize(normalizer: nil); end - def normalizer; end -end -class HTTP::Feature - def initialize(opts = nil); end - def on_error(request, error); end - def wrap_request(request); end - def wrap_response(response); end -end -class HTTP::Connection - def close; end - def expired?; end - def failed_proxy_connect?; end - def finish_response; end - def headers(*args, **, &block); end - def http_version(*args, **, &block); end - def initialize(req, options); end - def keep_alive?; end - def proxy_response_headers; end - def read_headers!; end - def read_more(size); end - def readpartial(size = nil); end - def reset_timer; end - def send_proxy_connect_request(req); end - def send_request(req); end - def set_keep_alive; end - def start_tls(req, options); end - def status_code(*args, **, &block); end - extend Forwardable -end -class HTTP::Redirector - def collect_cookies_from_request; end - def collect_cookies_from_response; end - def cookie_jar; end - def endless_loop?; end - def initialize(opts = nil); end - def max_hops; end - def perform(request, response); end - def redirect_to(uri); end - def strict; end - def too_many_hops?; end -end -class HTTP::Redirector::TooManyRedirectsError < HTTP::ResponseError -end -class HTTP::Redirector::EndlessRedirectError < HTTP::Redirector::TooManyRedirectsError -end -class HTTP::Client - def build_request(verb, uri, opts = nil); end - def build_response(req, options); end - def close; end - def initialize(default_options = nil); end - def make_form_data(form); end - def make_request_body(opts, headers); end - def make_request_headers(opts); end - def make_request_uri(uri, opts); end - def perform(request, options); end - def persistent?(*args, **, &block); end - def request(verb, uri, opts = nil); end - def verify_connection!(uri); end - def wrap_request(req, opts); end - extend Forwardable - include HTTP::Chainable -end -class HTTP::Request::Writer - def add_body_type_headers; end - def add_headers; end - def chunked?; end - def connect_through_proxy; end - def each_chunk; end - def encode_chunk(chunk); end - def initialize(socket, body, headers, headline); end - def join_headers; end - def send_request; end - def stream; end - def write(data); end -end -class HTTP::Request::UnsupportedMethodError < HTTP::RequestError -end -class HTTP::Request::UnsupportedSchemeError < HTTP::RequestError -end -class HTTP::ContentType - def charset; end - def charset=(arg0); end - def initialize(mime_type = nil, charset = nil); end - def mime_type; end - def mime_type=(arg0); end - def self.charset(str); end - def self.mime_type(str); end - def self.parse(str); end -end -module HTTP::MimeType - def self.[](type); end - def self.adapters; end - def self.aliases; end - def self.normalize(type); end - def self.register_adapter(type, adapter); end - def self.register_alias(type, shortcut); end -end -class HTTP::MimeType::Adapter - def decode(*arg0); end - def encode(*arg0); end - def self.allocate; end - def self.decode(*args, **, &block); end - def self.encode(*args, **, &block); end - def self.new(*arg0, **); end - extend Singleton::SingletonClassMethods - include Singleton -end -class HTTP::MimeType::JSON < HTTP::MimeType::Adapter - def decode(str); end - def encode(obj); end -end -class HTTP::Response - def body; end - def charset(*args, **, &block); end - def chunked?; end - def code(*args, **, &block); end - def connection(*args, **, &block); end - def content_length; end - def content_type; end - def cookies; end - def default_encoding; end - def flush; end - def init_request(opts); end - def initialize(opts); end - def inspect; end - def mime_type(*args, **, &block); end - def parse(type = nil); end - def proxy_headers; end - def readpartial(*args, **, &block); end - def reason(*args, **, &block); end - def request; end - def status; end - def to_a; end - def to_s(*args, **, &block); end - def to_str(*args, **, &block); end - def uri(*args, **, &block); end - def version; end - extend Forwardable - include HTTP::Headers::Mixin -end -class HTTP::Response::Status < Delegator - def __getobj__; end - def __setobj__(obj); end - def accepted?; end - def already_reported?; end - def bad_gateway?; end - def bad_request?; end - def client_error?; end - def code; end - def conflict?; end - def continue?; end - def created?; end - def expectation_failed?; end - def failed_dependency?; end - def forbidden?; end - def found?; end - def gateway_timeout?; end - def gone?; end - def http_version_not_supported?; end - def im_used?; end - def informational?; end - def inspect; end - def insufficient_storage?; end - def internal_server_error?; end - def length_required?; end - def locked?; end - def loop_detected?; end - def method_not_allowed?; end - def misdirected_request?; end - def moved_permanently?; end - def multi_status?; end - def multiple_choices?; end - def network_authentication_required?; end - def no_content?; end - def non_authoritative_information?; end - def not_acceptable?; end - def not_extended?; end - def not_found?; end - def not_implemented?; end - def not_modified?; end - def ok?; end - def partial_content?; end - def payload_too_large?; end - def payment_required?; end - def permanent_redirect?; end - def precondition_failed?; end - def precondition_required?; end - def processing?; end - def proxy_authentication_required?; end - def range_not_satisfiable?; end - def reason; end - def redirect?; end - def request_header_fields_too_large?; end - def request_timeout?; end - def reset_content?; end - def see_other?; end - def self.[](object); end - def self.coerce(object); end - def self.symbolize(str); end - def server_error?; end - def service_unavailable?; end - def success?; end - def switching_protocols?; end - def temporary_redirect?; end - def to_s; end - def to_sym; end - def too_many_requests?; end - def unauthorized?; end - def unavailable_for_legal_reasons?; end - def unprocessable_entity?; end - def unsupported_media_type?; end - def upgrade_required?; end - def uri_too_long?; end - def use_proxy?; end - def variant_also_negotiates?; end -end -class HTTP::Response::Inflater - def connection; end - def initialize(connection); end - def readpartial(*args); end - def zstream; end -end -class HTTP::Response::Body - def connection; end - def each; end - def empty?(*args, **, &block); end - def find_encoding(encoding); end - def initialize(stream, encoding: nil); end - def inspect; end - def readpartial(*args); end - def stream!; end - def to_s; end - def to_str; end - extend Forwardable - include Enumerable -end -class HTTP::Response::Parser - def <<(data); end - def add(data); end - def add_body(chunk); end - def add_header(name, value); end - def finished?; end - def headers; end - def headers?; end - def http_version; end - def initialize; end - def mark_header_finished; end - def mark_message_finished; end - def parser; end - def read(size); end - def reset; end - def status_code; end -end -class HTTP::Response::Parser::Handler < LLHttp::Delegate - def append_header; end - def initialize(target); end - def on_body(body); end - def on_header_field(field); end - def on_header_value(value); end - def on_headers_complete; end - def on_message_complete; end - def reset; end -end diff --git a/sorbet/rbi/gems/ip3country.rbi b/sorbet/rbi/gems/ip3country.rbi deleted file mode 100644 index a23457e..0000000 --- a/sorbet/rbi/gems/ip3country.rbi +++ /dev/null @@ -1,23 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/ip3country/all/ip3country.rbi -# -# ip3country-0.1.1 - -module CountryLookup - def self.initialize; end - def self.lookup_ip_number(ip_number); end - def self.lookup_ip_string(ip_string); end -end -class CountryLookup::Lookup - def binary_search(value); end - def initialize; end - def initialize_from_file; end - def lookup_ip_number(ip_number); end - def lookup_ip_string(ip_string); end -end diff --git a/sorbet/rbi/gems/llhttp-ffi.rbi b/sorbet/rbi/gems/llhttp-ffi.rbi deleted file mode 100644 index 417615d..0000000 --- a/sorbet/rbi/gems/llhttp-ffi.rbi +++ /dev/null @@ -1,77 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/llhttp-ffi/all/llhttp-ffi.rbi -# -# llhttp-ffi-0.4.0 - -module LLHttp - def llhttp_errno_name(*arg0); end - def llhttp_execute(*arg0); end - def llhttp_finish(*arg0); end - def llhttp_get_error_reason(*arg0); end - def llhttp_reset(*arg0); end - def llhttp_should_keep_alive(*arg0); end - def rb_llhttp_content_length(*arg0); end - def rb_llhttp_free(*arg0); end - def rb_llhttp_http_major(*arg0); end - def rb_llhttp_http_minor(*arg0); end - def rb_llhttp_init(*arg0); end - def rb_llhttp_method_name(*arg0); end - def rb_llhttp_status_code(*arg0); end - def self.llhttp_errno_name(*arg0); end - def self.llhttp_execute(*arg0); end - def self.llhttp_finish(*arg0); end - def self.llhttp_get_error_reason(*arg0); end - def self.llhttp_reset(*arg0); end - def self.llhttp_should_keep_alive(*arg0); end - def self.rb_llhttp_content_length(*arg0); end - def self.rb_llhttp_free(*arg0); end - def self.rb_llhttp_http_major(*arg0); end - def self.rb_llhttp_http_minor(*arg0); end - def self.rb_llhttp_init(*arg0); end - def self.rb_llhttp_method_name(*arg0); end - def self.rb_llhttp_status_code(*arg0); end - def self.version; end - extend FFI::Library -end -class LLHttp::Delegate -end -class LLHttp::Error < StandardError -end -class LLHttp::Parser - def <<(data); end - def build_error(errno); end - def content_length; end - def finish; end - def http_major; end - def http_minor; end - def initialize(delegate, type: nil); end - def keep_alive?; end - def method_name; end - def on_body(buffer, length); end - def on_chunk_complete; end - def on_chunk_header; end - def on_header_field(buffer, length); end - def on_header_field_complete; end - def on_header_value(buffer, length); end - def on_header_value_complete; end - def on_headers_complete; end - def on_message_begin; end - def on_message_complete; end - def on_status(buffer, length); end - def on_status_complete; end - def on_url(buffer, length); end - def on_url_complete; end - def parse(data); end - def reset; end - def self.free(pointer); end - def status_code; end - def type; end -end -class LLHttp::Callbacks < FFI::Struct -end diff --git a/sorbet/rbi/gems/minitest.rbi b/sorbet/rbi/gems/minitest.rbi deleted file mode 100644 index 57e4e0c..0000000 --- a/sorbet/rbi/gems/minitest.rbi +++ /dev/null @@ -1,427 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: true -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/minitest/all/minitest.rbi -# -# minitest-5.16.3 - -module Minitest - def self.__run(reporter, options); end - def self.after_run(&block); end - def self.autorun; end - def self.backtrace_filter; end - def self.backtrace_filter=(arg0); end - def self.cattr_accessor(name); end - def self.clock_time; end - def self.extensions; end - def self.extensions=(arg0); end - def self.filter_backtrace(bt); end - def self.info_signal; end - def self.info_signal=(arg0); end - def self.init_plugins(options); end - def self.load_plugins; end - def self.parallel_executor; end - def self.parallel_executor=(arg0); end - def self.process_args(args = nil); end - def self.reporter; end - def self.reporter=(arg0); end - def self.run(args = nil); end - def self.run_one_method(klass, method_name); end - def self.seed; end - def self.seed=(arg0); end -end -module Minitest::Parallel -end -class Minitest::Parallel::Executor - def <<(work); end - def initialize(size); end - def shutdown; end - def size; end - def start; end -end -module Minitest::Parallel::Test - def _synchronize; end -end -module Minitest::Parallel::Test::ClassMethods - def run_one_method(klass, method_name, reporter); end - def test_order; end -end -module Minitest::Assertions - def _synchronize; end - def assert(test, msg = nil); end - def assert_empty(obj, msg = nil); end - def assert_equal(exp, act, msg = nil); end - def assert_in_delta(exp, act, delta = nil, msg = nil); end - def assert_in_epsilon(exp, act, epsilon = nil, msg = nil); end - def assert_includes(collection, obj, msg = nil); end - def assert_instance_of(cls, obj, msg = nil); end - def assert_kind_of(cls, obj, msg = nil); end - def assert_match(matcher, obj, msg = nil); end - def assert_mock(mock); end - def assert_nil(obj, msg = nil); end - def assert_operator(o1, op, o2 = nil, msg = nil); end - def assert_output(stdout = nil, stderr = nil); end - def assert_path_exists(path, msg = nil); end - def assert_predicate(o1, op, msg = nil); end - def assert_raises(*exp); end - def assert_respond_to(obj, meth, msg = nil); end - def assert_same(exp, act, msg = nil); end - def assert_send(send_ary, m = nil); end - def assert_silent; end - def assert_throws(sym, msg = nil); end - def capture_io; end - def capture_subprocess_io; end - def diff(exp, act); end - def exception_details(e, msg); end - def fail_after(y, m, d, msg); end - def flunk(msg = nil); end - def message(msg = nil, ending = nil, &default); end - def mu_pp(obj); end - def mu_pp_for_diff(obj); end - def pass(_msg = nil); end - def refute(test, msg = nil); end - def refute_empty(obj, msg = nil); end - def refute_equal(exp, act, msg = nil); end - def refute_in_delta(exp, act, delta = nil, msg = nil); end - def refute_in_epsilon(a, b, epsilon = nil, msg = nil); end - def refute_includes(collection, obj, msg = nil); end - def refute_instance_of(cls, obj, msg = nil); end - def refute_kind_of(cls, obj, msg = nil); end - def refute_match(matcher, obj, msg = nil); end - def refute_nil(obj, msg = nil); end - def refute_operator(o1, op, o2 = nil, msg = nil); end - def refute_path_exists(path, msg = nil); end - def refute_predicate(o1, op, msg = nil); end - def refute_respond_to(obj, meth, msg = nil); end - def refute_same(exp, act, msg = nil); end - def self.diff; end - def self.diff=(o); end - def skip(msg = nil, bt = nil); end - def skip_until(y, m, d, msg); end - def skipped?; end - def things_to_diff(exp, act); end -end -class Minitest::Unit - def self.after_tests(&b); end - def self.autorun; end -end -class Minitest::Unit::TestCase < Minitest::Test - def self.inherited(klass); end -end -class Minitest::Test < Minitest::Runnable - def capture_exceptions; end - def class_name; end - def neuter_exception(e); end - def new_exception(klass, msg, bt, kill = nil); end - def run; end - def sanitize_exception(e); end - def self.i_suck_and_my_tests_are_order_dependent!; end - def self.io_lock; end - def self.io_lock=(arg0); end - def self.make_my_diffs_pretty!; end - def self.parallelize_me!; end - def self.runnable_methods; end - def self.test_order; end - def with_info_handler(&block); end - extend Minitest::Guard - include Minitest::Assertions - include Minitest::Guard - include Minitest::Reportable - include Minitest::Test::LifecycleHooks -end -module Minitest::Test::LifecycleHooks - def after_setup; end - def after_teardown; end - def before_setup; end - def before_teardown; end - def setup; end - def teardown; end -end -class Minitest::Runnable - def assertions; end - def assertions=(arg0); end - def failure; end - def failures; end - def failures=(arg0); end - def initialize(name); end - def marshal_dump; end - def marshal_load(ary); end - def name; end - def name=(o); end - def passed?; end - def result_code; end - def run; end - def self.inherited(klass); end - def self.methods_matching(re); end - def self.on_signal(name, action); end - def self.reset; end - def self.run(reporter, options = nil); end - def self.run_one_method(klass, method_name, reporter); end - def self.runnable_methods; end - def self.runnables; end - def self.with_info_handler(reporter, &block); end - def skipped?; end - def time; end - def time=(arg0); end - def time_it; end -end -module Minitest::Reportable - def class_name; end - def error?; end - def location; end - def passed?; end - def result_code; end - def skipped?; end -end -class Minitest::Result < Minitest::Runnable - def class_name; end - def klass; end - def klass=(arg0); end - def self.from(runnable); end - def source_location; end - def source_location=(arg0); end - def to_s; end - include Minitest::Reportable -end -class Minitest::AbstractReporter - def lock; end - def locked?; end - def passed?; end - def prerecord(klass, name); end - def record(result); end - def report; end - def start; end - def synchronize(&block); end - def try_lock; end - def unlock; end - include Mutex_m -end -class Minitest::Reporter < Minitest::AbstractReporter - def initialize(io = nil, options = nil); end - def io; end - def io=(arg0); end - def options; end - def options=(arg0); end -end -class Minitest::ProgressReporter < Minitest::Reporter - def prerecord(klass, name); end - def record(result); end -end -class Minitest::StatisticsReporter < Minitest::Reporter - def assertions; end - def assertions=(arg0); end - def count; end - def count=(arg0); end - def errors; end - def errors=(arg0); end - def failures; end - def failures=(arg0); end - def initialize(io = nil, options = nil); end - def passed?; end - def record(result); end - def report; end - def results; end - def results=(arg0); end - def skips; end - def skips=(arg0); end - def start; end - def start_time; end - def start_time=(arg0); end - def total_time; end - def total_time=(arg0); end -end -class Minitest::SummaryReporter < Minitest::StatisticsReporter - def aggregated_results(io); end - def binary_string; end - def old_sync; end - def old_sync=(arg0); end - def report; end - def start; end - def statistics; end - def summary; end - def sync; end - def sync=(arg0); end - def to_s; end -end -class Minitest::CompositeReporter < Minitest::AbstractReporter - def <<(reporter); end - def initialize(*reporters); end - def io; end - def passed?; end - def prerecord(klass, name); end - def record(result); end - def report; end - def reporters; end - def reporters=(arg0); end - def start; end -end -class Minitest::Assertion < Exception - def error; end - def location; end - def result_code; end - def result_label; end -end -class Minitest::Skip < Minitest::Assertion - def result_label; end -end -class Minitest::UnexpectedError < Minitest::Assertion - def backtrace; end - def error; end - def error=(arg0); end - def initialize(error); end - def message; end - def result_label; end -end -module Minitest::Guard - def jruby?(platform = nil); end - def maglev?(platform = nil); end - def mri?(platform = nil); end - def osx?(platform = nil); end - def rubinius?(platform = nil); end - def windows?(platform = nil); end -end -class Minitest::BacktraceFilter - def filter(bt); end -end -class MockExpectationError < StandardError -end -class Minitest::Mock - def ===(*args, **kwargs, &b); end - def __call(name, data); end - def __respond_to?(*arg0); end - def class(*args, **kwargs, &b); end - def expect(name, retval, args = nil, **kwargs, &blk); end - def initialize(delegator = nil); end - def inspect(*args, **kwargs, &b); end - def instance_eval(*args, **kwargs, &b); end - def instance_variables(*args, **kwargs, &b); end - def method_missing(sym, *args, **kwargs, &block); end - def object_id(*args, **kwargs, &b); end - def public_send(*args, **kwargs, &b); end - def respond_to?(sym, include_private = nil); end - def respond_to_missing?(*args, **kwargs, &b); end - def send(*args, **kwargs, &b); end - def to_s(*args, **kwargs, &b); end - def verify; end -end -class Object < BasicObject - def stub(name, val_or_callable, *block_args, **block_kwargs, &block); end - include Minitest::Expectations -end -module Minitest::Expectations - def must_be(*args); end - def must_be_close_to(*args); end - def must_be_empty(*args); end - def must_be_instance_of(*args); end - def must_be_kind_of(*args); end - def must_be_nil(*args); end - def must_be_same_as(*args); end - def must_be_silent(*args); end - def must_be_within_delta(*args); end - def must_be_within_epsilon(*args); end - def must_equal(*args); end - def must_include(*args); end - def must_match(*args); end - def must_output(*args); end - def must_raise(*args); end - def must_respond_to(*args); end - def must_throw(*args); end - def path_must_exist(*args); end - def path_wont_exist(*args); end - def wont_be(*args); end - def wont_be_close_to(*args); end - def wont_be_empty(*args); end - def wont_be_instance_of(*args); end - def wont_be_kind_of(*args); end - def wont_be_nil(*args); end - def wont_be_same_as(*args); end - def wont_be_within_delta(*args); end - def wont_be_within_epsilon(*args); end - def wont_equal(*args); end - def wont_include(*args); end - def wont_match(*args); end - def wont_respond_to(*args); end -end -class Minitest::Expectation < Struct - def ctx; end - def ctx=(_); end - def must_be(*args); end - def must_be_close_to(*args); end - def must_be_empty(*args); end - def must_be_instance_of(*args); end - def must_be_kind_of(*args); end - def must_be_nil(*args); end - def must_be_same_as(*args); end - def must_be_silent(*args); end - def must_be_within_delta(*args); end - def must_be_within_epsilon(*args); end - def must_equal(*args); end - def must_include(*args); end - def must_match(*args); end - def must_output(*args); end - def must_raise(*args); end - def must_respond_to(*args); end - def must_throw(*args); end - def path_must_exist(*args); end - def path_wont_exist(*args); end - def self.[](*arg0); end - def self.inspect; end - def self.keyword_init?; end - def self.members; end - def self.new(*arg0); end - def target; end - def target=(_); end - def wont_be(*args); end - def wont_be_close_to(*args); end - def wont_be_empty(*args); end - def wont_be_instance_of(*args); end - def wont_be_kind_of(*args); end - def wont_be_nil(*args); end - def wont_be_same_as(*args); end - def wont_be_within_delta(*args); end - def wont_be_within_epsilon(*args); end - def wont_equal(*args); end - def wont_include(*args); end - def wont_match(*args); end - def wont_respond_to(*args); end -end -class Module - def infect_an_assertion(meth, new_name, dont_flip = nil); end -end -module Kernel - def describe(desc, *additional_desc, &block); end -end -class Minitest::Spec < Minitest::Test - def initialize(name); end - def self.current; end - extend Minitest::Spec::DSL - include Minitest::Spec::DSL::InstanceMethods -end -module Minitest::Spec::DSL - def after(_type = nil, &block); end - def before(_type = nil, &block); end - def children; end - def create(name, desc); end - def desc; end - def describe_stack; end - def it(desc = nil, &block); end - def let(name, &block); end - def name; end - def nuke_test_methods!; end - def register_spec_type(*args, &block); end - def self.extended(obj); end - def spec_type(desc, *additional); end - def specify(desc = nil, &block); end - def subject(&block); end - def to_s; end -end -module Minitest::Spec::DSL::InstanceMethods - def _(value = nil, &block); end - def before_setup; end - def expect(value = nil, &block); end - def value(value = nil, &block); end -end diff --git a/sorbet/rbi/gems/public_suffix.rbi b/sorbet/rbi/gems/public_suffix.rbi deleted file mode 100644 index a8d5eba..0000000 --- a/sorbet/rbi/gems/public_suffix.rbi +++ /dev/null @@ -1,105 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: true -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/public_suffix/all/public_suffix.rbi -# -# public_suffix-5.0.0 - -module PublicSuffix - def self.decompose(name, rule); end - def self.domain(name, **options); end - def self.normalize(name); end - def self.parse(name, list: nil, default_rule: nil, ignore_private: nil); end - def self.valid?(name, list: nil, default_rule: nil, ignore_private: nil); end -end -class PublicSuffix::Domain - def domain; end - def domain?; end - def initialize(*args); end - def name; end - def self.name_to_labels(name); end - def sld; end - def subdomain; end - def subdomain?; end - def tld; end - def to_a; end - def to_s; end - def trd; end -end -class PublicSuffix::Error < StandardError -end -class PublicSuffix::DomainInvalid < PublicSuffix::Error -end -class PublicSuffix::DomainNotAllowed < PublicSuffix::DomainInvalid -end -module PublicSuffix::Rule - def self.default; end - def self.factory(content, private: nil); end -end -class PublicSuffix::Rule::Entry < Struct - def length; end - def length=(_); end - def private; end - def private=(_); end - def self.[](*arg0); end - def self.inspect; end - def self.keyword_init?; end - def self.members; end - def self.new(*arg0); end - def type; end - def type=(_); end -end -class PublicSuffix::Rule::Base - def ==(other); end - def decompose(*arg0); end - def eql?(other); end - def initialize(value:, length: nil, private: nil); end - def length; end - def match?(name); end - def parts; end - def private; end - def self.build(content, private: nil); end - def value; end -end -class PublicSuffix::Rule::Normal < PublicSuffix::Rule::Base - def decompose(domain); end - def parts; end - def rule; end -end -class PublicSuffix::Rule::Wildcard < PublicSuffix::Rule::Base - def decompose(domain); end - def initialize(value:, length: nil, private: nil); end - def parts; end - def rule; end - def self.build(content, private: nil); end -end -class PublicSuffix::Rule::Exception < PublicSuffix::Rule::Base - def decompose(domain); end - def parts; end - def rule; end - def self.build(content, private: nil); end -end -class PublicSuffix::List - def <<(rule); end - def ==(other); end - def add(rule); end - def clear; end - def default_rule; end - def each(&block); end - def empty?; end - def entry_to_rule(entry, value); end - def eql?(other); end - def find(name, default: nil, **options); end - def initialize; end - def rule_to_entry(rule); end - def rules; end - def select(name, ignore_private: nil); end - def self.default(**options); end - def self.default=(value); end - def self.parse(input, private_domains: nil); end - def size; end -end diff --git a/sorbet/rbi/gems/rexml.rbi b/sorbet/rbi/gems/rexml.rbi deleted file mode 100644 index 1beacbc..0000000 --- a/sorbet/rbi/gems/rexml.rbi +++ /dev/null @@ -1,612 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/rexml/all/rexml.rbi -# -# rexml-3.2.5 - -module REXML -end -class REXML::ParseException < RuntimeError - def context; end - def continued_exception; end - def continued_exception=(arg0); end - def initialize(message, source = nil, parser = nil, exception = nil); end - def line; end - def parser; end - def parser=(arg0); end - def position; end - def source; end - def source=(arg0); end - def to_s; end -end -class REXML::UndefinedNamespaceException < REXML::ParseException - def initialize(prefix, source, parser); end -end -module REXML::Encoding - def decode(string); end - def encode(string); end - def encoding; end - def encoding=(encoding); end - def find_encoding(name); end -end -class REXML::SourceFactory - def self.create_from(arg); end -end -class REXML::Source - def buffer; end - def consume(pattern); end - def current_line; end - def detect_encoding; end - def empty?; end - def encoding; end - def encoding=(enc); end - def encoding_updated; end - def initialize(arg, encoding = nil); end - def line; end - def match(pattern, cons = nil); end - def match_to(char, pattern); end - def match_to_consume(char, pattern); end - def position; end - def read; end - def scan(pattern, cons = nil); end - include REXML::Encoding -end -class REXML::IOSource < REXML::Source - def consume(pattern); end - def current_line; end - def empty?; end - def encoding_updated; end - def initialize(arg, block_size = nil, encoding = nil); end - def match(pattern, cons = nil); end - def position; end - def read; end - def readline; end - def scan(pattern, cons = nil); end -end -module REXML::Parsers -end -class REXML::Parsers::BaseParser - def add_listener(listener); end - def empty?; end - def entity(reference, entities); end - def has_next?; end - def initialize(source); end - def need_source_encoding_update?(xml_declaration_encoding); end - def normalize(input, entities = nil, entity_filter = nil); end - def parse_attributes(prefixes, curr_ns); end - def parse_id(base_error_message, accept_external_id:, accept_public_id:); end - def parse_id_invalid_details(accept_external_id:, accept_public_id:); end - def parse_name(base_error_message); end - def peek(depth = nil); end - def position; end - def process_instruction; end - def pull; end - def pull_event; end - def source; end - def stream=(source); end - def unnormalize(string, entities = nil, filter = nil); end - def unshift(token); end -end -class REXML::Parsers::StreamParser - def add_listener(listener); end - def initialize(source, listener); end - def parse; end -end -module REXML::XMLTokens -end -module REXML::Light -end -class REXML::Light::Node - def <<(element); end - def =~(path); end - def [](reference, ns = nil); end - def []=(reference, ns, value = nil); end - def children; end - def each; end - def has_name?(name, namespace = nil); end - def initialize(node = nil); end - def local_name; end - def local_name=(name_str); end - def name; end - def name=(name_str, ns = nil); end - def namespace(prefix = nil); end - def namespace=(namespace); end - def namespace_of(node, prefix = nil); end - def namesplit; end - def node_type; end - def parent; end - def parent=(node); end - def prefix(namespace = nil); end - def prefix_of(node, namespace = nil); end - def root; end - def size; end - def text=(foo); end - def to_s; end -end -module REXML::Security - def self.entity_expansion_limit; end - def self.entity_expansion_limit=(val); end - def self.entity_expansion_text_limit; end - def self.entity_expansion_text_limit=(val); end -end -module REXML::Formatters -end -class REXML::Formatters::Default - def initialize(ie_hack = nil); end - def write(node, output); end - def write_cdata(node, output); end - def write_comment(node, output); end - def write_document(node, output); end - def write_element(node, output); end - def write_instruction(node, output); end - def write_text(node, output); end -end -class REXML::Formatters::Pretty < REXML::Formatters::Default - def compact; end - def compact=(arg0); end - def indent_text(string, level = nil, style = nil, indentfirstline = nil); end - def initialize(indentation = nil, ie_hack = nil); end - def width; end - def width=(arg0); end - def wrap(string, width); end - def write_cdata(node, output); end - def write_comment(node, output); end - def write_document(node, output); end - def write_element(node, output); end - def write_text(node, output); end -end -module REXML::Node - def each_recursive(&block); end - def find_first_recursive(&block); end - def indent(to, ind); end - def index_in_parent; end - def next_sibling_node; end - def parent?; end - def previous_sibling_node; end - def to_s(indent = nil); end -end -class REXML::Child - def bytes; end - def document; end - def initialize(parent = nil); end - def next_sibling; end - def next_sibling=(other); end - def parent; end - def parent=(other); end - def previous_sibling; end - def previous_sibling=(other); end - def remove; end - def replace_with(child); end - include REXML::Node -end -class REXML::Entity < REXML::Child - def external; end - def initialize(stream, value = nil, parent = nil, reference = nil); end - def name; end - def ndata; end - def normalized; end - def pubid; end - def ref; end - def self.matches?(string); end - def to_s; end - def unnormalized; end - def value; end - def write(out, indent = nil); end - include REXML::XMLTokens -end -module REXML::EntityConst -end -class REXML::Parent < REXML::Child - def <<(object); end - def [](index); end - def []=(*args); end - def add(object); end - def children; end - def deep_clone; end - def delete(object); end - def delete_at(index); end - def delete_if(&block); end - def each(&block); end - def each_child(&block); end - def each_index(&block); end - def index(child); end - def initialize(parent = nil); end - def insert_after(child1, child2); end - def insert_before(child1, child2); end - def length; end - def parent?; end - def push(object); end - def replace_child(to_replace, replacement); end - def size; end - def to_a; end - def unshift(object); end - include Enumerable -end -module REXML::Namespace - def expanded_name; end - def fully_expanded_name; end - def has_name?(other, ns = nil); end - def local_name; end - def name; end - def name=(name); end - def prefix; end - def prefix=(arg0); end - include REXML::XMLTokens -end -class REXML::AttlistDecl < REXML::Child - def [](key); end - def each(&block); end - def element_name; end - def include?(key); end - def initialize(source); end - def node_type; end - def write(out, indent = nil); end - include Enumerable -end -class REXML::ReferenceWriter - def initialize(id_type, public_id_literal, system_literal, context = nil); end - def write(output); end -end -class REXML::DocType < REXML::Parent - def add(child); end - def attribute_of(element, attribute); end - def attributes_of(element); end - def clone; end - def context; end - def entities; end - def entity(name); end - def external_id; end - def initialize(first, parent = nil); end - def name; end - def namespaces; end - def node_type; end - def notation(name); end - def notations; end - def public; end - def system; end - def write(output, indent = nil, transitive = nil, ie_hack = nil); end - include REXML::XMLTokens -end -class REXML::Declaration < REXML::Child - def initialize(src); end - def to_s; end - def write(output, indent); end -end -class REXML::ElementDecl < REXML::Declaration - def initialize(src); end -end -class REXML::ExternalEntity < REXML::Child - def initialize(src); end - def to_s; end - def write(output, indent); end -end -class REXML::NotationDecl < REXML::Child - def initialize(name, middle, pub, sys); end - def name; end - def public; end - def public=(arg0); end - def system; end - def system=(arg0); end - def to_s; end - def write(output, indent = nil); end -end -class REXML::Text < REXML::Child - def <<(to_append); end - def <=>(other); end - def clear_cache; end - def clone; end - def doctype; end - def empty?; end - def indent_text(string, level = nil, style = nil, indentfirstline = nil); end - def initialize(arg, respect_whitespace = nil, parent = nil, raw = nil, entity_filter = nil, illegal = nil); end - def inspect; end - def node_type; end - def parent=(parent); end - def raw; end - def raw=(arg0); end - def self.check(string, pattern, doctype); end - def self.expand(ref, doctype, filter); end - def self.normalize(input, doctype = nil, entity_filter = nil); end - def self.read_with_substitution(input, illegal = nil); end - def self.unnormalize(string, doctype = nil, filter = nil, illegal = nil); end - def to_s; end - def value; end - def value=(val); end - def wrap(string, width, addnewline = nil); end - def write(writer, indent = nil, transitive = nil, ie_hack = nil); end - def write_with_substitution(out, input); end - def xpath; end - include Comparable -end -class REXML::Attribute - def ==(other); end - def clone; end - def doctype; end - def element; end - def element=(element); end - def hash; end - def initialize(first, second = nil, parent = nil); end - def inspect; end - def namespace(arg = nil); end - def node_type; end - def normalized=(arg0); end - def prefix; end - def remove; end - def to_s; end - def to_string; end - def value; end - def write(output, indent = nil); end - def xpath; end - include REXML::Namespace - include REXML::Node -end -class REXML::CData < REXML::Text - def clone; end - def initialize(first, whitespace = nil, parent = nil); end - def to_s; end - def value; end - def write(output = nil, indent = nil, transitive = nil, ie_hack = nil); end -end -module REXML::Functions -end -class REXML::Parsers::XPathParser - def AdditiveExpr(path, parsed); end - def AndExpr(path, parsed); end - def EqualityExpr(path, parsed); end - def FilterExpr(path, parsed); end - def FunctionCall(rest, parsed); end - def LocationPath(path, parsed); end - def MultiplicativeExpr(path, parsed); end - def NodeTest(path, parsed); end - def OrExpr(path, parsed); end - def PathExpr(path, parsed); end - def Predicate(path, parsed); end - def PrimaryExpr(path, parsed); end - def RelationalExpr(path, parsed); end - def RelativeLocationPath(path, parsed); end - def UnaryExpr(path, parsed); end - def UnionExpr(path, parsed); end - def abbreviate(path); end - def expand(path); end - def get_group(string); end - def namespaces=(namespaces); end - def parse(path); end - def parse_args(string); end - def predicate(path); end - def predicate_to_string(path, &block); end - include REXML::XMLTokens -end -module REXML::DClonable -end -class REXML::XPathParser - def []=(variable_name, value); end - def child(nodeset); end - def compare(a, operator, b); end - def descendant(nodeset, include_self); end - def descendant_recursive(raw_node, new_nodeset, new_nodes, include_self); end - def each_unnode(nodeset); end - def enter(tag, *args); end - def equality_relational_compare(set1, op, set2); end - def evaluate_predicate(expression, nodesets); end - def expr(path_stack, nodeset, context = nil); end - def filter_nodeset(nodeset); end - def first(path_stack, node); end - def following(node); end - def following_node_of(node); end - def get_first(path, nodeset); end - def get_namespace(node, prefix); end - def initialize(strict: nil); end - def leave(tag, *args); end - def match(path_stack, nodeset); end - def namespaces=(namespaces = nil); end - def next_sibling_node(node); end - def node_test(path_stack, nodesets, any_type: nil); end - def norm(b); end - def normalize_compare_values(a, operator, b); end - def parse(path, nodeset); end - def preceding(node); end - def preceding_node_of(node); end - def predicate(path, nodeset); end - def sort(array_of_nodes, order); end - def step(path_stack, any_type: nil, order: nil); end - def strict?; end - def trace(*args); end - def unnode(nodeset); end - def value_type(value); end - def variables=(vars = nil); end - include REXML::XMLTokens -end -class REXML::XPathNode - def context; end - def initialize(node, context = nil); end - def position; end - def raw_node; end -end -class REXML::XPath - def self.each(element, path = nil, namespaces = nil, variables = nil, options = nil, &block); end - def self.first(element, path = nil, namespaces = nil, variables = nil, options = nil); end - def self.match(element, path = nil, namespaces = nil, variables = nil, options = nil); end - include REXML::Functions -end -class REXML::Element < REXML::Parent - def [](name_or_index); end - def __to_xpath_helper(node); end - def add_attribute(key, value = nil); end - def add_attributes(hash); end - def add_element(element, attrs = nil); end - def add_namespace(prefix, uri = nil); end - def add_text(text); end - def attribute(name, namespace = nil); end - def attributes; end - def cdatas; end - def clone; end - def comments; end - def context; end - def context=(arg0); end - def delete_attribute(key); end - def delete_element(element); end - def delete_namespace(namespace = nil); end - def document; end - def each_element(xpath = nil, &block); end - def each_element_with_attribute(key, value = nil, max = nil, name = nil, &block); end - def each_element_with_text(text = nil, max = nil, name = nil, &block); end - def each_with_something(test, max = nil, name = nil); end - def elements; end - def get_elements(xpath); end - def get_text(path = nil); end - def has_attributes?; end - def has_elements?; end - def has_text?; end - def ignore_whitespace_nodes; end - def initialize(arg = nil, parent = nil, context = nil); end - def inspect; end - def instructions; end - def namespace(prefix = nil); end - def namespaces; end - def next_element; end - def node_type; end - def prefixes; end - def previous_element; end - def raw; end - def root; end - def root_node; end - def text(path = nil); end - def text=(text); end - def texts; end - def whitespace; end - def write(output = nil, indent = nil, transitive = nil, ie_hack = nil); end - def xpath; end - include REXML::Namespace -end -class REXML::Elements - def <<(element = nil); end - def [](index, name = nil); end - def []=(index, element); end - def add(element = nil); end - def collect(xpath = nil); end - def delete(element); end - def delete_all(xpath); end - def each(xpath = nil); end - def empty?; end - def index(element); end - def initialize(parent); end - def inject(xpath = nil, initial = nil); end - def literalize(name); end - def parent; end - def size; end - def to_a(xpath = nil); end - include Enumerable -end -class REXML::Attributes < Hash - def <<(attribute); end - def [](name); end - def []=(name, value); end - def add(attribute); end - def delete(attribute); end - def delete_all(name); end - def each; end - def each_attribute; end - def get_attribute(name); end - def get_attribute_ns(namespace, name); end - def initialize(element); end - def length; end - def namespaces; end - def prefixes; end - def size; end - def to_a; end -end -class REXML::XMLDecl < REXML::Child - def ==(other); end - def clone; end - def content(enc); end - def dowrite; end - def encoding=(enc); end - def initialize(version = nil, encoding = nil, standalone = nil); end - def inspect; end - def node_type; end - def nowrite; end - def old_enc=(encoding); end - def self.default; end - def stand_alone?; end - def standalone; end - def standalone=(arg0); end - def version; end - def version=(arg0); end - def write(writer, indent = nil, transitive = nil, ie_hack = nil); end - def writeencoding; end - def writethis; end - def xmldecl(version, encoding, standalone); end - include REXML::Encoding -end -class REXML::Comment < REXML::Child - def <=>(other); end - def ==(other); end - def clone; end - def initialize(first, second = nil); end - def node_type; end - def string; end - def string=(arg0); end - def to_s; end - def write(output, indent = nil, transitive = nil, ie_hack = nil); end - include Comparable -end -class REXML::Instruction < REXML::Child - def ==(other); end - def clone; end - def content; end - def content=(arg0); end - def initialize(target, content = nil); end - def inspect; end - def node_type; end - def target; end - def target=(arg0); end - def write(writer, indent = nil, transitive = nil, ie_hack = nil); end -end -class REXML::Output - def <<(content); end - def encoding; end - def initialize(real_IO, encd = nil); end - def to_s; end - include REXML::Encoding -end -module REXML::Validation -end -class REXML::Validation::ValidationException < RuntimeError - def initialize(msg); end -end -class REXML::Parsers::TreeParser - def add_listener(listener); end - def initialize(source, build_context = nil); end - def parse; end -end -class REXML::Document < REXML::Element - def <<(child); end - def add(child); end - def add_element(arg = nil, arg2 = nil); end - def build(source); end - def clone; end - def doctype; end - def document; end - def encoding; end - def entity_expansion_count; end - def expanded_name; end - def initialize(source = nil, context = nil); end - def name; end - def node_type; end - def record_entity_expansion; end - def root; end - def self.entity_expansion_limit; end - def self.entity_expansion_limit=(val); end - def self.entity_expansion_text_limit; end - def self.entity_expansion_text_limit=(val); end - def self.parse_stream(source, listener); end - def stand_alone?; end - def version; end - def write(*arguments); end - def xml_decl; end -end diff --git a/sorbet/rbi/gems/spy.rbi b/sorbet/rbi/gems/spy.rbi deleted file mode 100644 index 90b1f07..0000000 --- a/sorbet/rbi/gems/spy.rbi +++ /dev/null @@ -1,166 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/spy/all/spy.rbi -# -# spy-1.0.3 - -module Spy - def self.create_and_hook_spy(base_object, method_name, singleton_method = nil); end - def self.get(base_object, *method_names); end - def self.get_const(base_module, *constant_names); end - def self.mock(klass, *stubs); end - def self.mock_all(klass, *stubs); end - def self.off(base_object, *method_names); end - def self.off_const(base_module, *constant_names); end - def self.off_instance_method(base_class, *method_names); end - def self.on(base_object, *method_names); end - def self.on_const(base_module, *constant_names); end - def self.on_instance_method(base_class, *method_names); end - def self.teardown; end -end -class Spy::Error < StandardError -end -class Spy::AlreadyStubbedError < Spy::Error -end -class Spy::AlreadyHookedError < Spy::Error -end -class Spy::NotHookedError < Spy::Error -end -class Spy::NeverHookedError < Spy::Error -end -class Spy::NoSpyError < Spy::Error -end -module Marshal - def self.dump_with_mocks(*args); end - def self.dump_without_mocks(*arg0); end -end -class Spy::Agency - def active?(spy); end - def check_spy!(spy); end - def clear!; end - def dissolve!; end - def find(id); end - def initialize; end - def recruit(spy); end - def retire(spy); end - def self.allocate; end - def self.new(*arg0, **); end - def spies; end - extend Singleton::SingletonClassMethods - include Singleton -end -module Spy::API - def assert_received(base_object, method_name); end - def assert_received_with(base_object, method_name, *args, &block); end - def have_received(method_name); end -end -class Spy::API::DidNotReceiveError < Spy::Error -end -class Spy::API::HaveReceived - def actual; end - def args_message; end - def description; end - def failure_message_for_should; end - def failure_message_for_should_not; end - def initialize(method_name); end - def matches?(actual); end - def method_name; end - def spy; end - def with(*args, &block); end -end -module Spy::Base -end -class Spy::CallLog - def args; end - def block; end - def called_from; end - def initialize(object, called_from, args, block, result); end - def object; end - def result; end -end -class Spy::Constant - def and_hide; end - def and_return(value); end - def base_module; end - def constant_name; end - def currently_defined?; end - def hidden?; end - def hook(opts = nil); end - def hooked?; end - def initialize(base_module, constant_name); end - def name; end - def original_value; end - def previously_defined?; end - def self.get(base_module, constant_name); end - def self.off(base_module, constant_name); end - def self.on(base_module, constant_name); end - def unhook; end - include Spy::Base -end -module Spy::Mock - def initialize(&mock_method); end - def instance_of?(other); end - def method(method_name); end - def self.args_for_method(method); end - def self.classes_to_override_methods(mod); end - def self.get_inherited_methods(klass_ancestors, visibility); end - def self.included(mod); end - def self.new(klass); end - include Spy::Base -end -class Spy::Nest - def add(spy); end - def base_module; end - def get(constant_name); end - def hooked?(constant_name); end - def hooked_constants; end - def initialize(base_module); end - def remove(spy); end - def self.all; end - def self.fetch(base_module); end - def self.get(base_module); end -end -class Spy::Subroutine - def and_call_through; end - def and_raise(exception = nil, message = nil); end - def and_return(value = nil, &block); end - def and_throw(*args); end - def and_yield(*args); end - def arity_range; end - def base_object; end - def build_call_through_plan(object); end - def call_plan(plan, block, *args); end - def calls; end - def check_arity!(arity); end - def check_for_too_many_arguments!(block); end - def clear_method!; end - def current_method; end - def has_been_called?; end - def has_been_called_with?(*args, &block); end - def hook(opts = nil); end - def hook_opts; end - def hooked?; end - def initialize(object, method_name, singleton_method = nil); end - def invoke(object, args, block, called_from); end - def method_name; end - def method_owner; end - def method_visibility_of(method_name, all = nil); end - def original_method; end - def original_method_visibility; end - def override_method; end - def reset!; end - def ruby_27_last_arg_hash?(args); end - def self.get(base_object, method_name, singleton_method = nil); end - def self.get_spies(base_object, singleton_methods = nil); end - def self.get_spy_id(method); end - def self.off(base_object, method_name, singleton_method = nil); end - def self.on(base_object, method_name, singleton_method = nil); end - def singleton_method; end - def unhook; end - include Spy::Base -end diff --git a/sorbet/rbi/gems/statsig.rbi b/sorbet/rbi/gems/statsig.rbi deleted file mode 100644 index 6e4d28e..0000000 --- a/sorbet/rbi/gems/statsig.rbi +++ /dev/null @@ -1,28 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: false -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/statsig/all/statsig.rbi -# -# statsig-1.16.2 - -module Statsig - def self.check_gate(*args, **, &blk); end - def self.ensure_initialized; end - def self.get_client_initialize_response(*args, **, &blk); end - def self.get_config(*args, **, &blk); end - def self.get_experiment(*args, **, &blk); end - def self.get_layer(*args, **, &blk); end - def self.get_statsig_metadata(*args, **, &blk); end - def self.initialize(*args, **, &blk); end - def self.log_event(*args, **, &blk); end - def self.override_config(*args, **, &blk); end - def self.override_gate(*args, **, &blk); end - def self.shutdown(*args, **, &blk); end - extend T::Private::Methods::MethodHooks - extend T::Private::Methods::SingletonMethodHooks - extend T::Sig -end diff --git a/sorbet/rbi/gems/unf.rbi b/sorbet/rbi/gems/unf.rbi deleted file mode 100644 index 7cab774..0000000 --- a/sorbet/rbi/gems/unf.rbi +++ /dev/null @@ -1,19 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/unf/all/unf.rbi -# -# unf-0.1.4 - -module UNF -end -class String - def to_nfc; end - def to_nfd; end - def to_nfkc; end - def to_nfkd; end -end diff --git a/sorbet/rbi/gems/user_agent_parser.rbi b/sorbet/rbi/gems/user_agent_parser.rbi deleted file mode 100644 index c5baa19..0000000 --- a/sorbet/rbi/gems/user_agent_parser.rbi +++ /dev/null @@ -1,81 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/user_agent_parser/all/user_agent_parser.rbi -# -# user_agent_parser-2.11.0 - -module UserAgentParser - def self.parse(user_agent_string, options = nil); end -end -class UserAgentParser::Parser - def device_from_pattern_match(pattern, match); end - def first_pattern_match(patterns, value); end - def from_pattern_match(keys, pattern, match); end - def initialize(options = nil); end - def interpolate(replacement, match); end - def load_patterns(path); end - def os_from_pattern_match(pattern, match); end - def parse(user_agent); end - def parse_device(user_agent); end - def parse_os(user_agent); end - def parse_ua(user_agent, os = nil, device = nil); end - def patterns_path; end - def user_agent_from_pattern_match(pattern, match, os = nil, device = nil); end - def version_from_segments(*segments); end -end -class UserAgentParser::UserAgent - def ==(other); end - def device; end - def eql?(other); end - def family; end - def initialize(family = nil, version = nil, os = nil, device = nil); end - def inspect; end - def name; end - def os; end - def to_h; end - def to_s; end - def version; end -end -class UserAgentParser::Version - def <=>(other); end - def eql?(other); end - def initialize(*args); end - def inspect; end - def major; end - def minor; end - def patch; end - def patch_minor; end - def segments; end - def to_h; end - def to_s; end - def version; end - include Comparable -end -class UserAgentParser::OperatingSystem - def ==(other); end - def eql?(other); end - def family; end - def initialize(family = nil, version = nil); end - def inspect; end - def name; end - def to_h; end - def to_s; end - def version; end -end -class UserAgentParser::Device - def ==(other); end - def brand; end - def eql?(other); end - def family; end - def initialize(family = nil, model = nil, brand = nil); end - def inspect; end - def model; end - def name; end - def to_h; end - def to_s; end -end diff --git a/sorbet/rbi/gems/webmock.rbi b/sorbet/rbi/gems/webmock.rbi deleted file mode 100644 index 059c761..0000000 --- a/sorbet/rbi/gems/webmock.rbi +++ /dev/null @@ -1,542 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi gems - -# typed: strict -# -# If you would like to make changes to this file, great! Please create the gem's shim here: -# -# https://github.com/sorbet/sorbet-typed/new/master?filename=lib/webmock/all/webmock.rbi -# -# webmock-3.18.1 - -module WebMock - def after_request(*args, &block); end - def allow_net_connect!(*args, &block); end - def disable_net_connect!(*args, &block); end - def net_connect_allowed?(*args, &block); end - def registered_request?(*args, &block); end - def reset_callbacks(*args, &block); end - def reset_webmock(*args, &block); end - def self.after_request(options = nil, &block); end - def self.allow_net_connect!(options = nil); end - def self.disable!(options = nil); end - def self.disable_net_connect!(options = nil); end - def self.disallow_net_connect!(options = nil); end - def self.enable!; end - def self.enable_net_connect!(options = nil); end - def self.globally_stub_request(order = nil, &block); end - def self.hide_body_diff!; end - def self.hide_stubbing_instructions!; end - def self.included(clazz); end - def self.net_connect_allowed?(uri = nil); end - def self.net_connect_explicit_allowed?(allowed, uri = nil); end - def self.net_http_connect_on_start?(uri); end - def self.print_executed_requests; end - def self.registered_request?(request_signature); end - def self.request(method, uri); end - def self.reset!; end - def self.reset_callbacks; end - def self.reset_webmock; end - def self.show_body_diff!; end - def self.show_body_diff?; end - def self.show_stubbing_instructions!; end - def self.show_stubbing_instructions?; end - def self.version; end - extend WebMock::API - include WebMock::API -end -class WebMock::Deprecation - def self.warning(message); end -end -class WebMock::NetConnectNotAllowedError < Exception - def initialize(request_signature); end -end -module WebMock::Util -end -class WebMock::Util::QueryMapper - def self.collect_query_hash(query_array, empty_accumulator, options); end - def self.collect_query_parts(query); end - def self.dehash(hash); end - def self.fill_accumulator_for_dot(accumulator, key, value); end - def self.fill_accumulator_for_flat(accumulator, key, value); end - def self.fill_accumulator_for_flat_array(accumulator, key, value); end - def self.fill_accumulator_for_subscript(accumulator, key, value); end - def self.normalize_query_hash(query_hash, empty_accumulator, options); end - def self.query_to_values(query, options = nil); end - def self.to_query(parent, value, options = nil); end - def self.values_to_query(new_query_values, options = nil); end -end -class WebMock::Util::URI - def self.encode_unsafe_chars_in_userinfo(userinfo); end - def self.heuristic_parse(uri); end - def self.is_uri_localhost?(uri); end - def self.normalize_uri(uri); end - def self.sort_query_values(query_values); end - def self.strip_default_port_from_uri_string(uri_string); end - def self.uris_encoded_and_unencoded(uris); end - def self.uris_with_inferred_port_and_without(uris); end - def self.uris_with_scheme_and_without(uris); end - def self.uris_with_trailing_slash_and_without(uris); end - def self.variations_of_uri_as_strings(uri_object, only_with_scheme: nil); end -end -module WebMock::Util::URI::CharacterClasses -end -class WebMock::Util::Headers - def self.basic_auth_header(*credentials); end - def self.decode_userinfo_from_header(header); end - def self.normalize_headers(headers); end - def self.pp_headers_string(headers); end - def self.sorted_headers_string(headers); end -end -class WebMock::Util::HashCounter - def each(&block); end - def get(key); end - def hash; end - def hash=(arg0); end - def initialize; end - def put(key, num = nil); end - def select(&block); end -end -class WebMock::Util::HashKeysStringifier - def self.stringify_keys!(arg, options = nil); end -end -class WebMock::Util::ValuesStringifier - def self.stringify_values(value); end -end -class WebMock::Util::JSON - def self.convert_json_to_yaml(json); end - def self.parse(json); end - def self.unescape(str); end -end -class WebMock::Util::JSON::ParseError < StandardError -end -class WebMock::VersionChecker - def check_version!; end - def colorize(text, color_code); end - def compare_version; end - def initialize(library_name, library_version, min_patch_level, max_minor_version = nil, unsupported_versions = nil); end - def parse_version(version); end - def too_high?; end - def too_low?; end - def unsupported_version?; end - def version_requirement; end - def warn_about_too_high; end - def warn_about_too_low; end - def warn_about_unsupported_version; end - def warn_in_red(text); end -end -class WebMock::HashValidator - def initialize(hash); end - def validate_keys(*valid_keys); end -end -module WebMock::Matchers -end -class WebMock::Matchers::HashArgumentMatcher - def ==(_actual, &block); end - def initialize(expected); end - def self.from_rspec_matcher(matcher); end -end -class WebMock::Matchers::HashExcludingMatcher < WebMock::Matchers::HashArgumentMatcher - def ==(actual); end - def inspect; end -end -class WebMock::Matchers::HashIncludingMatcher < WebMock::Matchers::HashArgumentMatcher - def ==(actual); end - def inspect; end -end -class WebMock::Matchers::AnyArgMatcher - def ==(other); end - def initialize(ignore); end -end -module WebMock::RSpecMatcherDetector - def rSpecHashExcludingMatcher?(matcher); end - def rSpecHashIncludingMatcher?(matcher); end -end -class WebMock::RequestPattern - def assign_options(options); end - def body_pattern; end - def create_uri_pattern(uri); end - def headers_pattern; end - def initialize(method, uri, options = nil); end - def matches?(request_signature); end - def method_pattern; end - def set_basic_auth_as_headers!(options); end - def to_s; end - def uri_pattern; end - def validate_basic_auth!(basic_auth); end - def with(options = nil, &block); end -end -class WebMock::MethodPattern - def initialize(pattern); end - def matches?(method); end - def to_s; end -end -class WebMock::URIPattern - def add_query_params(query_params); end - def initialize(pattern); end - def matches?(uri); end - def pattern_inspect; end - def query_params_matches?(uri); end - def to_s; end - include WebMock::RSpecMatcherDetector -end -class WebMock::URICallablePattern < WebMock::URIPattern - def pattern_matches?(uri); end -end -class WebMock::URIRegexpPattern < WebMock::URIPattern - def pattern_matches?(uri); end -end -class WebMock::URIAddressablePattern < WebMock::URIPattern - def add_query_params(query_params); end - def matches_with_variations?(uri); end - def pattern_inspect; end - def pattern_matches?(uri); end - def template_matches_uri?(template, uri); end -end -class WebMock::URIStringPattern < WebMock::URIPattern - def add_query_params(query_params); end - def pattern_inspect; end - def pattern_matches?(uri); end -end -class WebMock::BodyPattern - def assert_non_multipart_body(content_type); end - def body_as_hash(body, content_type); end - def body_format(content_type); end - def empty_string?(string); end - def initialize(pattern); end - def matches?(body, content_type = nil); end - def matching_body_array?(query_parameters, pattern, content_type); end - def matching_body_hashes?(query_parameters, pattern, content_type); end - def matching_values(actual, expected, content_type); end - def normalize_hash(hash); end - def pattern; end - def to_s; end - def url_encoded_body?(content_type); end - include WebMock::RSpecMatcherDetector -end -class WebMock::HeadersPattern - def empty_headers?(headers); end - def initialize(pattern); end - def matches?(headers); end - def pp_to_s; end - def to_s; end -end -class WebMock::RequestSignature - def ==(other); end - def assign_options(options); end - def body; end - def body=(arg0); end - def eql?(other); end - def hash; end - def headers; end - def headers=(headers); end - def initialize(method, uri, options = nil); end - def json_headers?; end - def method; end - def method=(arg0); end - def to_s; end - def uri; end - def uri=(arg0); end - def url_encoded?; end -end -class WebMock::ResponsesSequence - def end?; end - def increase_position; end - def initialize(responses); end - def next_response; end - def times_to_repeat; end - def times_to_repeat=(arg0); end -end -class WebMock::RequestStub - def and_raise(*exceptions); end - def and_return(*response_hashes, &block); end - def and_return_json(*response_hashes); end - def and_timeout; end - def has_responses?; end - def initialize(method, uri); end - def matches?(request_signature); end - def request_pattern; end - def request_pattern=(arg0); end - def response; end - def self.from_request_signature(signature); end - def then; end - def times(number); end - def to_rack(app, options = nil); end - def to_raise(*exceptions); end - def to_return(*response_hashes, &block); end - def to_return_json(*response_hashes); end - def to_s; end - def to_timeout; end - def with(params = nil, &block); end -end -class WebMock::ResponseFactory - def self.response_for(options); end -end -class WebMock::Response - def ==(other); end - def assert_valid_body!; end - def body; end - def body=(body); end - def evaluate(request_signature); end - def exception; end - def exception=(exception); end - def headers; end - def headers=(headers); end - def initialize(options = nil); end - def options=(options); end - def raise_error_if_any; end - def read_raw_response(io); end - def should_timeout; end - def status; end - def status=(status); end - def stringify_body!; end -end -class WebMock::Response::InvalidBody < StandardError -end -class WebMock::DynamicResponse < WebMock::Response - def evaluate(request_signature); end - def initialize(responder); end - def responder; end - def responder=(arg0); end -end -class WebMock::RackResponse < WebMock::Response - def body_from_rack_response(response); end - def build_rack_env(request); end - def evaluate(request); end - def initialize(app); end - def session; end - def session_options; end -end -class WebMock::StubRequestSnippet - def body_pattern; end - def initialize(request_stub); end - def to_s(with_response = nil); end -end -class WebMock::RequestSignatureSnippet - def add_body_diff(stub, text); end - def initialize(request_signature); end - def pretty_print_to_string(string_to_print); end - def request_params; end - def request_signature; end - def request_stub; end - def request_stubs; end - def signature_stub_body_diff(stub); end - def stubbing_instructions; end -end -class WebMock::RequestBodyDiff - def body_diff; end - def initialize(request_signature, request_stub); end - def parseable_json?(body_pattern); end - def request_signature; end - def request_signature_body_hash; end - def request_signature_diffable?; end - def request_signature_parseable_json?; end - def request_stub; end - def request_stub_body; end - def request_stub_body_hash; end - def request_stub_diffable?; end - def request_stub_parseable_json?; end -end -class WebMock::AssertionFailure - def self.error_class; end - def self.error_class=(arg0); end - def self.failure(message); end -end -class WebMock::RequestExecutionVerifier - def at_least_times_executed; end - def at_least_times_executed=(arg0); end - def at_most_times_executed; end - def at_most_times_executed=(arg0); end - def description; end - def does_not_match?; end - def expected_times_executed; end - def expected_times_executed=(arg0); end - def failure_message; end - def failure_message_phrase(is_negated = nil); end - def failure_message_when_negated; end - def initialize(request_pattern = nil, expected_times_executed = nil, at_least_times_executed = nil, at_most_times_executed = nil); end - def matches?; end - def quantity_phrase(is_negated = nil); end - def request_pattern; end - def request_pattern=(arg0); end - def self.executed_requests_message; end - def times(times); end - def times_executed; end - def times_executed=(arg0); end -end -class WebMock::Config - def allow; end - def allow=(arg0); end - def allow_localhost; end - def allow_localhost=(arg0); end - def allow_net_connect; end - def allow_net_connect=(arg0); end - def initialize; end - def net_http_connect_on_start; end - def net_http_connect_on_start=(arg0); end - def query_values_notation; end - def query_values_notation=(arg0); end - def self.allocate; end - def self.new(*arg0, **); end - def show_body_diff; end - def show_body_diff=(arg0); end - def show_stubbing_instructions; end - def show_stubbing_instructions=(arg0); end - extend Singleton::SingletonClassMethods - include Singleton -end -class WebMock::CallbackRegistry - def self.add_callback(options, block); end - def self.any_callbacks?; end - def self.callbacks; end - def self.invoke_callbacks(options, request_signature, response); end - def self.reset; end -end -class WebMock::RequestRegistry - def initialize; end - def requested_signatures; end - def requested_signatures=(arg0); end - def reset!; end - def self.allocate; end - def self.new(*arg0, **); end - def times_executed(request_pattern); end - def to_s; end - extend Singleton::SingletonClassMethods - include Singleton -end -class WebMock::StubRegistry - def evaluate_response_for_request(response, request_signature); end - def global_stubs; end - def initialize; end - def register_global_stub(order = nil, &block); end - def register_request_stub(stub); end - def registered_request?(request_signature); end - def remove_request_stub(stub); end - def request_stub_for(request_signature); end - def request_stubs; end - def request_stubs=(arg0); end - def reset!; end - def response_for_request(request_signature); end - def self.allocate; end - def self.new(*arg0, **); end - extend Singleton::SingletonClassMethods - include Singleton -end -module WebMock::API - def a_request(method, uri); end - def anythingize_lonely_keys(*args); end - def assert_not_requested(*args, &block); end - def assert_request_not_requested(request, options = nil); end - def assert_request_requested(request, options = nil); end - def assert_requested(*args, &block); end - def convert_uri_method_and_options_to_request_and_options(method, uri, options, &block); end - def hash_excluding(*args); end - def hash_including(*args); end - def refute_requested(*args, &block); end - def remove_request_stub(stub); end - def reset_executed_requests!; end - def self.request(method, uri); end - def stub_http_request(method, uri); end - def stub_request(method, uri); end - extend WebMock::API -end -class WebMock::HttpLibAdapterRegistry - def each_adapter(&block); end - def http_lib_adapters; end - def http_lib_adapters=(arg0); end - def initialize; end - def register(lib, adapter); end - def self.allocate; end - def self.new(*arg0, **); end - extend Singleton::SingletonClassMethods - include Singleton -end -class WebMock::HttpLibAdapter - def self.adapter_for(lib); end -end -module Net -end -module Net::WebMockHTTPResponse - def read_body(dest = nil, &block); end -end -module WebMock::HttpLibAdapters -end -class WebMock::HttpLibAdapters::NetHttpAdapter < WebMock::HttpLibAdapter - def self.disable!; end - def self.enable!; end -end -class StubSocket - def close; end - def closed?; end - def continue_timeout; end - def continue_timeout=(arg0); end - def initialize(*args); end - def io; end - def read_timeout; end - def read_timeout=(arg0); end - def readuntil(*args); end - def write_timeout; end - def write_timeout=(arg0); end -end -class StubSocket::StubIO - def cipher; end - def peer_cert; end - def peeraddr; end - def setsockopt(*args); end - def ssl_version; end -end -module WebMock::NetHTTPUtility - def self.check_right_http_connection; end - def self.get_uri(net_http, path = nil); end - def self.puts_warning_for_right_http_if_needed; end - def self.request_signature_from_request(net_http, request, body = nil); end -end -module HTTP -end -class HTTP::Client - def __perform__(req, options); end - def webmock_enabled?; end -end -class HTTP::Request - def webmock_signature; end -end -class HTTP::Response - def self.from_webmock(request, webmock_response, request_signature = nil); end - def self.normalize_uri(uri); end - def to_webmock; end -end -class HTTP::Response::Streamer - def close; end - def initialize(str, encoding: nil); end - def readpartial(size = nil, outbuf = nil); end - def sequence_id; end -end -class HTTP::WebMockPerform - def exec; end - def halt; end - def initialize(request, options, &perform); end - def invoke_callbacks(webmock_response, options = nil); end - def perform; end - def raise_timeout_error; end - def register_request(signature); end - def replay; end - def request_signature; end - def response_for_request(signature); end -end -class WebMock::HttpLibAdapters::HttpRbAdapter < WebMock::HttpLibAdapter - def self.disable!; end - def self.enable!; end - def self.enabled?; end -end -class Minitest::Test < Minitest::Runnable - def assert_request_not_requested(*args); end - def assert_request_not_requested_with_assertions_count(*args); end - def assert_request_not_requested_without_assertions_count(request, options = nil); end - def assert_request_requested(*args); end - def assert_request_requested_with_assertions_count(*args); end - def assert_request_requested_without_assertions_count(request, options = nil); end - def teardown; end - def teardown_with_webmock; end - def teardown_without_webmock; end - include WebMock::API -end diff --git a/sorbet/rbi/hidden-definitions/hidden.rbi b/sorbet/rbi/hidden-definitions/hidden.rbi deleted file mode 100644 index a0c034a..0000000 --- a/sorbet/rbi/hidden-definitions/hidden.rbi +++ /dev/null @@ -1,6491 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi hidden-definitions - -# typed: autogenerated - -module Addressable::IDNA - ACE_MAX_LENGTH = ::T.let(nil, ::T.untyped) - ACE_PREFIX = ::T.let(nil, ::T.untyped) - COMPOSITION_TABLE = ::T.let(nil, ::T.untyped) - HANGUL_LBASE = ::T.let(nil, ::T.untyped) - HANGUL_LCOUNT = ::T.let(nil, ::T.untyped) - HANGUL_NCOUNT = ::T.let(nil, ::T.untyped) - HANGUL_SBASE = ::T.let(nil, ::T.untyped) - HANGUL_SCOUNT = ::T.let(nil, ::T.untyped) - HANGUL_TBASE = ::T.let(nil, ::T.untyped) - HANGUL_TCOUNT = ::T.let(nil, ::T.untyped) - HANGUL_VBASE = ::T.let(nil, ::T.untyped) - HANGUL_VCOUNT = ::T.let(nil, ::T.untyped) - PUNYCODE_BASE = ::T.let(nil, ::T.untyped) - PUNYCODE_DAMP = ::T.let(nil, ::T.untyped) - PUNYCODE_DELIMITER = ::T.let(nil, ::T.untyped) - PUNYCODE_INITIAL_BIAS = ::T.let(nil, ::T.untyped) - PUNYCODE_INITIAL_N = ::T.let(nil, ::T.untyped) - PUNYCODE_MAXINT = ::T.let(nil, ::T.untyped) - PUNYCODE_PRINT_ASCII = ::T.let(nil, ::T.untyped) - PUNYCODE_SKEW = ::T.let(nil, ::T.untyped) - PUNYCODE_TMAX = ::T.let(nil, ::T.untyped) - PUNYCODE_TMIN = ::T.let(nil, ::T.untyped) - UNICODE_DATA = ::T.let(nil, ::T.untyped) - UNICODE_DATA_CANONICAL = ::T.let(nil, ::T.untyped) - UNICODE_DATA_COMBINING_CLASS = ::T.let(nil, ::T.untyped) - UNICODE_DATA_COMPATIBILITY = ::T.let(nil, ::T.untyped) - UNICODE_DATA_EXCLUSION = ::T.let(nil, ::T.untyped) - UNICODE_DATA_LOWERCASE = ::T.let(nil, ::T.untyped) - UNICODE_DATA_TITLECASE = ::T.let(nil, ::T.untyped) - UNICODE_DATA_UPPERCASE = ::T.let(nil, ::T.untyped) - UNICODE_MAX_LENGTH = ::T.let(nil, ::T.untyped) - UNICODE_TABLE = ::T.let(nil, ::T.untyped) - UTF8_REGEX = ::T.let(nil, ::T.untyped) - UTF8_REGEX_MULTIBYTE = ::T.let(nil, ::T.untyped) -end - -class Addressable::Template - EXPRESSION = ::T.let(nil, ::T.untyped) - JOINERS = ::T.let(nil, ::T.untyped) - LEADERS = ::T.let(nil, ::T.untyped) - RESERVED = ::T.let(nil, ::T.untyped) - UNRESERVED = ::T.let(nil, ::T.untyped) - VARIABLE_LIST = ::T.let(nil, ::T.untyped) - VARNAME = ::T.let(nil, ::T.untyped) - VARSPEC = ::T.let(nil, ::T.untyped) -end - -class Addressable::URI - EMPTY_STR = ::T.let(nil, ::T.untyped) - NORMPATH = ::T.let(nil, ::T.untyped) - PARENT = ::T.let(nil, ::T.untyped) - PORT_MAPPING = ::T.let(nil, ::T.untyped) - RULE_2A = ::T.let(nil, ::T.untyped) - RULE_2B_2C = ::T.let(nil, ::T.untyped) - RULE_2D = ::T.let(nil, ::T.untyped) - RULE_PREFIXED_PARENT = ::T.let(nil, ::T.untyped) - SELF_REF = ::T.let(nil, ::T.untyped) - SEQUENCE_ENCODING_TABLE = ::T.let(nil, ::T.untyped) - SEQUENCE_UPCASED_PERCENT_ENCODING_TABLE = ::T.let(nil, ::T.untyped) - SLASH = ::T.let(nil, ::T.untyped) - URIREGEX = ::T.let(nil, ::T.untyped) -end - -module Addressable::URI::CharacterClasses - ALPHA = ::T.let(nil, ::T.untyped) - AUTHORITY = ::T.let(nil, ::T.untyped) - DIGIT = ::T.let(nil, ::T.untyped) - FRAGMENT = ::T.let(nil, ::T.untyped) - GEN_DELIMS = ::T.let(nil, ::T.untyped) - HOST = ::T.let(nil, ::T.untyped) - PATH = ::T.let(nil, ::T.untyped) - PCHAR = ::T.let(nil, ::T.untyped) - QUERY = ::T.let(nil, ::T.untyped) - RESERVED = ::T.let(nil, ::T.untyped) - SCHEME = ::T.let(nil, ::T.untyped) - SUB_DELIMS = ::T.let(nil, ::T.untyped) - UNRESERVED = ::T.let(nil, ::T.untyped) -end - -module Addressable::URI::NormalizeCharacterClasses - FRAGMENT = ::T.let(nil, ::T.untyped) - HOST = ::T.let(nil, ::T.untyped) - PCHAR = ::T.let(nil, ::T.untyped) - QUERY = ::T.let(nil, ::T.untyped) - SCHEME = ::T.let(nil, ::T.untyped) - UNRESERVED = ::T.let(nil, ::T.untyped) -end - -module Addressable::VERSION - MAJOR = ::T.let(nil, ::T.untyped) - MINOR = ::T.let(nil, ::T.untyped) - STRING = ::T.let(nil, ::T.untyped) - TINY = ::T.let(nil, ::T.untyped) -end - -class Addrinfo - def connect_internal(local_addrinfo, timeout=T.unsafe(nil)); end -end - -class Array - include ::JSON::Ext::Generator::GeneratorMethods::Array - def deconstruct(); end - - def intersect?(arg); end - - def shelljoin(); end - - def to_h(); end -end - -class Array - def self.try_convert(arg); end -end - -class BadClass - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -BasicObject::BasicObject = BasicObject - -class BigDecimal - def clone(); end - - def n_significant_digits(); end - - def precision(); end - - def precision_scale(); end - - def scale(); end - EXCEPTION_NaN = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -class BigDecimal - def self.interpret_loosely(arg); end -end - -class Binding - def clone(); end - - def irb(); end -end - -class Bundler::APIResponseInvalidDependenciesError - def status_code(); end -end - -class Bundler::APIResponseInvalidDependenciesError -end - -class Bundler::CurrentRuby - def jruby_30?(); end - - def jruby_3?(); end - - def maglev_30?(); end - - def maglev_3?(); end - - def mingw_30?(); end - - def mingw_3?(); end - - def mri_30?(); end - - def mri_3?(); end - - def mswin64_30?(); end - - def mswin64_3?(); end - - def mswin_30?(); end - - def mswin_3?(); end - - def on_30?(); end - - def on_3?(); end - - def rbx_30?(); end - - def rbx_3?(); end - - def ruby_30?(); end - - def ruby_3?(); end - - def truffleruby_30?(); end - - def truffleruby_3?(); end - - def x64_mingw_30?(); end - - def x64_mingw_3?(); end -end - -class Bundler::Definition - def dependencies_for(groups); end - - def locked_dependencies(); end - - def most_specific_locked_platform(); end - - def requested_dependencies(); end - - def resolve_only_locally!(); end -end - -class Bundler::Definition - def self.no_lock(); end - - def self.no_lock=(no_lock); end -end - -class Bundler::DepProxy - def clone(); end -end - -class Bundler::DepProxy - def self.get_proxy(dep, platform); end -end - -class Bundler::Dependency - def branch(); end - - def expanded_platforms(); end - - def git(); end - - def github(); end - - def ref(); end -end - -Bundler::Deprecate = Gem::Deprecate - -module Bundler::Digest - SHA1_MASK = ::T.let(nil, ::T.untyped) - SHA1_WORDS = ::T.let(nil, ::T.untyped) -end - -module Bundler::Digest - def self.sha1(string); end -end - -class Bundler::Dsl - def check_primary_source_safety(); end - GITHUB_PULL_REQUEST_URL = ::T.let(nil, ::T.untyped) -end - -class Bundler::Env -end - -class Bundler::Env - def self.environment(); end - - def self.report(options=T.unsafe(nil)); end - - def self.write(io); end -end - -class Bundler::EnvironmentPreserver - def replace_with_backup(); end -end - -class Bundler::EnvironmentPreserver - def self.env_to_hash(env); end - - def self.from_env(); end -end - -class Bundler::Fetcher - def fetch_spec(spec); end - - def fetchers(); end - - def http_proxy(); end - - def initialize(remote); end - - def specs(gem_names, source); end - - def specs_with_retry(gem_names, source); end - - def uri(); end - - def use_api(); end - - def user_agent(); end - FAIL_ERRORS = ::T.let(nil, ::T.untyped) - FETCHERS = ::T.let(nil, ::T.untyped) - HTTP_ERRORS = ::T.let(nil, ::T.untyped) - NET_ERRORS = ::T.let(nil, ::T.untyped) -end - -class Bundler::Fetcher::AuthenticationRequiredError - def initialize(remote_uri); end -end - -class Bundler::Fetcher::BadAuthenticationError - def initialize(remote_uri); end -end - -class Bundler::Fetcher::Base - def api_fetcher?(); end - - def available?(); end - - def display_uri(); end - - def downloader(); end - - def fetch_uri(); end - - def initialize(downloader, remote, display_uri); end - - def remote(); end - - def remote_uri(); end -end - -class Bundler::Fetcher::Base -end - -class Bundler::Fetcher::CertificateFailureError - def initialize(remote_uri); end -end - -class Bundler::Fetcher::CompactIndex - def available?(*args, &blk); end - - def specs(*args, &blk); end - - def specs_for_names(gem_names); end -end - -class Bundler::Fetcher::CompactIndex::ClientFetcher - def call(path, headers); end - - def fetcher(); end - - def fetcher=(_); end - - def ui(); end - - def ui=(_); end -end - -class Bundler::Fetcher::CompactIndex::ClientFetcher - def self.[](*arg); end - - def self.keyword_init?(); end - - def self.members(); end -end - -class Bundler::Fetcher::CompactIndex - def self.compact_index_request(method_name); end -end - -class Bundler::Fetcher::Dependency - def dependency_api_uri(gem_names=T.unsafe(nil)); end - - def dependency_specs(gem_names); end - - def get_formatted_specs_and_deps(gem_list); end - - def specs(gem_names, full_dependency_list=T.unsafe(nil), last_spec_list=T.unsafe(nil)); end - - def unmarshalled_dep_gems(gem_names); end -end - -class Bundler::Fetcher::Dependency -end - -class Bundler::Fetcher::Downloader - def connection(); end - - def fetch(uri, headers=T.unsafe(nil), counter=T.unsafe(nil)); end - - def initialize(connection, redirect_limit); end - - def redirect_limit(); end - - def request(uri, headers); end -end - -class Bundler::Fetcher::Downloader -end - -class Bundler::Fetcher::Index - def specs(_gem_names); end -end - -class Bundler::Fetcher::Index -end - -class Bundler::Fetcher::SSLError - def initialize(msg=T.unsafe(nil)); end -end - -class Bundler::Fetcher::TooManyRequestsError -end - -class Bundler::Fetcher::TooManyRequestsError -end - -class Bundler::Fetcher - def self.api_timeout(); end - - def self.api_timeout=(api_timeout); end - - def self.disable_endpoint(); end - - def self.disable_endpoint=(disable_endpoint); end - - def self.max_retries(); end - - def self.max_retries=(max_retries); end - - def self.redirect_limit(); end - - def self.redirect_limit=(redirect_limit); end -end - -module Bundler::FileUtils - VERSION = ::T.let(nil, ::T.untyped) -end - -class Bundler::FileUtils::Entry_ - def link(dest); end -end - -module Bundler::FileUtils - def self.cp_lr(src, dest, noop: T.unsafe(nil), verbose: T.unsafe(nil), dereference_root: T.unsafe(nil), remove_destination: T.unsafe(nil)); end - - def self.link_entry(src, dest, dereference_root=T.unsafe(nil), remove_destination=T.unsafe(nil)); end -end - -class Bundler::GemHelper - def allowed_push_host(); end - - def already_tagged?(); end - - def base(); end - - def build_checksum(built_gem_path=T.unsafe(nil)); end - - def build_gem(); end - - def built_gem_path(); end - - def clean?(); end - - def committed?(); end - - def current_branch(); end - - def default_remote(); end - - def gem_command(); end - - def gem_key(); end - - def gem_push?(); end - - def gem_push_host(); end - - def gemspec(); end - - def git_push(remote=T.unsafe(nil)); end - - def guard_clean(); end - - def initialize(base=T.unsafe(nil), name=T.unsafe(nil)); end - - def install(); end - - def install_gem(built_gem_path=T.unsafe(nil), local=T.unsafe(nil)); end - - def name(); end - - def rubygem_push(path); end - - def sh(cmd, &block); end - - def sh_with_input(cmd); end - - def sh_with_status(cmd, &block); end - - def spec_path(); end - - def tag_prefix=(tag_prefix); end - - def tag_version(); end - - def version(); end - - def version_tag(); end -end - -class Bundler::GemHelper - def self.gemspec(&block); end - - def self.install_tasks(opts=T.unsafe(nil)); end - - def self.instance(); end - - def self.instance=(instance); end - - def self.tag_prefix=(prefix); end -end - -class Bundler::GemHelpers::PlatformMatch - def self.specificity_score(spec_platform, user_platform); end -end - -module Bundler::GemHelpers - def self.local_platform(); end - - def self.same_deps(spec, exemplary_spec); end - - def self.same_specificity(platform, spec, exemplary_spec); end -end - -class Bundler::GemVersionPromoter - def initialize(locked_specs=T.unsafe(nil), unlock_gems=T.unsafe(nil)); end - - def level(); end - - def level=(value); end - - def locked_specs(); end - - def major?(); end - - def minor?(); end - - def prerelease_specified(); end - - def prerelease_specified=(prerelease_specified); end - - def sort_versions(dep, spec_groups); end - - def strict(); end - - def strict=(strict); end - - def unlock_gems(); end - DEBUG = ::T.let(nil, ::T.untyped) -end - -class Bundler::GemVersionPromoter -end - -class Bundler::Graph - def edge_options(); end - - def groups(); end - - def initialize(env, output_file, show_version=T.unsafe(nil), show_requirements=T.unsafe(nil), output_format=T.unsafe(nil), without=T.unsafe(nil)); end - - def node_options(); end - - def output_file(); end - - def output_format(); end - - def relations(); end - - def viz(); end - GRAPH_NAME = ::T.let(nil, ::T.untyped) -end - -class Bundler::Graph::GraphVizClient - def g(); end - - def initialize(graph_instance); end - - def run(); end -end - -class Bundler::Graph::GraphVizClient -end - -class Bundler::Graph -end - -class Bundler::Index - include ::Enumerable -end - -class Bundler::Injector - def initialize(deps, options=T.unsafe(nil)); end - - def inject(gemfile_path, lockfile_path); end - - def remove(gemfile_path, lockfile_path); end - INJECTED_GEMS = ::T.let(nil, ::T.untyped) -end - -class Bundler::Injector - def self.inject(new_deps, options=T.unsafe(nil)); end - - def self.remove(gems, options=T.unsafe(nil)); end -end - -class Bundler::LazySpecification - def eql?(other); end - - def platform_string(); end -end - -class Bundler::LockfileParser - def self.bundled_with(); end -end - -module Bundler::Molinillo::SpecificationProvider - def dependencies_equal?(dependencies, other_dependencies); end -end - -class Bundler::PermissionError - def parent_folder(); end - - def permission_type(); end -end - -module Bundler::Plugin::API::Source - def ==(other); end - - def add_dependency_names(names); end - - def app_cache_dirname(); end - - def app_cache_path(custom_path=T.unsafe(nil)); end - - def cache(spec, custom_path=T.unsafe(nil)); end - - def cached!(); end - - def can_lock?(spec); end - - def dependency_names(); end - - def dependency_names=(dependency_names); end - - def double_check_for(*arg); end - - def eql?(other); end - - def fetch_gemspec_files(); end - - def gem_install_dir(); end - - def hash(); end - - def identifier(); end - - def include?(other); end - - def initialize(opts); end - - def install(spec, opts); end - - def install_path(); end - - def installed?(); end - - def local!(); end - - def name(); end - - def options(); end - - def options_to_lock(); end - - def post_install(spec, disable_exts=T.unsafe(nil)); end - - def remote!(); end - - def root(); end - - def spec_names(); end - - def specs(); end - - def to_lock(); end - - def to_s(); end - - def unlock!(); end - - def unmet_deps(); end - - def uri(); end - - def uri_hash(); end -end - -module Bundler::Plugin::API::Source -end - -module Bundler::Plugin::Events - GEM_AFTER_INSTALL = ::T.let(nil, ::T.untyped) - GEM_AFTER_INSTALL_ALL = ::T.let(nil, ::T.untyped) - GEM_BEFORE_INSTALL = ::T.let(nil, ::T.untyped) - GEM_BEFORE_INSTALL_ALL = ::T.let(nil, ::T.untyped) -end - -class Bundler::Plugin::Index - def installed_plugins(); end - - def plugin_commands(plugin); end - - def unregister_plugin(name); end -end - -class Bundler::Plugin::Index::CommandConflict - def initialize(plugin, commands); end -end - -class Bundler::Plugin::Index::CommandConflict -end - -class Bundler::Plugin::Index::SourceConflict - def initialize(plugin, sources); end -end - -class Bundler::Plugin::Index::SourceConflict -end - -class Bundler::Plugin::Installer - def install(names, options); end - - def install_definition(definition); end -end - -class Bundler::Plugin::Installer::Git - def generate_bin(spec, disable_extensions=T.unsafe(nil)); end -end - -class Bundler::Plugin::Installer::Git -end - -class Bundler::Plugin::Installer::Rubygems -end - -class Bundler::Plugin::Installer::Rubygems -end - -class Bundler::Plugin::Installer -end - -class Bundler::Plugin::PluginInstallError -end - -class Bundler::Plugin::PluginInstallError -end - -class Bundler::Plugin::SourceList -end - -class Bundler::Plugin::SourceList -end - -module Bundler::Plugin - def self.list(); end - - def self.save_plugin(name, spec, optional_plugin=T.unsafe(nil)); end - - def self.uninstall(names, options); end -end - -class Bundler::ProcessLock -end - -class Bundler::ProcessLock - def self.lock(bundle_path=T.unsafe(nil)); end -end - -class Bundler::RemoteSpecification - def required_rubygems_version(); end -end - -class Bundler::Resolver - include ::Bundler::GemHelpers - def results_for(dependency, base); end - - def source_for(name); end -end - -class Bundler::Resolver::SpecGroup - def activated_platforms(); end - - def activated_platforms=(activated_platforms); end - - def sorted_activated_platforms(); end -end - -class Bundler::Resolver::SpecGroup - def self.create_for(specs, all_platforms, specific_platform); end -end - -class Bundler::Retry - def attempt(&block); end - - def attempts(&block); end - - def current_run(); end - - def current_run=(current_run); end - - def initialize(name, exceptions=T.unsafe(nil), retries=T.unsafe(nil)); end - - def name(); end - - def name=(name); end - - def total_runs(); end - - def total_runs=(total_runs); end -end - -class Bundler::Retry - def self.attempts(); end - - def self.default_attempts(); end - - def self.default_retries(); end -end - -class Bundler::RubygemsIntegration - def add_default_gems_to(specs); end - - def add_to_load_path(paths); end - - def all_specs(); end - - def backport_ext_builder_monitor(); end - - def correct_for_windows_path(path); end - - def default_stubs(); end - - def find_bundler(version); end - - def find_name(name); end - - def gem_remote_fetcher(); end - - def load_env_plugins(); end - - def plain_specs(); end - - def plain_specs=(specs); end - - def stub_rubygems(specs); end - - def supports_bundler_trampolining?(); end -end - -class Bundler::SelfManager - def install_locked_bundler_and_restart_with_it_if_needed(); end - - def restart_with_locked_bundler_if_needed(); end - - def update_bundler_and_restart_with_it_if_needed(target); end -end - -class Bundler::SelfManager -end - -class Bundler::Settings - def processor_count(); end - STRING_KEYS = ::T.let(nil, ::T.untyped) -end - -class Bundler::Settings::Mirror - def ==(other); end - - def fallback_timeout(); end - - def fallback_timeout=(timeout); end - - def initialize(uri=T.unsafe(nil), fallback_timeout=T.unsafe(nil)); end - - def uri(); end - - def uri=(uri); end - - def valid?(); end - - def validate!(probe=T.unsafe(nil)); end - DEFAULT_FALLBACK_TIMEOUT = ::T.let(nil, ::T.untyped) -end - -class Bundler::Settings::Mirror -end - -class Bundler::Settings::Mirrors - def each(&blk); end - - def for(uri); end - - def initialize(prober=T.unsafe(nil)); end - - def parse(key, value); end -end - -class Bundler::Settings::Mirrors -end - -class Bundler::Settings::Path - def self.keyword_init?(); end -end - -class Bundler::Settings::Validator -end - -class Bundler::Settings::Validator::Rule - def description(); end - - def fail!(key, value, *reasons); end - - def initialize(keys, description, &validate); end - - def k(key); end - - def set(settings, key, value, *reasons); end - - def validate!(key, value, settings); end -end - -class Bundler::Settings::Validator::Rule -end - -class Bundler::Settings::Validator - def self.validate!(key, value, settings); end -end - -class Bundler::Settings - def self.key_for(key); end -end - -class Bundler::Source - def add_dependency_names(names); end - - def cached!(); end - - def identifier(); end - - def local!(); end - - def local_only!(); end - - def remote!(); end - - def spec_names(); end -end - -class Bundler::Source::Git - def glob(); end - - def local?(); end -end - -class Bundler::Source::Rubygems - def default_cache_path_for(dir); end - - def dependency_api_available?(); end - - def multiple_remotes?(); end - - def no_remotes?(); end - - def remote_names(); end -end - -class Bundler::Source::RubygemsAggregate - def identifier(); end - - def initialize(sources, source_map); end - - def source_map(); end - - def sources(); end - - def specs(); end -end - -class Bundler::Source::RubygemsAggregate -end - -class Bundler::SourceList - def add_global_rubygems_remote(uri); end - - def aggregate_global_source?(); end - - def expired_sources?(replacement_sources); end - - def global_path_source(); end - - def implicit_global_source?(); end - - def local_only!(); end - - def lock_other_sources(); end - - def lock_rubygems_sources(); end - - def merged_gem_lockfile_sections!(replacement_source); end - - def merged_gem_lockfile_sections?(); end - - def non_default_explicit_sources(); end - - def non_global_rubygems_sources(); end -end - -class Bundler::SourceMap - def all_requirements(); end - - def dependencies(); end - - def direct_requirements(); end - - def initialize(sources, dependencies, locked_specs); end - - def locked_requirements(); end - - def locked_specs(); end - - def pinned_spec_names(skip=T.unsafe(nil)); end - - def sources(); end -end - -class Bundler::SourceMap -end - -class Bundler::SpecSet - include ::Enumerable - include ::Bundler::TSort - def missing_specs(); end -end - -class Bundler::StubSpecification - def extensions(); end - - def gem_build_complete_path(); end - - def manually_installed?(); end -end - -module Bundler::TSort - def each_strongly_connected_component(&block); end - - def each_strongly_connected_component_from(node, id_map=T.unsafe(nil), stack=T.unsafe(nil), &block); end - - def strongly_connected_components(); end - - def tsort(); end - - def tsort_each(&block); end - - def tsort_each_child(node); end - - def tsort_each_node(); end -end - -class Bundler::TSort::Cyclic -end - -class Bundler::TSort::Cyclic -end - -module Bundler::TSort - def self.each_strongly_connected_component(each_node, each_child); end - - def self.each_strongly_connected_component_from(node, each_child, id_map=T.unsafe(nil), stack=T.unsafe(nil)); end - - def self.strongly_connected_components(each_node, each_child); end - - def self.tsort(each_node, each_child); end - - def self.tsort_each(each_node, each_child); end -end - -class Bundler::Thor - include ::Bundler::Thor::Base - include ::Bundler::Thor::Invocation - include ::Bundler::Thor::Shell - def help(command=T.unsafe(nil), subcommand=T.unsafe(nil)); end - HELP_MAPPINGS = ::T.let(nil, ::T.untyped) - TEMPLATE_EXTNAME = ::T.let(nil, ::T.untyped) - THOR_RESERVED_WORDS = ::T.let(nil, ::T.untyped) -end - -module Bundler::Thor::Actions - def _cleanup_options_and_set(options, key); end - - def _shared_configuration(); end - - def action(instance); end - - def add_file(destination, *args, &block); end - - def add_link(destination, *args); end - - def append_file(path, *args, &block); end - - def append_to_file(path, *args, &block); end - - def apply(path, config=T.unsafe(nil)); end - - def behavior(); end - - def behavior=(behavior); end - - def chmod(path, mode, config=T.unsafe(nil)); end - - def comment_lines(path, flag, *args); end - - def copy_file(source, *args, &block); end - - def create_file(destination, *args, &block); end - - def create_link(destination, *args); end - - def destination_root(); end - - def destination_root=(root); end - - def directory(source, *args, &block); end - - def empty_directory(destination, config=T.unsafe(nil)); end - - def find_in_source_paths(file); end - - def get(source, *args, &block); end - - def gsub_file(path, flag, *args, &block); end - - def in_root(); end - - def initialize(args=T.unsafe(nil), options=T.unsafe(nil), config=T.unsafe(nil)); end - - def inject_into_class(path, klass, *args, &block); end - - def inject_into_file(destination, *args, &block); end - - def inject_into_module(path, module_name, *args, &block); end - - def insert_into_file(destination, *args, &block); end - - def inside(dir=T.unsafe(nil), config=T.unsafe(nil), &block); end - - def link_file(source, *args); end - - def prepend_file(path, *args, &block); end - - def prepend_to_file(path, *args, &block); end - - def relative_to_original_destination_root(path, remove_dot=T.unsafe(nil)); end - - def remove_dir(path, config=T.unsafe(nil)); end - - def remove_file(path, config=T.unsafe(nil)); end - - def run(command, config=T.unsafe(nil)); end - - def run_ruby_script(command, config=T.unsafe(nil)); end - - def source_paths(); end - - def template(source, *args, &block); end - - def thor(command, *args); end - - def uncomment_lines(path, flag, *args); end - WARNINGS = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Actions::CapturableERB -end - -class Bundler::Thor::Actions::CapturableERB -end - -module Bundler::Thor::Actions::ClassMethods - def add_runtime_options!(); end - - def source_paths(); end - - def source_paths_for_search(); end - - def source_root(path=T.unsafe(nil)); end -end - -module Bundler::Thor::Actions::ClassMethods -end - -class Bundler::Thor::Actions::CreateFile - def data(); end - - def force_on_collision?(); end - - def force_or_skip_or_conflict(force, skip, &block); end - - def identical?(); end - - def initialize(base, destination, data, config=T.unsafe(nil)); end - - def on_conflict_behavior(&block); end - - def render(); end -end - -class Bundler::Thor::Actions::CreateFile -end - -class Bundler::Thor::Actions::CreateLink -end - -class Bundler::Thor::Actions::CreateLink -end - -class Bundler::Thor::Actions::Directory - def execute!(); end - - def file_level_lookup(previous_lookup); end - - def files(lookup); end - - def initialize(base, source, destination=T.unsafe(nil), config=T.unsafe(nil), &block); end - - def source(); end -end - -class Bundler::Thor::Actions::Directory -end - -class Bundler::Thor::Actions::EmptyDirectory - def base(); end - - def config(); end - - def convert_encoded_instructions(filename); end - - def destination(); end - - def destination=(destination); end - - def exists?(); end - - def given_destination(); end - - def initialize(base, destination, config=T.unsafe(nil)); end - - def invoke!(); end - - def invoke_with_conflict_check(&block); end - - def on_conflict_behavior(); end - - def on_file_clash_behavior(); end - - def pretend?(); end - - def relative_destination(); end - - def revoke!(); end - - def say_status(status, color); end -end - -class Bundler::Thor::Actions::EmptyDirectory -end - -class Bundler::Thor::Actions::InjectIntoFile - def behavior(); end - - def flag(); end - - def initialize(base, destination, data, config); end - - def replace!(regexp, string, force); end - - def replacement(); end - - def say_status(behavior, warning: T.unsafe(nil), color: T.unsafe(nil)); end -end - -class Bundler::Thor::Actions::InjectIntoFile -end - -module Bundler::Thor::Actions - def self.included(base); end -end - -class Bundler::Thor::AmbiguousCommandError -end - -class Bundler::Thor::AmbiguousCommandError -end - -Bundler::Thor::AmbiguousTaskError = Bundler::Thor::AmbiguousCommandError - -class Bundler::Thor::Argument - def banner(); end - - def default(); end - - def default_banner(); end - - def description(); end - - def enum(); end - - def human_name(); end - - def initialize(name, options=T.unsafe(nil)); end - - def name(); end - - def required(); end - - def required?(); end - - def show_default?(); end - - def type(); end - - def usage(); end - - def valid_type?(type); end - - def validate!(); end - VALID_TYPES = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Argument -end - -class Bundler::Thor::Arguments - def initialize(arguments=T.unsafe(nil)); end - - def parse(args); end - - def remaining(); end - NUMERIC = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Arguments - def self.parse(*args); end - - def self.split(args); end -end - -module Bundler::Thor::Base - def args(); end - - def args=(args); end - - def initialize(args=T.unsafe(nil), local_options=T.unsafe(nil), config=T.unsafe(nil)); end - - def options(); end - - def options=(options); end - - def parent_options(); end - - def parent_options=(parent_options); end -end - -module Bundler::Thor::Base::ClassMethods - def all_commands(); end - - def all_tasks(); end - - def allow_incompatible_default_type!(); end - - def argument(name, options=T.unsafe(nil)); end - - def arguments(); end - - def attr_accessor(*arg); end - - def attr_reader(*arg); end - - def attr_writer(*arg); end - - def baseclass(); end - - def basename(); end - - def build_option(name, options, scope); end - - def build_options(options, scope); end - - def check_default_type(); end - - def check_default_type!(); end - - def check_unknown_options(); end - - def check_unknown_options!(); end - - def check_unknown_options?(config); end - - def class_option(name, options=T.unsafe(nil)); end - - def class_options(options=T.unsafe(nil)); end - - def class_options_help(shell, groups=T.unsafe(nil)); end - - def commands(); end - - def create_command(meth); end - - def create_task(meth); end - - def disable_required_check?(command_name); end - - def dispatch(command, given_args, given_opts, config); end - - def exit_on_failure?(); end - - def find_and_refresh_command(name); end - - def find_and_refresh_task(name); end - - def from_superclass(method, default=T.unsafe(nil)); end - - def group(name=T.unsafe(nil)); end - - def handle_argument_error(command, error, args, arity); end - - def handle_no_command_error(command, has_namespace=T.unsafe(nil)); end - - def handle_no_task_error(command, has_namespace=T.unsafe(nil)); end - - def inherited(klass); end - - def initialize_added(); end - - def is_thor_reserved_word?(word, type); end - - def method_added(meth); end - - def namespace(name=T.unsafe(nil)); end - - def no_commands(&block); end - - def no_commands?(); end - - def no_commands_context(); end - - def no_tasks(&block); end - - def print_options(shell, options, group_name=T.unsafe(nil)); end - - def public_command(*names); end - - def public_task(*names); end - - def remove_argument(*names); end - - def remove_class_option(*names); end - - def remove_command(*names); end - - def remove_task(*names); end - - def start(given_args=T.unsafe(nil), config=T.unsafe(nil)); end - - def stop_on_unknown_option?(command_name); end - - def strict_args_position(); end - - def strict_args_position!(); end - - def strict_args_position?(config); end - - def tasks(); end -end - -module Bundler::Thor::Base::ClassMethods -end - -module Bundler::Thor::Base - def self.included(base); end - - def self.register_klass_file(klass); end - - def self.shell(); end - - def self.shell=(shell); end - - def self.subclass_files(); end - - def self.subclasses(); end -end - -class Bundler::Thor::Command - def formatted_usage(klass, namespace=T.unsafe(nil), subcommand=T.unsafe(nil)); end - - def handle_argument_error?(instance, error, caller); end - - def handle_no_method_error?(instance, error, caller); end - - def hidden?(); end - - def initialize(name, description, long_description, usage, options=T.unsafe(nil)); end - - def local_method?(instance, name); end - - def not_debugging?(instance); end - - def private_method?(instance); end - - def public_method?(instance); end - - def required_arguments_for(klass, usage); end - - def required_options(); end - - def run(instance, args=T.unsafe(nil)); end - - def sans_backtrace(backtrace, caller); end - FILE_REGEXP = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Command -end - -module Bundler::Thor::CoreExt -end - -class Bundler::Thor::CoreExt::HashWithIndifferentAccess - def [](key); end - - def []=(key, value); end - - def convert_key(key); end - - def delete(key); end - - def except(*keys); end - - def fetch(key, *args); end - - def initialize(hash=T.unsafe(nil)); end - - def key?(key); end - - def merge(other); end - - def merge!(other); end - - def method_missing(method, *args); end - - def replace(other_hash); end - - def reverse_merge(other); end - - def reverse_merge!(other_hash); end - - def values_at(*indices); end -end - -class Bundler::Thor::CoreExt::HashWithIndifferentAccess -end - -module Bundler::Thor::CoreExt -end - -Bundler::Thor::Correctable = DidYouMean::Correctable - -class Bundler::Thor::DynamicCommand - def initialize(name, options=T.unsafe(nil)); end -end - -class Bundler::Thor::DynamicCommand -end - -Bundler::Thor::DynamicTask = Bundler::Thor::DynamicCommand - -class Bundler::Thor::Error -end - -class Bundler::Thor::Error -end - -class Bundler::Thor::Group - include ::Bundler::Thor::Base - include ::Bundler::Thor::Invocation - include ::Bundler::Thor::Shell - def _invoke_for_class_method(klass, command=T.unsafe(nil), *args, &block); end -end - -class Bundler::Thor::Group - extend ::Bundler::Thor::Base::ClassMethods - extend ::Bundler::Thor::Invocation::ClassMethods - def self.banner(); end - - def self.desc(description=T.unsafe(nil)); end - - def self.get_options_from_invocations(group_options, base_options); end - - def self.handle_argument_error(command, error, _args, arity); end - - def self.help(shell); end - - def self.invocation_blocks(); end - - def self.invocations(); end - - def self.invoke(*names, &block); end - - def self.invoke_from_option(*names, &block); end - - def self.printable_commands(*arg); end - - def self.printable_tasks(*arg); end - - def self.remove_invocation(*names); end - - def self.self_command(); end - - def self.self_task(); end -end - -class Bundler::Thor::HiddenCommand -end - -class Bundler::Thor::HiddenCommand -end - -Bundler::Thor::HiddenTask = Bundler::Thor::HiddenCommand - -module Bundler::Thor::Invocation - def _parse_initialization_options(args, opts, config); end - - def _retrieve_class_and_command(name, sent_command=T.unsafe(nil)); end - - def _retrieve_class_and_task(name, sent_command=T.unsafe(nil)); end - - def _shared_configuration(); end - - def current_command_chain(); end - - def initialize(args=T.unsafe(nil), options=T.unsafe(nil), config=T.unsafe(nil), &block); end - - def invoke(name=T.unsafe(nil), *args); end - - def invoke_all(); end - - def invoke_command(command, *args); end - - def invoke_task(command, *args); end - - def invoke_with_padding(*args); end -end - -module Bundler::Thor::Invocation::ClassMethods - def prepare_for_invocation(key, name); end -end - -module Bundler::Thor::Invocation::ClassMethods -end - -module Bundler::Thor::Invocation - def self.included(base); end -end - -class Bundler::Thor::InvocationError -end - -class Bundler::Thor::InvocationError -end - -module Bundler::Thor::LineEditor -end - -class Bundler::Thor::LineEditor::Basic - def initialize(prompt, options); end - - def options(); end - - def prompt(); end - - def readline(); end -end - -class Bundler::Thor::LineEditor::Basic - def self.available?(); end -end - -class Bundler::Thor::LineEditor::Readline -end - -class Bundler::Thor::LineEditor::Readline::PathCompletion - def initialize(text); end - - def matches(); end -end - -class Bundler::Thor::LineEditor::Readline::PathCompletion -end - -class Bundler::Thor::LineEditor::Readline -end - -module Bundler::Thor::LineEditor - def self.best_available(); end - - def self.readline(prompt, options=T.unsafe(nil)); end -end - -class Bundler::Thor::MalformattedArgumentError -end - -class Bundler::Thor::MalformattedArgumentError -end - -class Bundler::Thor::NestedContext - def enter(); end - - def entered?(); end -end - -class Bundler::Thor::NestedContext -end - -class Bundler::Thor::NoKwargSpellChecker - def initialize(dictionary); end -end - -class Bundler::Thor::NoKwargSpellChecker -end - -class Bundler::Thor::Option - def aliases(); end - - def array?(); end - - def boolean?(); end - - def dasherize(str); end - - def dasherized?(); end - - def group(); end - - def hash?(); end - - def hide(); end - - def lazy_default(); end - - def numeric?(); end - - def repeatable(); end - - def string?(); end - - def switch_name(); end - - def undasherize(str); end - - def usage(padding=T.unsafe(nil)); end - - def validate_default_type!(); end - VALID_TYPES = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Option - def self.parse(key, value); end -end - -class Bundler::Thor::Options - def assign_result!(option, result); end - - def check_unknown!(); end - - def current_is_switch?(); end - - def current_is_switch_formatted?(); end - - def initialize(hash_options=T.unsafe(nil), defaults=T.unsafe(nil), stop_on_unknown=T.unsafe(nil), disable_required_check=T.unsafe(nil)); end - - def normalize_switch(arg); end - - def parse_boolean(switch); end - - def parse_peek(switch, option); end - - def parsing_options?(); end - - def switch?(arg); end - - def switch_option(arg); end - - def unshift(arg, is_value: T.unsafe(nil)); end - EQ_RE = ::T.let(nil, ::T.untyped) - LONG_RE = ::T.let(nil, ::T.untyped) - OPTS_END = ::T.let(nil, ::T.untyped) - SHORT_NUM = ::T.let(nil, ::T.untyped) - SHORT_RE = ::T.let(nil, ::T.untyped) - SHORT_SQ_RE = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Options - def self.to_switches(options); end -end - -module Bundler::Thor::RakeCompat - include ::Rake::DSL - include ::Rake::FileUtilsExt - include ::FileUtils - include ::FileUtils::StreamUtils_ -end - -module Bundler::Thor::RakeCompat - def self.included(base); end - - def self.rake_classes(); end -end - -class Bundler::Thor::RequiredArgumentMissingError -end - -class Bundler::Thor::RequiredArgumentMissingError -end - -module Bundler::Thor::Sandbox -end - -module Bundler::Thor::Sandbox -end - -module Bundler::Thor::Shell - def _shared_configuration(); end - - def ask(*args, &block); end - - def error(*args, &block); end - - def file_collision(*args, &block); end - - def initialize(args=T.unsafe(nil), options=T.unsafe(nil), config=T.unsafe(nil)); end - - def no?(*args, &block); end - - def print_in_columns(*args, &block); end - - def print_table(*args, &block); end - - def print_wrapped(*args, &block); end - - def say(*args, &block); end - - def say_error(*args, &block); end - - def say_status(*args, &block); end - - def set_color(*args, &block); end - - def shell(); end - - def shell=(shell); end - - def terminal_width(*args, &block); end - - def with_padding(); end - - def yes?(*args, &block); end - SHELL_DELEGATED_METHODS = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Shell::Basic - def answer_match(possibilities, answer, case_insensitive); end - - def as_unicode(); end - - def ask(statement, *args); end - - def ask_filtered(statement, color, options); end - - def ask_simply(statement, color, options); end - - def base(); end - - def base=(base); end - - def can_display_colors?(); end - - def dynamic_width(); end - - def dynamic_width_stty(); end - - def dynamic_width_tput(); end - - def error(statement); end - - def file_collision(destination); end - - def file_collision_help(); end - - def git_merge_tool(); end - - def indent(count=T.unsafe(nil)); end - - def is?(value); end - - def lookup_color(color); end - - def merge(destination, content); end - - def merge_tool(); end - - def mute(); end - - def mute?(); end - - def no?(statement, color=T.unsafe(nil)); end - - def padding(); end - - def padding=(value); end - - def prepare_message(message, *color); end - - def print_in_columns(array); end - - def print_table(array, options=T.unsafe(nil)); end - - def print_wrapped(message, options=T.unsafe(nil)); end - - def quiet?(); end - - def say(message=T.unsafe(nil), color=T.unsafe(nil), force_new_line=T.unsafe(nil)); end - - def say_error(message=T.unsafe(nil), color=T.unsafe(nil), force_new_line=T.unsafe(nil)); end - - def say_status(status, message, log_status=T.unsafe(nil)); end - - def set_color(string, *arg); end - - def show_diff(destination, content); end - - def stderr(); end - - def stdout(); end - - def terminal_width(); end - - def truncate(string, width); end - - def unix?(); end - - def yes?(statement, color=T.unsafe(nil)); end - DEFAULT_TERMINAL_WIDTH = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Shell::Basic -end - -class Bundler::Thor::Shell::Color - def are_colors_disabled?(); end - - def are_colors_supported?(); end - - def diff_lcs_loaded?(); end - - def output_diff_line(diff); end - - def set_color(string, *colors); end - BLACK = ::T.let(nil, ::T.untyped) - BLUE = ::T.let(nil, ::T.untyped) - BOLD = ::T.let(nil, ::T.untyped) - CLEAR = ::T.let(nil, ::T.untyped) - CYAN = ::T.let(nil, ::T.untyped) - GREEN = ::T.let(nil, ::T.untyped) - MAGENTA = ::T.let(nil, ::T.untyped) - ON_BLACK = ::T.let(nil, ::T.untyped) - ON_BLUE = ::T.let(nil, ::T.untyped) - ON_CYAN = ::T.let(nil, ::T.untyped) - ON_GREEN = ::T.let(nil, ::T.untyped) - ON_MAGENTA = ::T.let(nil, ::T.untyped) - ON_RED = ::T.let(nil, ::T.untyped) - ON_WHITE = ::T.let(nil, ::T.untyped) - ON_YELLOW = ::T.let(nil, ::T.untyped) - RED = ::T.let(nil, ::T.untyped) - WHITE = ::T.let(nil, ::T.untyped) - YELLOW = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Shell::Color -end - -class Bundler::Thor::Shell::HTML - def ask(statement, color=T.unsafe(nil)); end - - def diff_lcs_loaded?(); end - - def output_diff_line(diff); end - - def set_color(string, *colors); end - BLACK = ::T.let(nil, ::T.untyped) - BLUE = ::T.let(nil, ::T.untyped) - BOLD = ::T.let(nil, ::T.untyped) - CYAN = ::T.let(nil, ::T.untyped) - GREEN = ::T.let(nil, ::T.untyped) - MAGENTA = ::T.let(nil, ::T.untyped) - ON_BLACK = ::T.let(nil, ::T.untyped) - ON_BLUE = ::T.let(nil, ::T.untyped) - ON_CYAN = ::T.let(nil, ::T.untyped) - ON_GREEN = ::T.let(nil, ::T.untyped) - ON_MAGENTA = ::T.let(nil, ::T.untyped) - ON_RED = ::T.let(nil, ::T.untyped) - ON_WHITE = ::T.let(nil, ::T.untyped) - ON_YELLOW = ::T.let(nil, ::T.untyped) - RED = ::T.let(nil, ::T.untyped) - WHITE = ::T.let(nil, ::T.untyped) - YELLOW = ::T.let(nil, ::T.untyped) -end - -class Bundler::Thor::Shell::HTML -end - -module Bundler::Thor::Shell -end - -Bundler::Thor::Task = Bundler::Thor::Command - -class Bundler::Thor::UndefinedCommandError - include ::DidYouMean::Correctable - def all_commands(); end - - def command(); end - - def initialize(command, all_commands, namespace); end -end - -class Bundler::Thor::UndefinedCommandError::SpellChecker - def corrections(); end - - def error(); end - - def initialize(error); end - - def spell_checker(); end -end - -class Bundler::Thor::UndefinedCommandError::SpellChecker -end - -class Bundler::Thor::UndefinedCommandError -end - -Bundler::Thor::UndefinedTaskError = Bundler::Thor::UndefinedCommandError - -class Bundler::Thor::UnknownArgumentError - include ::DidYouMean::Correctable - def initialize(switches, unknown); end - - def switches(); end - - def unknown(); end -end - -class Bundler::Thor::UnknownArgumentError::SpellChecker - def corrections(); end - - def error(); end - - def initialize(error); end - - def spell_checker(); end -end - -class Bundler::Thor::UnknownArgumentError::SpellChecker -end - -class Bundler::Thor::UnknownArgumentError -end - -module Bundler::Thor::Util -end - -module Bundler::Thor::Util - def self.camel_case(str); end - - def self.escape_globs(path); end - - def self.escape_html(string); end - - def self.find_by_namespace(namespace); end - - def self.find_class_and_command_by_namespace(namespace, fallback=T.unsafe(nil)); end - - def self.find_class_and_task_by_namespace(namespace, fallback=T.unsafe(nil)); end - - def self.globs_for(path); end - - def self.load_thorfile(path, content=T.unsafe(nil), debug=T.unsafe(nil)); end - - def self.namespace_from_thor_class(constant); end - - def self.namespaces_in_content(contents, file=T.unsafe(nil)); end - - def self.ruby_command(); end - - def self.snake_case(str); end - - def self.thor_classes_in(klass); end - - def self.thor_root(); end - - def self.thor_root_glob(); end - - def self.user_home(); end -end - -class Bundler::Thor - extend ::Bundler::Thor::Base::ClassMethods - extend ::Bundler::Thor::Invocation::ClassMethods - def self.banner(command, namespace=T.unsafe(nil), subcommand=T.unsafe(nil)); end - - def self.check_unknown_options!(options=T.unsafe(nil)); end - - def self.command_help(shell, command_name); end - - def self.default_command(meth=T.unsafe(nil)); end - - def self.default_task(meth=T.unsafe(nil)); end - - def self.deprecation_warning(message); end - - def self.desc(usage, description, options=T.unsafe(nil)); end - - def self.disable_required_check(); end - - def self.disable_required_check!(*command_names); end - - def self.disable_required_check?(command); end - - def self.dispatch(meth, given_args, given_opts, config); end - - def self.dynamic_command_class(); end - - def self.find_command_possibilities(meth); end - - def self.find_task_possibilities(meth); end - - def self.help(shell, subcommand=T.unsafe(nil)); end - - def self.long_desc(long_description, options=T.unsafe(nil)); end - - def self.map(mappings=T.unsafe(nil), **kw); end - - def self.method_option(name, options=T.unsafe(nil)); end - - def self.method_options(options=T.unsafe(nil)); end - - def self.normalize_command_name(meth); end - - def self.normalize_task_name(meth); end - - def self.option(name, options=T.unsafe(nil)); end - - def self.options(options=T.unsafe(nil)); end - - def self.package_name(name, _=T.unsafe(nil)); end - - def self.printable_commands(all=T.unsafe(nil), subcommand=T.unsafe(nil)); end - - def self.printable_tasks(all=T.unsafe(nil), subcommand=T.unsafe(nil)); end - - def self.register(klass, subcommand_name, usage, description, options=T.unsafe(nil)); end - - def self.retrieve_command_name(args); end - - def self.retrieve_task_name(args); end - - def self.stop_on_unknown_option(); end - - def self.stop_on_unknown_option!(*command_names); end - - def self.stop_on_unknown_option?(command); end - - def self.subcommand(subcommand, subcommand_class); end - - def self.subcommand_classes(); end - - def self.subcommand_help(cmd); end - - def self.subcommands(); end - - def self.subtask(subcommand, subcommand_class); end - - def self.subtask_help(cmd); end - - def self.subtasks(); end - - def self.task_help(shell, command_name); end -end - -class Bundler::UI::Shell - def add_color(string, *color); end - - def ask(msg); end - - def confirm(msg, newline=T.unsafe(nil)); end - - def debug(msg, newline=T.unsafe(nil)); end - - def debug?(); end - - def error(msg, newline=T.unsafe(nil), color=T.unsafe(nil)); end - - def info(msg, newline=T.unsafe(nil)); end - - def initialize(options=T.unsafe(nil)); end - - def level(name=T.unsafe(nil)); end - - def level=(level); end - - def no?(); end - - def quiet?(); end - - def shell=(shell); end - - def silence(&blk); end - - def trace(e, newline=T.unsafe(nil), force=T.unsafe(nil)); end - - def unprinted_warnings(); end - - def warn(msg, newline=T.unsafe(nil), color=T.unsafe(nil)); end - - def yes?(msg); end - LEVELS = ::T.let(nil, ::T.untyped) -end - -class Bundler::UI::Shell -end - -module Bundler::URI - include ::Bundler::URI::RFC2396_REGEXP - ABS_PATH = ::T.let(nil, ::T.untyped) - ABS_URI = ::T.let(nil, ::T.untyped) - ABS_URI_REF = ::T.let(nil, ::T.untyped) - DEFAULT_PARSER = ::T.let(nil, ::T.untyped) - ESCAPED = ::T.let(nil, ::T.untyped) - FRAGMENT = ::T.let(nil, ::T.untyped) - HOST = ::T.let(nil, ::T.untyped) - OPAQUE = ::T.let(nil, ::T.untyped) - PORT = ::T.let(nil, ::T.untyped) - QUERY = ::T.let(nil, ::T.untyped) - REGISTRY = ::T.let(nil, ::T.untyped) - REL_PATH = ::T.let(nil, ::T.untyped) - REL_URI = ::T.let(nil, ::T.untyped) - REL_URI_REF = ::T.let(nil, ::T.untyped) - RFC3986_PARSER = ::T.let(nil, ::T.untyped) - SCHEME = ::T.let(nil, ::T.untyped) - TBLDECWWWCOMP_ = ::T.let(nil, ::T.untyped) - TBLENCWWWCOMP_ = ::T.let(nil, ::T.untyped) - UNSAFE = ::T.let(nil, ::T.untyped) - URI_REF = ::T.let(nil, ::T.untyped) - USERINFO = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) - VERSION_CODE = ::T.let(nil, ::T.untyped) - WEB_ENCODINGS_ = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::BadURIError -end - -class Bundler::URI::BadURIError -end - -class Bundler::URI::Error -end - -class Bundler::URI::Error -end - -class Bundler::URI::FTP - def set_typecode(v); end - - def typecode(); end - - def typecode=(typecode); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) - TYPECODE = ::T.let(nil, ::T.untyped) - TYPECODE_PREFIX = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::FTP - def self.new2(user, password, host, port, path, typecode=T.unsafe(nil), arg_check=T.unsafe(nil)); end -end - -class Bundler::URI::File - def check_password(user); end - - def check_user(user); end - - def check_userinfo(user); end - - def set_userinfo(v); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::File -end - -class Bundler::URI::Generic - include ::Bundler::URI - include ::Bundler::URI::RFC2396_REGEXP - def +(oth); end - - def -(oth); end - - def ==(oth); end - - def absolute(); end - - def absolute?(); end - - def coerce(oth); end - - def component(); end - - def component_ary(); end - - def default_port(); end - - def eql?(oth); end - - def find_proxy(env=T.unsafe(nil)); end - - def fragment(); end - - def fragment=(v); end - - def hierarchical?(); end - - def host(); end - - def host=(v); end - - def hostname(); end - - def hostname=(v); end - - def initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser=T.unsafe(nil), arg_check=T.unsafe(nil)); end - - def merge(oth); end - - def merge!(oth); end - - def normalize(); end - - def normalize!(); end - - def opaque(); end - - def opaque=(v); end - - def parser(); end - - def password(); end - - def password=(password); end - - def path(); end - - def path=(v); end - - def port(); end - - def port=(v); end - - def query(); end - - def query=(v); end - - def registry(); end - - def registry=(v); end - - def relative?(); end - - def route_from(oth); end - - def route_to(oth); end - - def scheme(); end - - def scheme=(v); end - - def select(*components); end - - def set_host(v); end - - def set_opaque(v); end - - def set_password(v); end - - def set_path(v); end - - def set_port(v); end - - def set_registry(v); end - - def set_scheme(v); end - - def set_user(v); end - - def set_userinfo(user, password=T.unsafe(nil)); end - - def user(); end - - def user=(user); end - - def userinfo(); end - - def userinfo=(userinfo); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) - USE_REGISTRY = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::Generic - def self.build(args); end - - def self.build2(args); end - - def self.component(); end - - def self.default_port(); end - - def self.use_proxy?(hostname, addr, port, no_proxy); end - - def self.use_registry(); end -end - -class Bundler::URI::HTTP - def request_uri(); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::HTTP -end - -class Bundler::URI::HTTPS - DEFAULT_PORT = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::HTTPS -end - -class Bundler::URI::InvalidComponentError -end - -class Bundler::URI::InvalidComponentError -end - -class Bundler::URI::InvalidURIError -end - -class Bundler::URI::InvalidURIError -end - -class Bundler::URI::LDAP - def attributes(); end - - def attributes=(val); end - - def dn(); end - - def dn=(val); end - - def extensions(); end - - def extensions=(val); end - - def filter(); end - - def filter=(val); end - - def initialize(*arg); end - - def scope(); end - - def scope=(val); end - - def set_attributes(val); end - - def set_dn(val); end - - def set_extensions(val); end - - def set_filter(val); end - - def set_scope(val); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) - SCOPE = ::T.let(nil, ::T.untyped) - SCOPE_BASE = ::T.let(nil, ::T.untyped) - SCOPE_ONE = ::T.let(nil, ::T.untyped) - SCOPE_SUB = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::LDAP -end - -class Bundler::URI::LDAPS - DEFAULT_PORT = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::LDAPS -end - -class Bundler::URI::MailTo - def headers(); end - - def headers=(v); end - - def initialize(*arg); end - - def set_headers(v); end - - def set_to(v); end - - def to(); end - - def to=(v); end - - def to_mailtext(); end - - def to_rfc822text(); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) - EMAIL_REGEXP = ::T.let(nil, ::T.untyped) - HEADER_REGEXP = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::MailTo -end - -Bundler::URI::Parser = Bundler::URI::RFC2396_Parser - -Bundler::URI::REGEXP = Bundler::URI::RFC2396_REGEXP - -class Bundler::URI::RFC2396_Parser - include ::Bundler::URI::RFC2396_REGEXP - def escape(str, unsafe=T.unsafe(nil)); end - - def extract(str, schemes=T.unsafe(nil)); end - - def initialize(opts=T.unsafe(nil)); end - - def join(*uris); end - - def make_regexp(schemes=T.unsafe(nil)); end - - def parse(uri); end - - def pattern(); end - - def regexp(); end - - def split(uri); end - - def unescape(str, escaped=T.unsafe(nil)); end -end - -class Bundler::URI::RFC2396_Parser -end - -module Bundler::URI::RFC2396_REGEXP -end - -module Bundler::URI::RFC2396_REGEXP::PATTERN - ABS_PATH = ::T.let(nil, ::T.untyped) - ABS_URI = ::T.let(nil, ::T.untyped) - ALNUM = ::T.let(nil, ::T.untyped) - ALPHA = ::T.let(nil, ::T.untyped) - DOMLABEL = ::T.let(nil, ::T.untyped) - ESCAPED = ::T.let(nil, ::T.untyped) - FRAGMENT = ::T.let(nil, ::T.untyped) - HEX = ::T.let(nil, ::T.untyped) - HIER_PART = ::T.let(nil, ::T.untyped) - HOST = ::T.let(nil, ::T.untyped) - HOSTNAME = ::T.let(nil, ::T.untyped) - HOSTPORT = ::T.let(nil, ::T.untyped) - IPV4ADDR = ::T.let(nil, ::T.untyped) - IPV6ADDR = ::T.let(nil, ::T.untyped) - IPV6REF = ::T.let(nil, ::T.untyped) - NET_PATH = ::T.let(nil, ::T.untyped) - OPAQUE_PART = ::T.let(nil, ::T.untyped) - PATH_SEGMENTS = ::T.let(nil, ::T.untyped) - PORT = ::T.let(nil, ::T.untyped) - QUERY = ::T.let(nil, ::T.untyped) - REG_NAME = ::T.let(nil, ::T.untyped) - REL_PATH = ::T.let(nil, ::T.untyped) - REL_SEGMENT = ::T.let(nil, ::T.untyped) - REL_URI = ::T.let(nil, ::T.untyped) - RESERVED = ::T.let(nil, ::T.untyped) - SCHEME = ::T.let(nil, ::T.untyped) - TOPLABEL = ::T.let(nil, ::T.untyped) - UNRESERVED = ::T.let(nil, ::T.untyped) - URIC = ::T.let(nil, ::T.untyped) - URIC_NO_SLASH = ::T.let(nil, ::T.untyped) - URI_REF = ::T.let(nil, ::T.untyped) - USERINFO = ::T.let(nil, ::T.untyped) - X_ABS_URI = ::T.let(nil, ::T.untyped) - X_REL_URI = ::T.let(nil, ::T.untyped) -end - -module Bundler::URI::RFC2396_REGEXP::PATTERN -end - -module Bundler::URI::RFC2396_REGEXP -end - -class Bundler::URI::RFC3986_Parser - def join(*uris); end - - def parse(uri); end - - def regexp(); end - - def split(uri); end - RFC3986_URI = ::T.let(nil, ::T.untyped) - RFC3986_relative_ref = ::T.let(nil, ::T.untyped) -end - -class Bundler::URI::RFC3986_Parser -end - -module Bundler::URI::Util -end - -module Bundler::URI::Util - def self.make_components_hash(klass, array_hash); end -end - -module Bundler::URI - def self.decode_www_form(str, enc=T.unsafe(nil), separator: T.unsafe(nil), use__charset_: T.unsafe(nil), isindex: T.unsafe(nil)); end - - def self.decode_www_form_component(str, enc=T.unsafe(nil)); end - - def self.encode_www_form(enum, enc=T.unsafe(nil)); end - - def self.encode_www_form_component(str, enc=T.unsafe(nil)); end - - def self.extract(str, schemes=T.unsafe(nil), &block); end - - def self.for(scheme, *arguments, default: T.unsafe(nil)); end - - def self.get_encoding(label); end - - def self.join(*str); end - - def self.parse(uri); end - - def self.regexp(schemes=T.unsafe(nil)); end - - def self.scheme_list(); end - - def self.split(uri); end -end - -module Bundler::VersionRanges -end - -class Bundler::VersionRanges::NEq - def version(); end - - def version=(_); end -end - -class Bundler::VersionRanges::NEq - def self.[](*arg); end - - def self.keyword_init?(); end - - def self.members(); end -end - -class Bundler::VersionRanges::ReqR - def cover?(v); end - - def empty?(); end - - def left(); end - - def left=(_); end - - def right(); end - - def right=(_); end - - def single?(); end - INFINITY = ::T.let(nil, ::T.untyped) - UNIVERSAL = ::T.let(nil, ::T.untyped) - ZERO = ::T.let(nil, ::T.untyped) -end - -class Bundler::VersionRanges::ReqR::Endpoint - def inclusive(); end - - def inclusive=(_); end - - def version(); end - - def version=(_); end -end - -class Bundler::VersionRanges::ReqR::Endpoint - def self.[](*arg); end - - def self.keyword_init?(); end - - def self.members(); end -end - -class Bundler::VersionRanges::ReqR - def self.[](*arg); end - - def self.keyword_init?(); end - - def self.members(); end -end - -module Bundler::VersionRanges - def self.empty?(ranges, neqs); end - - def self.for(requirement); end - - def self.for_many(requirements); end -end - -module Bundler - def self.configure_gem_home_and_path(path=T.unsafe(nil)); end - - def self.most_specific_locked_platform?(platform); end - - def self.original_exec(*args); end - - def self.original_system(*args); end - - def self.preferred_gemfile_name(); end - - def self.reset_settings_and_root!(); end - - def self.self_manager(); end - - def self.unbundled_env(); end - - def self.unbundled_exec(*args); end - - def self.unbundled_system(*args); end -end - -class Class - def json_creatable?(); end -end - -module Concurrent - NULL = ::T.let(nil, ::T.untyped) - NULL_LOGGER = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -class Concurrent::AbstractExecutorService - FALLBACK_POLICIES = ::T.let(nil, ::T.untyped) -end - -Concurrent::Collection::MapImplementation = Concurrent::Collection::MriMapBackend - -class Concurrent::ConcurrentUpdateError - CONC_UP_ERR_BACKTRACE = ::T.let(nil, ::T.untyped) -end - -class Concurrent::LockFreeStack - EMPTY = ::T.let(nil, ::T.untyped) -end - -class Concurrent::MVar - EMPTY = ::T.let(nil, ::T.untyped) - TIMEOUT = ::T.let(nil, ::T.untyped) -end - -class Concurrent::Maybe - NONE = ::T.let(nil, ::T.untyped) -end - -module Concurrent::Promises::InternalStates - PENDING = ::T.let(nil, ::T.untyped) - RESERVED = ::T.let(nil, ::T.untyped) - RESOLVED = ::T.let(nil, ::T.untyped) -end - -class Concurrent::ReadWriteLock - MAX_READERS = ::T.let(nil, ::T.untyped) - MAX_WRITERS = ::T.let(nil, ::T.untyped) - RUNNING_WRITER = ::T.let(nil, ::T.untyped) - WAITING_WRITER = ::T.let(nil, ::T.untyped) -end - -class Concurrent::ReentrantReadWriteLock - MAX_READERS = ::T.let(nil, ::T.untyped) - MAX_WRITERS = ::T.let(nil, ::T.untyped) - READER_BITS = ::T.let(nil, ::T.untyped) - READ_LOCK_MASK = ::T.let(nil, ::T.untyped) - RUNNING_WRITER = ::T.let(nil, ::T.untyped) - WAITING_WRITER = ::T.let(nil, ::T.untyped) - WRITER_BITS = ::T.let(nil, ::T.untyped) - WRITE_LOCK_HELD = ::T.let(nil, ::T.untyped) - WRITE_LOCK_MASK = ::T.let(nil, ::T.untyped) -end - -class Concurrent::RubyThreadPoolExecutor - DEFAULT_MAX_POOL_SIZE = ::T.let(nil, ::T.untyped) - DEFAULT_MAX_QUEUE_SIZE = ::T.let(nil, ::T.untyped) - DEFAULT_MIN_POOL_SIZE = ::T.let(nil, ::T.untyped) - DEFAULT_SYNCHRONOUS = ::T.let(nil, ::T.untyped) - DEFAULT_THREAD_IDLETIMEOUT = ::T.let(nil, ::T.untyped) -end - -class Concurrent::SerializedExecutionDelegator - RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped) -end - -Concurrent::Synchronization::Volatile = Concurrent::Synchronization::MriAttrVolatile - -class Concurrent::SynchronizedDelegator - RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped) -end - -module Concurrent::ThreadSafe::Util - CPU_COUNT = ::T.let(nil, ::T.untyped) - FIXNUM_BIT_SIZE = ::T.let(nil, ::T.untyped) - MAX_INT = ::T.let(nil, ::T.untyped) -end - -class Concurrent::TimerTask - EXECUTION_INTERVAL = ::T.let(nil, ::T.untyped) - TIMEOUT_INTERVAL = ::T.let(nil, ::T.untyped) -end - -class Concurrent::Transaction - ABORTED = ::T.let(nil, ::T.untyped) -end - -module Concurrent::Utility::NativeInteger - MAX_VALUE = ::T.let(nil, ::T.untyped) - MIN_VALUE = ::T.let(nil, ::T.untyped) -end - -class Crack::JSON - DATE_REGEX = ::T.let(nil, ::T.untyped) -end - -class Date - def infinite?(); end - VERSION = ::T.let(nil, ::T.untyped) -end - -class Date::Infinity - def initialize(d=T.unsafe(nil)); end -end - -class DateTime - def self.new(*arg); end -end - -class Delegator - RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -class DidYouMean::ClassNameChecker - def class_name(); end - - def class_names(); end - - def corrections(); end - - def initialize(exception); end - - def scopes(); end -end - -module DidYouMean::Correctable - def corrections(); end - - def original_message(); end - - def spell_checker(); end - - def to_s(); end -end - -class DidYouMean::Formatter - def message_for(corrections); end -end - -class DidYouMean::Formatter - def self.message_for(corrections); end -end - -module DidYouMean::Jaro - def self.distance(str1, str2); end -end - -module DidYouMean::JaroWinkler - def self.distance(str1, str2); end -end - -class DidYouMean::KeyErrorChecker - def corrections(); end - - def initialize(key_error); end -end - -class DidYouMean::KeyErrorChecker -end - -module DidYouMean::Levenshtein - def self.distance(str1, str2); end - - def self.min3(a, b, c); end -end - -class DidYouMean::MethodNameChecker - def corrections(); end - - def initialize(exception); end - - def method_name(); end - - def method_names(); end - - def names_to_exclude(); end - - def receiver(); end - RB_RESERVED_WORDS = ::T.let(nil, ::T.untyped) -end - -class DidYouMean::NullChecker - def corrections(); end - - def initialize(*arg); end -end - -class DidYouMean::PatternKeyNameChecker - def corrections(); end - - def initialize(no_matching_pattern_key_error); end -end - -class DidYouMean::PatternKeyNameChecker -end - -DidYouMean::PlainFormatter = DidYouMean::Formatter - -class DidYouMean::RequirePathChecker - def corrections(); end - - def initialize(exception); end - - def path(); end -end - -class DidYouMean::RequirePathChecker - def self.requireables(); end -end - -class DidYouMean::TreeSpellChecker - def augment(); end - - def correct(input); end - - def dictionary(); end - - def dictionary_without_leaves(); end - - def dimensions(); end - - def find_leaves(path); end - - def initialize(dictionary:, separator: T.unsafe(nil), augment: T.unsafe(nil)); end - - def plausible_dimensions(input); end - - def possible_paths(states); end - - def separator(); end - - def tree_depth(); end -end - -class DidYouMean::TreeSpellChecker -end - -class DidYouMean::VariableNameChecker - def corrections(); end - - def cvar_names(); end - - def initialize(exception); end - - def ivar_names(); end - - def lvar_names(); end - - def method_names(); end - - def name(); end - RB_RESERVED_WORDS = ::T.let(nil, ::T.untyped) -end - -module DidYouMean - def self.correct_error(error_class, spell_checker); end - - def self.formatter(); end - - def self.formatter=(formatter); end - - def self.spell_checkers(); end -end - -module Digest - VERSION = ::T.let(nil, ::T.untyped) -end - -class Dir - def children(); end - - def each_child(); end -end - -module Dir::Tmpname - UNUSABLE_CHARS = ::T.let(nil, ::T.untyped) -end - -class Dir - def self.exists?(arg); end -end - -class DomainName - DOT = ::T.let(nil, ::T.untyped) - ETLD_DATA = ::T.let(nil, ::T.untyped) - ETLD_DATA_DATE = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -module DomainName::Punycode - BASE = ::T.let(nil, ::T.untyped) - CUTOFF = ::T.let(nil, ::T.untyped) - DAMP = ::T.let(nil, ::T.untyped) - DECODE_DIGIT = ::T.let(nil, ::T.untyped) - DELIMITER = ::T.let(nil, ::T.untyped) - DOT = ::T.let(nil, ::T.untyped) - ENCODE_DIGIT = ::T.let(nil, ::T.untyped) - INITIAL_BIAS = ::T.let(nil, ::T.untyped) - INITIAL_N = ::T.let(nil, ::T.untyped) - LOBASE = ::T.let(nil, ::T.untyped) - MAXINT = ::T.let(nil, ::T.untyped) - PREFIX = ::T.let(nil, ::T.untyped) - RE_NONBASIC = ::T.let(nil, ::T.untyped) - SKEW = ::T.let(nil, ::T.untyped) - TMAX = ::T.let(nil, ::T.untyped) - TMIN = ::T.let(nil, ::T.untyped) -end - -class DynamicConfig - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -class ERB - def def_method(mod, methodname, fname=T.unsafe(nil)); end - - def def_module(methodname=T.unsafe(nil)); end -end - -class Encoding - def _dump(*arg); end - CESU_8 = ::T.let(nil, ::T.untyped) - CP720 = ::T.let(nil, ::T.untyped) - IBM720 = ::T.let(nil, ::T.untyped) -end - -class Encoding::Converter - def initialize(*arg); end -end - -class Encoding - def self._load(arg); end -end - -module Enumerable - def compact(); end -end - -class Enumerator - def +(arg); end - - def each_with_index(); end -end - -class Enumerator::ArithmeticSequence - def begin(); end - - def each(&blk); end - - def end(); end - - def exclude_end?(); end - - def last(*arg); end - - def step(); end -end - -class Enumerator::ArithmeticSequence -end - -class Enumerator::Chain -end - -class Enumerator::Chain -end - -class Enumerator::Generator - def each(*arg, &blk); end - - def initialize(*arg); end -end - -class Enumerator::Producer - def each(&blk); end -end - -class Enumerator::Producer -end - -class Errno::EAUTH - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EAUTH -end - -class Errno::EBADARCH - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EBADARCH -end - -class Errno::EBADEXEC - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EBADEXEC -end - -class Errno::EBADMACHO - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EBADMACHO -end - -class Errno::EBADRPC - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EBADRPC -end - -Errno::ECAPMODE = Errno::NOERROR - -Errno::EDEADLOCK = Errno::NOERROR - -class Errno::EDEVERR - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EDEVERR -end - -Errno::EDOOFUS = Errno::NOERROR - -class Errno::EFTYPE - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EFTYPE -end - -Errno::EIPSEC = Errno::NOERROR - -class Errno::ELAST - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ELAST -end - -class Errno::ENEEDAUTH - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ENEEDAUTH -end - -class Errno::ENOATTR - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ENOATTR -end - -class Errno::ENOPOLICY - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ENOPOLICY -end - -Errno::ENOTCAPABLE = Errno::NOERROR - -class Errno::ENOTSUP - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ENOTSUP -end - -class Errno::EPROCLIM - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EPROCLIM -end - -class Errno::EPROCUNAVAIL - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EPROCUNAVAIL -end - -class Errno::EPROGMISMATCH - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EPROGMISMATCH -end - -class Errno::EPROGUNAVAIL - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EPROGUNAVAIL -end - -class Errno::EPWROFF - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::EPWROFF -end - -Errno::EQFULL = Errno::ELAST - -class Errno::ERPCMISMATCH - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ERPCMISMATCH -end - -class Errno::ESHLIBVERS - Errno = ::T.let(nil, ::T.untyped) -end - -class Errno::ESHLIBVERS -end - -module Etc - VERSION = ::T.let(nil, ::T.untyped) -end - -class Etc::Group - def gid(); end - - def gid=(_); end - - def mem(); end - - def mem=(_); end - - def name(); end - - def name=(_); end - - def passwd(); end - - def passwd=(_); end -end - -class Etc::Group - extend ::Enumerable - def self.[](*arg); end - - def self.each(&blk); end - - def self.keyword_init?(); end - - def self.members(); end -end - -class Etc::Passwd - def change(); end - - def change=(_); end - - def dir=(_); end - - def expire(); end - - def expire=(_); end - - def gecos(); end - - def gecos=(_); end - - def gid=(_); end - - def name=(_); end - - def passwd=(_); end - - def shell=(_); end - - def uclass(); end - - def uclass=(_); end - - def uid=(_); end -end - -class Etc::Passwd - extend ::Enumerable - def self.[](*arg); end - - def self.each(&blk); end - - def self.keyword_init?(); end - - def self.members(); end -end - -class ExitCalledError -end - -class ExitCalledError -end - -module FFI - CURRENT_PROCESS = ::T.let(nil, ::T.untyped) - SizeTypes = ::T.let(nil, ::T.untyped) - TYPE_BOOL = ::T.let(nil, ::T.untyped) - TYPE_BUFFER_IN = ::T.let(nil, ::T.untyped) - TYPE_BUFFER_INOUT = ::T.let(nil, ::T.untyped) - TYPE_BUFFER_OUT = ::T.let(nil, ::T.untyped) - TYPE_FLOAT32 = ::T.let(nil, ::T.untyped) - TYPE_FLOAT64 = ::T.let(nil, ::T.untyped) - TYPE_INT16 = ::T.let(nil, ::T.untyped) - TYPE_INT32 = ::T.let(nil, ::T.untyped) - TYPE_INT64 = ::T.let(nil, ::T.untyped) - TYPE_INT8 = ::T.let(nil, ::T.untyped) - TYPE_LONG = ::T.let(nil, ::T.untyped) - TYPE_LONGDOUBLE = ::T.let(nil, ::T.untyped) - TYPE_POINTER = ::T.let(nil, ::T.untyped) - TYPE_STRING = ::T.let(nil, ::T.untyped) - TYPE_UINT16 = ::T.let(nil, ::T.untyped) - TYPE_UINT32 = ::T.let(nil, ::T.untyped) - TYPE_UINT64 = ::T.let(nil, ::T.untyped) - TYPE_UINT8 = ::T.let(nil, ::T.untyped) - TYPE_ULONG = ::T.let(nil, ::T.untyped) - TYPE_VARARGS = ::T.let(nil, ::T.untyped) - TYPE_VOID = ::T.let(nil, ::T.untyped) - TypeDefs = ::T.let(nil, ::T.untyped) - USE_THIS_PROCESS_AS_LIBRARY = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -FFI::CallbackInfo = FFI::FunctionType - -class FFI::Compiler::Platform - LIBSUFFIX = ::T.let(nil, ::T.untyped) -end - -class FFI::DynamicLibrary - RTLD_ALL_MASK = ::T.let(nil, ::T.untyped) - RTLD_BINDING_MASK = ::T.let(nil, ::T.untyped) - RTLD_DEEPBIND = ::T.let(nil, ::T.untyped) - RTLD_FIRST = ::T.let(nil, ::T.untyped) - RTLD_GLOBAL = ::T.let(nil, ::T.untyped) - RTLD_LAZY = ::T.let(nil, ::T.untyped) - RTLD_LOCAL = ::T.let(nil, ::T.untyped) - RTLD_LOCATION_MASK = ::T.let(nil, ::T.untyped) - RTLD_MEMBER = ::T.let(nil, ::T.untyped) - RTLD_NODELETE = ::T.let(nil, ::T.untyped) - RTLD_NOLOAD = ::T.let(nil, ::T.untyped) - RTLD_NOW = ::T.let(nil, ::T.untyped) -end - -FFI::FunctionInfo = FFI::FunctionType - -module FFI::Library - CURRENT_PROCESS = ::T.let(nil, ::T.untyped) - FlagsMap = ::T.let(nil, ::T.untyped) - LIBC = ::T.let(nil, ::T.untyped) -end - -FFI::NativeLibrary = FFI::DynamicLibrary - -module FFI::NativeType - BOOL = ::T.let(nil, ::T.untyped) - BUFFER_IN = ::T.let(nil, ::T.untyped) - BUFFER_INOUT = ::T.let(nil, ::T.untyped) - BUFFER_OUT = ::T.let(nil, ::T.untyped) - FLOAT32 = ::T.let(nil, ::T.untyped) - FLOAT64 = ::T.let(nil, ::T.untyped) - INT16 = ::T.let(nil, ::T.untyped) - INT32 = ::T.let(nil, ::T.untyped) - INT64 = ::T.let(nil, ::T.untyped) - INT8 = ::T.let(nil, ::T.untyped) - LONG = ::T.let(nil, ::T.untyped) - LONGDOUBLE = ::T.let(nil, ::T.untyped) - POINTER = ::T.let(nil, ::T.untyped) - STRING = ::T.let(nil, ::T.untyped) - UINT16 = ::T.let(nil, ::T.untyped) - UINT32 = ::T.let(nil, ::T.untyped) - UINT64 = ::T.let(nil, ::T.untyped) - UINT8 = ::T.let(nil, ::T.untyped) - ULONG = ::T.let(nil, ::T.untyped) - VARARGS = ::T.let(nil, ::T.untyped) - VOID = ::T.let(nil, ::T.untyped) -end - -module FFI::NativeType -end - -class FFI::NullPointerError -end - -class FFI::NullPointerError -end - -module FFI::Platform - ADDRESS_ALIGN = ::T.let(nil, ::T.untyped) - ADDRESS_SIZE = ::T.let(nil, ::T.untyped) - ARCH = ::T.let(nil, ::T.untyped) - BIG_ENDIAN = ::T.let(nil, ::T.untyped) - BYTE_ORDER = ::T.let(nil, ::T.untyped) - CONF_DIR = ::T.let(nil, ::T.untyped) - CPU = ::T.let(nil, ::T.untyped) - DOUBLE_ALIGN = ::T.let(nil, ::T.untyped) - DOUBLE_SIZE = ::T.let(nil, ::T.untyped) - FLOAT_ALIGN = ::T.let(nil, ::T.untyped) - FLOAT_SIZE = ::T.let(nil, ::T.untyped) - INT16_ALIGN = ::T.let(nil, ::T.untyped) - INT16_SIZE = ::T.let(nil, ::T.untyped) - INT32_ALIGN = ::T.let(nil, ::T.untyped) - INT32_SIZE = ::T.let(nil, ::T.untyped) - INT64_ALIGN = ::T.let(nil, ::T.untyped) - INT64_SIZE = ::T.let(nil, ::T.untyped) - INT8_ALIGN = ::T.let(nil, ::T.untyped) - INT8_SIZE = ::T.let(nil, ::T.untyped) - IS_BSD = ::T.let(nil, ::T.untyped) - IS_DRAGONFLYBSD = ::T.let(nil, ::T.untyped) - IS_FREEBSD = ::T.let(nil, ::T.untyped) - IS_GNU = ::T.let(nil, ::T.untyped) - IS_LINUX = ::T.let(nil, ::T.untyped) - IS_MAC = ::T.let(nil, ::T.untyped) - IS_NETBSD = ::T.let(nil, ::T.untyped) - IS_OPENBSD = ::T.let(nil, ::T.untyped) - IS_SOLARIS = ::T.let(nil, ::T.untyped) - IS_WINDOWS = ::T.let(nil, ::T.untyped) - LIBC = ::T.let(nil, ::T.untyped) - LIBPREFIX = ::T.let(nil, ::T.untyped) - LIBSUFFIX = ::T.let(nil, ::T.untyped) - LITTLE_ENDIAN = ::T.let(nil, ::T.untyped) - LONG_ALIGN = ::T.let(nil, ::T.untyped) - LONG_DOUBLE_ALIGN = ::T.let(nil, ::T.untyped) - LONG_DOUBLE_SIZE = ::T.let(nil, ::T.untyped) - LONG_SIZE = ::T.let(nil, ::T.untyped) - NAME = ::T.let(nil, ::T.untyped) - OS = ::T.let(nil, ::T.untyped) - OSVERSION = ::T.let(nil, ::T.untyped) -end - -class FFI::Pointer - NULL = ::T.let(nil, ::T.untyped) - SIZE = ::T.let(nil, ::T.untyped) -end - -class FFI::Struct::InlineArray - include ::Enumerable -end - -class FFI::StructLayout::Number -end - -class FFI::StructLayout::Number -end - -class FFI::StructLayout::Pointer -end - -class FFI::StructLayout::Pointer -end - -class FFI::StructLayout::String -end - -class FFI::StructLayout::String -end - -class FFI::StructLayoutBuilder - NUMBER_TYPES = ::T.let(nil, ::T.untyped) -end - -class FFI::Type - BOOL = ::T.let(nil, ::T.untyped) - BUFFER_IN = ::T.let(nil, ::T.untyped) - BUFFER_INOUT = ::T.let(nil, ::T.untyped) - BUFFER_OUT = ::T.let(nil, ::T.untyped) - CHAR = ::T.let(nil, ::T.untyped) - DOUBLE = ::T.let(nil, ::T.untyped) - FLOAT = ::T.let(nil, ::T.untyped) - FLOAT32 = ::T.let(nil, ::T.untyped) - FLOAT64 = ::T.let(nil, ::T.untyped) - INT = ::T.let(nil, ::T.untyped) - INT16 = ::T.let(nil, ::T.untyped) - INT32 = ::T.let(nil, ::T.untyped) - INT64 = ::T.let(nil, ::T.untyped) - INT8 = ::T.let(nil, ::T.untyped) - LONG = ::T.let(nil, ::T.untyped) - LONGDOUBLE = ::T.let(nil, ::T.untyped) - LONG_LONG = ::T.let(nil, ::T.untyped) - POINTER = ::T.let(nil, ::T.untyped) - SCHAR = ::T.let(nil, ::T.untyped) - SHORT = ::T.let(nil, ::T.untyped) - SINT = ::T.let(nil, ::T.untyped) - SLONG = ::T.let(nil, ::T.untyped) - SLONG_LONG = ::T.let(nil, ::T.untyped) - SSHORT = ::T.let(nil, ::T.untyped) - STRING = ::T.let(nil, ::T.untyped) - UCHAR = ::T.let(nil, ::T.untyped) - UINT = ::T.let(nil, ::T.untyped) - UINT16 = ::T.let(nil, ::T.untyped) - UINT32 = ::T.let(nil, ::T.untyped) - UINT64 = ::T.let(nil, ::T.untyped) - UINT8 = ::T.let(nil, ::T.untyped) - ULONG = ::T.let(nil, ::T.untyped) - ULONG_LONG = ::T.let(nil, ::T.untyped) - USHORT = ::T.let(nil, ::T.untyped) - VARARGS = ::T.let(nil, ::T.untyped) - VOID = ::T.let(nil, ::T.untyped) -end - -FFI::Type::Array = FFI::ArrayType - -FFI::Type::Function = FFI::FunctionType - -FFI::Type::Struct = FFI::StructByValue - -class FalseClass - include ::JSON::Ext::Generator::GeneratorMethods::FalseClass -end - -class Fiber - def backtrace(*arg); end - - def backtrace_locations(*arg); end - - def blocking?(); end - - def initialize(*arg); end - - def transfer(*arg); end -end - -class Fiber - def self.blocking?(); end - - def self.current(); end - - def self.current_scheduler(); end - - def self.schedule(*arg); end - - def self.scheduler(); end - - def self.set_scheduler(arg); end -end - -class File - def self.absolute_path?(arg); end - - def self.exists?(arg); end -end - -module FileUtils - include ::FileUtils::StreamUtils_ - LN_SUPPORTED = ::T.let(nil, ::T.untyped) - RUBY = ::T.let(nil, ::T.untyped) -end - -module FileUtils::DryRun - include ::FileUtils - include ::FileUtils::StreamUtils_ - include ::FileUtils::LowMethods -end - -module FileUtils::DryRun - extend ::FileUtils::DryRun - extend ::FileUtils - extend ::FileUtils::StreamUtils_ - extend ::FileUtils::LowMethods -end - -module FileUtils::NoWrite - include ::FileUtils - include ::FileUtils::StreamUtils_ - include ::FileUtils::LowMethods -end - -module FileUtils::NoWrite - extend ::FileUtils::NoWrite - extend ::FileUtils - extend ::FileUtils::StreamUtils_ - extend ::FileUtils::LowMethods -end - -module FileUtils::Verbose - include ::FileUtils - include ::FileUtils::StreamUtils_ -end - -module FileUtils::Verbose - extend ::FileUtils::Verbose - extend ::FileUtils - extend ::FileUtils::StreamUtils_ -end - -module FileUtils - extend ::FileUtils::StreamUtils_ -end - -class Float - include ::JSON::Ext::Generator::GeneratorMethods::Float -end - -module Forwardable - VERSION = ::T.let(nil, ::T.untyped) -end - -module Forwardable - def self._compile_method(src, file, line); end - - def self._delegator_method(obj, accessor, method, ali); end - - def self._valid_method?(method); end - - def self.debug(); end - - def self.debug=(debug); end -end - -module GC - def garbage_collect(full_mark: T.unsafe(nil), immediate_mark: T.unsafe(nil), immediate_sweep: T.unsafe(nil)); end -end - -module GC - def self.latest_compact_info(); end - - def self.measure_total_time(); end - - def self.measure_total_time=(flag); end - - def self.total_time(); end - - def self.using_rvargc?(); end - - def self.verify_transient_heap_internal_consistency(); end -end - -module Gem - ConfigMap = ::T.let(nil, ::T.untyped) - HAVE_OPENSSL = ::T.let(nil, ::T.untyped) - KERNEL_WARN_IGNORES_INTERNAL_ENTRIES = ::T.let(nil, ::T.untyped) - RbConfigPriorities = ::T.let(nil, ::T.untyped) - RubyGemsVersion = ::T.let(nil, ::T.untyped) - UNTAINT = ::T.let(nil, ::T.untyped) -end - -class Gem::BasicSpecification - def plugins(); end -end - -module Gem::BundlerVersionFinder - def self.prioritize!(specs); end -end - -class Gem::ConfigFile - def ipv4_fallback_enabled(); end - - def ipv4_fallback_enabled=(ipv4_fallback_enabled); end - DEFAULT_IPV4_FALLBACK_ENABLED = ::T.let(nil, ::T.untyped) -end - -class Gem::Dependency - def prioritizes_bundler?(); end -end - -class Gem::DependencyList - include ::Gem::TSort -end - -module Gem::Deprecate - def deprecate(name, repl, year, month); end -end - -module Gem::Deprecate - def self.next_rubygems_major_version(); end - - def self.rubygems_deprecate(name, replacement=T.unsafe(nil)); end - - def self.rubygems_deprecate_command(); end -end - -class Gem::Ext::CargoBuilder - def build(_extension, dest_path, results, args=T.unsafe(nil), lib_dir=T.unsafe(nil), cargo_dir=T.unsafe(nil)); end - - def initialize(spec); end - - def spec(); end -end - -class Gem::Ext::CargoBuilder::DylibNotFoundError - def initialize(dir); end -end - -class Gem::Ext::CargoBuilder::DylibNotFoundError -end - -class Gem::Ext::CargoBuilder -end - -class Gem::Ext::ExtConfBuilder -end - -class Gem::Ext::ExtConfBuilder - def self.build(extension, dest_path, results, args=T.unsafe(nil), lib_dir=T.unsafe(nil), extension_dir=T.unsafe(nil)); end - - def self.get_relative_path(path, base); end -end - -class Gem::Installer - include ::Gem::InstallerUninstallerUtils - def ensure_writable_dir(dir); end - - def explicit_version_requirement(name); end - - def gemdeps_load(name); end - - def generate_plugins(); end -end - -Gem::Installer::ExtensionBuildError = Gem::Ext::BuildError - -class Gem::Installer::FakePackage - def copy_to(path); end - - def data_mode(); end - - def data_mode=(data_mode); end - - def dir_mode(); end - - def dir_mode=(dir_mode); end - - def extract_files(destination_dir, pattern=T.unsafe(nil)); end - - def initialize(spec); end - - def prog_mode(); end - - def prog_mode=(prog_mode); end - - def spec(); end - - def spec=(spec); end -end - -class Gem::Installer::FakePackage -end - -class Gem::Installer - def self.inherited(klass); end -end - -module Gem::InstallerUninstallerUtils - def regenerate_plugins_for(spec, plugins_dir); end - - def remove_plugins_for(spec, plugins_dir); end -end - -module Gem::InstallerUninstallerUtils -end - -class Gem::Licenses - LICENSE_REF = ::T.let(nil, ::T.untyped) -end - -class Gem::PathSupport - def home(); end - - def initialize(env); end - - def path(); end - - def spec_cache_dir(); end -end - -class Gem::Platform - def self.match_gem?(platform, gem_name); end - - def self.match_spec?(spec); end - - def self.sort_priority(platform); end -end - -class Gem::Request - extend ::Gem::UserInteraction - extend ::Gem::DefaultUserInteraction - extend ::Gem::Text -end - -class Gem::RequestSet - include ::Gem::TSort -end - -class Gem::RequestSet::Lockfile::Tokenizer::Token - def self.keyword_init?(); end -end - -class Gem::Requirement - def _sorted_requirements(); end -end - -class Gem::Resolver::APISet::GemParser - def parse(line); end -end - -class Gem::Resolver::APISet::GemParser -end - -class Gem::Resolver::APISpecification - def self.new(set, api_data); end -end - -class Gem::Resolver::ActivationRequest - def eql?(other); end -end - -class Gem::Resolver::CurrentSet -end - -class Gem::Resolver::CurrentSet -end - -class Gem::Resolver::IndexSpecification - def ==(other); end -end - -class Gem::Resolver::InstallerSet - def force(); end - - def force=(force); end -end - -class Gem::Resolver::LocalSpecification -end - -class Gem::Resolver::LocalSpecification -end - -module Gem::Resolver::Molinillo::Delegates::ResolutionState - def unused_unwind_options(); end -end - -module Gem::Resolver::Molinillo::Delegates::SpecificationProvider - def dependencies_equal?(dependencies, other_dependencies); end -end - -class Gem::Resolver::Molinillo::DependencyGraph - include ::Gem::TSort -end - -class Gem::Resolver::Molinillo::DependencyGraph::Edge - def self.keyword_init?(); end -end - -class Gem::Resolver::Molinillo::DependencyGraph::Log - def add_edge_no_circular(graph, origin, destination, requirement); end - - def add_vertex(graph, name, payload, root); end - - def delete_edge(graph, origin_name, destination_name, requirement); end - - def detach_vertex_named(graph, name); end - - def each(&blk); end - - def pop!(graph); end - - def reverse_each(); end - - def rewind_to(graph, tag); end - - def set_payload(graph, name, payload); end - - def tag(graph, tag); end -end - -class Gem::Resolver::Molinillo::DependencyGraph::Log - extend ::Enumerable -end - -class Gem::Resolver::Molinillo::DependencyGraph::Vertex - def _path_to?(other, visited=T.unsafe(nil)); end - - def _recursive_predecessors(vertices=T.unsafe(nil)); end - - def _recursive_successors(vertices=T.unsafe(nil)); end -end - -class Gem::Resolver::Molinillo::ResolutionState - def unused_unwind_options(); end - - def unused_unwind_options=(_); end -end - -class Gem::Resolver::Molinillo::ResolutionState - def self.keyword_init?(); end -end - -class Gem::Resolver::Molinillo::Resolver::Resolution::Conflict - def possibility_set(); end - - def possibility_set=(_); end - - def underlying_error(); end - - def underlying_error=(_); end -end - -class Gem::Resolver::Molinillo::Resolver::Resolution::Conflict - def self.keyword_init?(); end -end - -class Gem::Resolver::Molinillo::Resolver::Resolution::PossibilitySet - def dependencies(); end - - def dependencies=(_); end - - def latest_version(); end - - def possibilities(); end - - def possibilities=(_); end -end - -class Gem::Resolver::Molinillo::Resolver::Resolution::PossibilitySet - def self.[](*arg); end - - def self.keyword_init?(); end - - def self.members(); end -end - -class Gem::Resolver::Molinillo::Resolver::Resolution::UnwindDetails - include ::Comparable - def all_requirements(); end - - def conflicting_requirements(); end - - def conflicting_requirements=(_); end - - def requirement_tree(); end - - def requirement_tree=(_); end - - def requirement_trees(); end - - def requirement_trees=(_); end - - def requirements_unwound_to_instead(); end - - def requirements_unwound_to_instead=(_); end - - def reversed_requirement_tree_index(); end - - def state_index(); end - - def state_index=(_); end - - def state_requirement(); end - - def state_requirement=(_); end - - def sub_dependencies_to_avoid(); end - - def unwinding_to_primary_requirement?(); end -end - -class Gem::Resolver::Molinillo::Resolver::Resolution::UnwindDetails - def self.[](*arg); end - - def self.keyword_init?(); end - - def self.members(); end -end - -module Gem::Resolver::Molinillo::SpecificationProvider - def dependencies_equal?(dependencies, other_dependencies); end -end - -class Gem::Resolver::Molinillo::VersionConflict - include ::Gem::Resolver::Molinillo::Delegates::SpecificationProvider - def message_with_trees(opts=T.unsafe(nil)); end - - def specification_provider(); end -end - -class Gem::Resolver::Specification - def required_ruby_version(); end - - def required_rubygems_version(); end -end - -class Gem::RuntimeRequirementNotMetError - def suggestion(); end - - def suggestion=(suggestion); end -end - -class Gem::RuntimeRequirementNotMetError -end - -class Gem::SpecFetcher - include ::Gem::UserInteraction - include ::Gem::DefaultUserInteraction - include ::Gem::Text - def available_specs(type); end - - def detect(type=T.unsafe(nil)); end - - def initialize(sources=T.unsafe(nil)); end - - def latest_specs(); end - - def prerelease_specs(); end - - def search_for_dependency(dependency, matching_platform=T.unsafe(nil)); end - - def sources(); end - - def spec_for_dependency(dependency, matching_platform=T.unsafe(nil)); end - - def specs(); end - - def suggest_gems_from_name(gem_name, type=T.unsafe(nil), num_results=T.unsafe(nil)); end - - def tuples_for(source, type, gracefully_ignore=T.unsafe(nil)); end -end - -class Gem::SpecFetcher - def self.fetcher(); end - - def self.fetcher=(fetcher); end -end - -class Gem::Specification - include ::Bundler::MatchPlatform - include ::Bundler::GemHelpers - include ::Gem::Specification::YamlBackfiller - def _deprecated_validate_dependencies(); end - - def _deprecated_validate_metadata(); end - - def _deprecated_validate_permissions(); end - - def deleted_gem?(); end - - def removed_method_calls(); end - - def to_ruby(); end - REMOVED_METHODS = ::T.let(nil, ::T.untyped) -end - -module Gem::Specification::YamlBackfiller - def to_yaml(opts=T.unsafe(nil)); end -end - -module Gem::Specification::YamlBackfiller -end - -class Gem::Specification - extend ::Gem::Deprecate - extend ::Enumerable - def self.latest_spec_for(name); end - - def self.stubs_for_pattern(pattern, match_platform=T.unsafe(nil)); end -end - -class Gem::SpecificationPolicy - include ::Gem::UserInteraction - include ::Gem::DefaultUserInteraction - include ::Gem::Text - def initialize(specification); end - - def packaging(); end - - def packaging=(packaging); end - - def validate(strict=T.unsafe(nil)); end - - def validate_dependencies(); end - - def validate_duplicate_dependencies(); end - - def validate_metadata(); end - - def validate_optional(strict); end - - def validate_permissions(); end - - def validate_required!(); end - HOMEPAGE_URI_PATTERN = ::T.let(nil, ::T.untyped) - LAZY = ::T.let(nil, ::T.untyped) - LAZY_PATTERN = ::T.let(nil, ::T.untyped) - METADATA_LINK_KEYS = ::T.let(nil, ::T.untyped) - SPECIAL_CHARACTERS = ::T.let(nil, ::T.untyped) - VALID_NAME_PATTERN = ::T.let(nil, ::T.untyped) - VALID_URI_PATTERN = ::T.let(nil, ::T.untyped) -end - -class Gem::SpecificationPolicy -end - -class Gem::StubSpecification - def build_extensions(); end - - def extensions(); end - - def initialize(filename, base_dir, gems_dir, default_gem); end - - def missing_extensions?(); end - - def valid?(); end -end - -class Gem::StubSpecification::StubLine - def extensions(); end - - def full_name(); end - - def initialize(data, extensions); end - - def name(); end - - def platform(); end - - def require_paths(); end - - def version(); end -end - -class Gem::StubSpecification - def self.default_gemspec_stub(filename, base_dir, gems_dir); end - - def self.gemspec_stub(filename, base_dir, gems_dir); end -end - -module Gem::TSort - def each_strongly_connected_component(&block); end - - def each_strongly_connected_component_from(node, id_map=T.unsafe(nil), stack=T.unsafe(nil), &block); end - - def strongly_connected_components(); end - - def tsort(); end - - def tsort_each(&block); end - - def tsort_each_child(node); end - - def tsort_each_node(); end -end - -module Gem::TSort - def self.each_strongly_connected_component(each_node, each_child); end - - def self.each_strongly_connected_component_from(node, each_child, id_map=T.unsafe(nil), stack=T.unsafe(nil)); end - - def self.strongly_connected_components(each_node, each_child); end - - def self.tsort(each_node, each_child); end - - def self.tsort_each(each_node, each_child); end -end - -class Gem::UninstallError - def spec(); end - - def spec=(spec); end -end - -class Gem::UninstallError -end - -class Gem::UnknownCommandError - def initialize(unknown_command); end - - def unknown_command(); end -end - -class Gem::UnknownCommandError - def self.attach_correctable(); end -end - -class Gem::UnknownCommandSpellChecker - def corrections(); end - - def error(); end - - def initialize(error); end -end - -class Gem::UnknownCommandSpellChecker -end - -Gem::UnsatisfiableDepedencyError = Gem::UnsatisfiableDependencyError - -module Gem::Util - def self._deprecated_silent_system(*command); end -end - -Gem::Version::Requirement = Gem::Requirement - -module Gem - def self.activated_gem_paths(); end - - def self.cache_home(); end - - def self.config_home(); end - - def self.data_home(); end - - def self.disable_system_update_message(); end - - def self.disable_system_update_message=(disable_system_update_message); end - - def self.find_config_file(); end - - def self.old_default_bindir(); end - - def self.old_default_dir(); end - - def self.old_default_path(); end - - def self.old_default_specifications_dir(); end - - def self.old_ruby(); end - - def self.open_file(path, flags, &block); end - - def self.plugin_suffix_pattern(); end - - def self.plugin_suffix_regexp(); end - - def self.plugindir(install_dir=T.unsafe(nil)); end - - def self.private_dir(); end - - def self.solaris_platform?(); end -end - -module HTTP - VERSION = ::T.let(nil, ::T.untyped) -end - -class HTTP::Client - HTTP_OR_HTTPS_RE = ::T.let(nil, ::T.untyped) -end - -class HTTP::Connection - BUFFER_SIZE = ::T.let(nil, ::T.untyped) - CLOSE = ::T.let(nil, ::T.untyped) - HTTP_1_0 = ::T.let(nil, ::T.untyped) - HTTP_1_1 = ::T.let(nil, ::T.untyped) - KEEP_ALIVE = ::T.let(nil, ::T.untyped) -end - -class HTTP::ContentType - CHARSET_RE = ::T.let(nil, ::T.untyped) - MIME_TYPE_RE = ::T.let(nil, ::T.untyped) -end - -class HTTP::Cookie - MAX_COOKIES_PER_DOMAIN = ::T.let(nil, ::T.untyped) - MAX_COOKIES_TOTAL = ::T.let(nil, ::T.untyped) - MAX_LENGTH = ::T.let(nil, ::T.untyped) - PERSISTENT_PROPERTIES = ::T.let(nil, ::T.untyped) - UNIX_EPOCH = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -class HTTP::Cookie::Scanner - def initialize(string, logger=T.unsafe(nil)); end - - def parse_cookie_date(s); end - - def scan_cookie(); end - - def scan_dquoted(); end - - def scan_name(); end - - def scan_name_value(comma_as_separator=T.unsafe(nil)); end - - def scan_set_cookie(); end - - def scan_value(comma_as_separator=T.unsafe(nil)); end - - def skip_wsp(); end - RE_BAD_CHAR = ::T.let(nil, ::T.untyped) - RE_COOKIE_COMMA = ::T.let(nil, ::T.untyped) - RE_NAME = ::T.let(nil, ::T.untyped) - RE_WSP = ::T.let(nil, ::T.untyped) -end - -class HTTP::Cookie::Scanner - def self.quote(s); end -end - -module HTTP::FormData - CRLF = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -class HTTP::FormData::File - DEFAULT_MIME = ::T.let(nil, ::T.untyped) -end - -class HTTP::Headers - ACCEPT = ::T.let(nil, ::T.untyped) - ACCEPT_ENCODING = ::T.let(nil, ::T.untyped) - AGE = ::T.let(nil, ::T.untyped) - AUTHORIZATION = ::T.let(nil, ::T.untyped) - CACHE_CONTROL = ::T.let(nil, ::T.untyped) - CANONICAL_NAME_RE = ::T.let(nil, ::T.untyped) - COMPLIANT_NAME_RE = ::T.let(nil, ::T.untyped) - CONNECTION = ::T.let(nil, ::T.untyped) - CONTENT_ENCODING = ::T.let(nil, ::T.untyped) - CONTENT_LENGTH = ::T.let(nil, ::T.untyped) - CONTENT_TYPE = ::T.let(nil, ::T.untyped) - COOKIE = ::T.let(nil, ::T.untyped) - DATE = ::T.let(nil, ::T.untyped) - ETAG = ::T.let(nil, ::T.untyped) - EXPIRES = ::T.let(nil, ::T.untyped) - HOST = ::T.let(nil, ::T.untyped) - IF_MODIFIED_SINCE = ::T.let(nil, ::T.untyped) - IF_NONE_MATCH = ::T.let(nil, ::T.untyped) - LAST_MODIFIED = ::T.let(nil, ::T.untyped) - LOCATION = ::T.let(nil, ::T.untyped) - PROXY_AUTHORIZATION = ::T.let(nil, ::T.untyped) - SET_COOKIE = ::T.let(nil, ::T.untyped) - TRANSFER_ENCODING = ::T.let(nil, ::T.untyped) - USER_AGENT = ::T.let(nil, ::T.untyped) - VARY = ::T.let(nil, ::T.untyped) -end - -class HTTP::Redirector - REDIRECT_CODES = ::T.let(nil, ::T.untyped) - SEE_OTHER_ALLOWED_VERBS = ::T.let(nil, ::T.untyped) - STRICT_SENSITIVE_CODES = ::T.let(nil, ::T.untyped) - UNSAFE_VERBS = ::T.let(nil, ::T.untyped) -end - -class HTTP::Request - METHODS = ::T.let(nil, ::T.untyped) - PORTS = ::T.let(nil, ::T.untyped) - SCHEMES = ::T.let(nil, ::T.untyped) - USER_AGENT = ::T.let(nil, ::T.untyped) -end - -class HTTP::Request::Writer - CHUNKED = ::T.let(nil, ::T.untyped) - CHUNKED_END = ::T.let(nil, ::T.untyped) - CRLF = ::T.let(nil, ::T.untyped) - ZERO = ::T.let(nil, ::T.untyped) -end - -class HTTP::Response::Status - REASONS = ::T.let(nil, ::T.untyped) - RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped) - SYMBOLS = ::T.let(nil, ::T.untyped) - SYMBOL_CODES = ::T.let(nil, ::T.untyped) -end - -class HTTP::Timeout::PerOperation - CONNECT_TIMEOUT = ::T.let(nil, ::T.untyped) - READ_TIMEOUT = ::T.let(nil, ::T.untyped) - WRITE_TIMEOUT = ::T.let(nil, ::T.untyped) -end - -class HTTP::URI - HTTPS_SCHEME = ::T.let(nil, ::T.untyped) - HTTP_SCHEME = ::T.let(nil, ::T.untyped) - NORMALIZER = ::T.let(nil, ::T.untyped) -end - -class Hash - include ::JSON::Ext::Generator::GeneratorMethods::Hash - def deconstruct_keys(arg); end -end - -class Hash - def self.ruby2_keywords_hash(arg); end - - def self.ruby2_keywords_hash?(arg); end -end - -module Hashdiff - VERSION = ::T.let(nil, ::T.untyped) -end - -class IO - def nonblock(*arg); end - - def nonblock=(nonblock); end - - def nonblock?(); end - - def nread(); end - - def pathconf(arg); end - - def ready?(); end - - def wait(*arg); end - - def wait_priority(*arg); end - - def wait_readable(*arg); end - - def wait_writable(*arg); end - PRIORITY = ::T.let(nil, ::T.untyped) - READABLE = ::T.let(nil, ::T.untyped) - WRITABLE = ::T.let(nil, ::T.untyped) -end - -class IO::Buffer - include ::Comparable - def clear(*arg); end - - def copy(*arg); end - - def empty?(); end - - def external?(); end - - def free(); end - - def get_string(*arg); end - - def get_value(arg, arg1); end - - def hexdump(); end - - def initialize(*arg); end - - def internal?(); end - - def locked(); end - - def locked?(); end - - def mapped?(); end - - def null?(); end - - def pread(arg, arg1, arg2); end - - def pwrite(arg, arg1, arg2); end - - def read(arg, arg1); end - - def readonly?(); end - - def resize(arg); end - - def set_string(*arg); end - - def set_value(arg, arg1, arg2); end - - def size(); end - - def slice(arg, arg1); end - - def transfer(); end - - def valid?(); end - - def write(arg, arg1); end - BIG_ENDIAN = ::T.let(nil, ::T.untyped) - DEFAULT_SIZE = ::T.let(nil, ::T.untyped) - EXTERNAL = ::T.let(nil, ::T.untyped) - HOST_ENDIAN = ::T.let(nil, ::T.untyped) - INTERNAL = ::T.let(nil, ::T.untyped) - LITTLE_ENDIAN = ::T.let(nil, ::T.untyped) - LOCKED = ::T.let(nil, ::T.untyped) - MAPPED = ::T.let(nil, ::T.untyped) - NETWORK_ENDIAN = ::T.let(nil, ::T.untyped) - PAGE_SIZE = ::T.let(nil, ::T.untyped) - PRIVATE = ::T.let(nil, ::T.untyped) - READONLY = ::T.let(nil, ::T.untyped) -end - -class IO::Buffer::AccessError -end - -class IO::Buffer::AccessError -end - -class IO::Buffer::AllocationError -end - -class IO::Buffer::AllocationError -end - -class IO::Buffer::InvalidatedError -end - -class IO::Buffer::InvalidatedError -end - -class IO::Buffer::LockedError -end - -class IO::Buffer::LockedError -end - -class IO::Buffer - def self.for(arg); end - - def self.map(*arg); end -end - -IO::EWOULDBLOCKWaitReadable = IO::EAGAINWaitReadable - -IO::EWOULDBLOCKWaitWritable = IO::EAGAINWaitWritable - -class IO - def self.new(*arg); end -end - -class IPAddr - def ==(other); end - - def initialize(addr=T.unsafe(nil), family=T.unsafe(nil)); end - - def netmask(); end - - def zone_id(); end - - def zone_id=(zid); end - VERSION = ::T.let(nil, ::T.untyped) -end - -class Integer - include ::JSON::Ext::Generator::GeneratorMethods::Integer - def to_bn(); end -end - -class Integer - def self.try_convert(arg); end -end - -class JSON::Ext::Generator::State - def escape_slash(); end - - def escape_slash=(escape_slash); end - - def escape_slash?(); end -end - -class JSON::Ext::Generator::State - def self.from_state(arg); end -end - -class JSON::Ext::Parser - def initialize(*arg); end -end - -JSON::Parser = JSON::Ext::Parser - -JSON::State = JSON::Ext::Generator::State - -JSON::UnparserError = JSON::GeneratorError - -module JSON - def self.create_fast_state(); end - - def self.create_pretty_state(); end - - def self.load_file(filespec, opts=T.unsafe(nil)); end - - def self.load_file!(filespec, opts=T.unsafe(nil)); end -end - -module Kernel - def pretty_inspect(); end -end - -module Kernel - def self.at_exit(); end -end - -class KeyError - include ::DidYouMean::Correctable -end - -module LLHttp - VERSION = ::T.let(nil, ::T.untyped) -end - -class LLHttp::Parser - CALLBACKS = ::T.let(nil, ::T.untyped) - CALLBACKS_WITH_DATA = ::T.let(nil, ::T.untyped) - LLHTTP_TYPES = ::T.let(nil, ::T.untyped) -end - -class Layer - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -class LoadError - include ::DidYouMean::Correctable -end - -class Logger - def debug!(); end - - def error!(); end - - def fatal!(); end - - def info!(); end - - def warn!(); end - SEV_LABEL = ::T.let(nil, ::T.untyped) -end - -class Logger::Formatter - DatetimeFormat = ::T.let(nil, ::T.untyped) - Format = ::T.let(nil, ::T.untyped) -end - -class Logger::LogDevice - include ::MonitorMixin -end - -module Logger::Period - SiD = ::T.let(nil, ::T.untyped) -end - -class MatchData - def match(arg); end - - def match_length(arg); end -end - -class Method - def private?(); end - - def protected?(); end - - def public?(); end -end - -MiniTest = Minitest - -module Minitest - VERSION = ::T.let(nil, ::T.untyped) -end - -module Minitest::Assertions - E = ::T.let(nil, ::T.untyped) - UNDEFINED = ::T.let(nil, ::T.untyped) -end - -class Minitest::BacktraceFilter - MT_RE = ::T.let(nil, ::T.untyped) -end - -class Minitest::Runnable - SIGNALS = ::T.let(nil, ::T.untyped) -end - -class Minitest::Spec - TYPES = ::T.let(nil, ::T.untyped) -end - -module Minitest::Spec::DSL - TYPES = ::T.let(nil, ::T.untyped) -end - -class Minitest::Test - PASSTHROUGH_EXCEPTIONS = ::T.let(nil, ::T.untyped) - TEARDOWN_METHODS = ::T.let(nil, ::T.untyped) -end - -class Minitest::Unit - VERSION = ::T.let(nil, ::T.untyped) -end - -class Monitor - def enter(); end - - def exit(); end - - def mon_check_owner(); end - - def mon_enter(); end - - def mon_exit(); end - - def mon_locked?(); end - - def mon_owned?(); end - - def mon_synchronize(); end - - def mon_try_enter(); end - - def new_cond(); end - - def synchronize(); end - - def try_enter(); end - - def try_mon_enter(); end - - def wait_for_cond(arg, arg1); end -end - -module MonitorMixin - def initialize(*arg, **arg1, &arg2); end -end - -class MonitorMixin::ConditionVariable - def initialize(monitor); end -end - -module Mutex_m - VERSION = ::T.let(nil, ::T.untyped) -end - -class NameError - include ::ErrorHighlight::CoreExt - include ::DidYouMean::Correctable -end - -class Net::BufferedIO - def write_timeout(); end - - def write_timeout=(write_timeout); end -end - -class Net::HTTP - def extra_chain_cert(); end - - def extra_chain_cert=(extra_chain_cert); end - - def ipaddr(); end - - def ipaddr=(addr); end - - def max_retries(); end - - def max_retries=(retries); end - - def max_version(); end - - def max_version=(max_version); end - - def min_version(); end - - def min_version=(min_version); end - - def verify_hostname(); end - - def verify_hostname=(verify_hostname); end - - def write_timeout(); end - - def write_timeout=(sec); end - ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -Net::HTTP::ProxyMod = Net::HTTP::ProxyDelta - -class Net::HTTPAlreadyReported - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPAlreadyReported -end - -Net::HTTPClientError::EXCEPTION_TYPE = Net::HTTPServerException - -Net::HTTPClientErrorCode = Net::HTTPClientError - -class Net::HTTPEarlyHints - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPEarlyHints -end - -Net::HTTPFatalErrorCode = Net::HTTPClientError - -class Net::HTTPInformation -end - -Net::HTTPInformationCode::EXCEPTION_TYPE = Net::HTTPError - -class Net::HTTPInformation -end - -class Net::HTTPLoopDetected - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPLoopDetected -end - -class Net::HTTPMisdirectedRequest - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPMisdirectedRequest -end - -Net::HTTPMovedTemporarily = Net::HTTPFound - -Net::HTTPMultipleChoice = Net::HTTPMultipleChoices - -class Net::HTTPNotExtended - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPNotExtended -end - -class Net::HTTPPayloadTooLarge - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPPayloadTooLarge -end - -class Net::HTTPProcessing - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPProcessing -end - -class Net::HTTPRangeNotSatisfiable - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPRangeNotSatisfiable -end - -Net::HTTPRedirection::EXCEPTION_TYPE = Net::HTTPRetriableError - -Net::HTTPRedirectionCode = Net::HTTPRedirection - -Net::HTTPRequestURITooLarge = Net::HTTPURITooLong - -Net::HTTPResponceReceiver = Net::HTTPResponse - -Net::HTTPResponseReceiver = Net::HTTPResponse - -Net::HTTPRetriableCode = Net::HTTPRedirection - -Net::HTTPServerError::EXCEPTION_TYPE = Net::HTTPFatalError - -Net::HTTPServerErrorCode = Net::HTTPServerError - -Net::HTTPSession = Net::HTTP - -Net::HTTPSuccess::EXCEPTION_TYPE = Net::HTTPError - -Net::HTTPSuccessCode = Net::HTTPSuccess - -class Net::HTTPURITooLong - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPURITooLong -end - -Net::HTTPUnknownResponse::EXCEPTION_TYPE = Net::HTTPError - -class Net::HTTPVariantAlsoNegotiates - HAS_BODY = ::T.let(nil, ::T.untyped) -end - -class Net::HTTPVariantAlsoNegotiates -end - -Net::NetPrivate::HTTPRequest = Net::HTTPRequest - -Net::NetPrivate::Socket = Net::InternetMessageIO - -Net::ProtocRetryError = Net::ProtoRetriableError - -class Net::Protocol - VERSION = ::T.let(nil, ::T.untyped) -end - -class Net::ReadTimeout - def initialize(io=T.unsafe(nil)); end - - def io(); end -end - -class Net::WriteTimeout - def initialize(io=T.unsafe(nil)); end - - def io(); end -end - -class NilClass - include ::JSON::Ext::Generator::GeneratorMethods::NilClass -end - -class NoMatchingPatternError -end - -class NoMatchingPatternError -end - -class NoMatchingPatternKeyError - include ::DidYouMean::Correctable - def key(); end - - def matchee(); end -end - -class NoMatchingPatternKeyError -end - -class Object - include ::JSON::Ext::Generator::GeneratorMethods::Object - include ::PP::ObjectMixin - def to_yaml(options=T.unsafe(nil)); end - ARGF = ::T.let(nil, ::T.untyped) - ARGV = ::T.let(nil, ::T.untyped) - CROSS_COMPILING = ::T.let(nil, ::T.untyped) - ENV = ::T.let(nil, ::T.untyped) - RUBY_COPYRIGHT = ::T.let(nil, ::T.untyped) - RUBY_DESCRIPTION = ::T.let(nil, ::T.untyped) - RUBY_ENGINE = ::T.let(nil, ::T.untyped) - RUBY_ENGINE_VERSION = ::T.let(nil, ::T.untyped) - RUBY_PATCHLEVEL = ::T.let(nil, ::T.untyped) - RUBY_PLATFORM = ::T.let(nil, ::T.untyped) - RUBY_RELEASE_DATE = ::T.let(nil, ::T.untyped) - RUBY_REVISION = ::T.let(nil, ::T.untyped) - RUBY_VERSION = ::T.let(nil, ::T.untyped) - STDERR = ::T.let(nil, ::T.untyped) - STDIN = ::T.let(nil, ::T.untyped) - STDOUT = ::T.let(nil, ::T.untyped) - TOPLEVEL_BINDING = ::T.let(nil, ::T.untyped) -end - -class Object - def self.yaml_tag(url); end -end - -class OpenSSL::ASN1::ASN1Data - def indefinite_length(); end - - def indefinite_length=(indefinite_length); end -end - -class OpenSSL::BN - def +@(); end - - def -@(); end - - def /(arg); end - - def abs(); end - - def get_flags(arg); end - - def negative?(); end - - def set_flags(arg); end - CONSTTIME = ::T.let(nil, ::T.untyped) -end - -module OpenSSL::Buffering - def getbyte(); end -end - -class OpenSSL::Buffering::Buffer - def <<(string); end - - def concat(string); end - - def initialize(); end - BINARY = ::T.let(nil, ::T.untyped) -end - -class OpenSSL::Buffering::Buffer -end - -class OpenSSL::Cipher - def ccm_data_len=(ccm_data_len); end -end - -class OpenSSL::HMAC - def ==(other); end - - def base64digest(); end -end - -class OpenSSL::HMAC - def self.base64digest(digest, key, data); end -end - -module OpenSSL::Marshal - def _dump(_level); end -end - -module OpenSSL::Marshal::ClassMethods - def _load(string); end -end - -module OpenSSL::Marshal::ClassMethods -end - -module OpenSSL::Marshal - def self.included(base); end -end - -class OpenSSL::OCSP::Request - def signed?(); end -end - -OpenSSL::PKCS7::Signer = OpenSSL::PKCS7::SignerInfo - -class OpenSSL::PKey::DH - include ::OpenSSL::Marshal -end - -class OpenSSL::PKey::DH - extend ::OpenSSL::Marshal::ClassMethods - def self.new(*args, &blk); end -end - -class OpenSSL::PKey::DSA - include ::OpenSSL::Marshal -end - -class OpenSSL::PKey::DSA - extend ::OpenSSL::Marshal::ClassMethods - def self.new(*args, &blk); end -end - -class OpenSSL::PKey::EC - include ::OpenSSL::Marshal - EXPLICIT_CURVE = ::T.let(nil, ::T.untyped) -end - -class OpenSSL::PKey::EC::Point - def add(arg); end - - def to_octet_string(arg); end -end - -class OpenSSL::PKey::EC - extend ::OpenSSL::Marshal::ClassMethods -end - -class OpenSSL::PKey::PKey - def compare?(arg); end - - def decrypt(*arg); end - - def derive(*arg); end - - def encrypt(*arg); end - - def oid(); end - - def private_to_der(*arg); end - - def private_to_pem(*arg); end - - def public_to_der(); end - - def public_to_pem(); end - - def sign_raw(*arg); end - - def to_text(); end - - def verify_raw(*arg); end - - def verify_recover(*arg); end -end - -class OpenSSL::PKey::RSA - include ::OpenSSL::Marshal -end - -class OpenSSL::PKey::RSA - extend ::OpenSSL::Marshal::ClassMethods - def self.new(*args, &blk); end -end - -module OpenSSL::PKey - def self.generate_key(*arg); end - - def self.generate_parameters(*arg); end -end - -module OpenSSL::SSL - OP_ALLOW_NO_DHE_KEX = ::T.let(nil, ::T.untyped) - OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ::T.let(nil, ::T.untyped) - OP_CRYPTOPRO_TLSEXT_BUG = ::T.let(nil, ::T.untyped) - OP_ENABLE_MIDDLEBOX_COMPAT = ::T.let(nil, ::T.untyped) - OP_LEGACY_SERVER_CONNECT = ::T.let(nil, ::T.untyped) - OP_NO_ANTI_REPLAY = ::T.let(nil, ::T.untyped) - OP_NO_ENCRYPT_THEN_MAC = ::T.let(nil, ::T.untyped) - OP_NO_RENEGOTIATION = ::T.let(nil, ::T.untyped) - OP_NO_TLSv1_3 = ::T.let(nil, ::T.untyped) - OP_PRIORITIZE_CHACHA = ::T.let(nil, ::T.untyped) - OP_SAFARI_ECDHE_ECDSA_BUG = ::T.let(nil, ::T.untyped) - OP_TLSEXT_PADDING = ::T.let(nil, ::T.untyped) - SSL2_VERSION = ::T.let(nil, ::T.untyped) - SSL3_VERSION = ::T.let(nil, ::T.untyped) - TLS1_1_VERSION = ::T.let(nil, ::T.untyped) - TLS1_2_VERSION = ::T.let(nil, ::T.untyped) - TLS1_3_VERSION = ::T.let(nil, ::T.untyped) - TLS1_VERSION = ::T.let(nil, ::T.untyped) -end - -class OpenSSL::SSL::SSLContext - def alpn_protocols(); end - - def alpn_protocols=(alpn_protocols); end - - def alpn_select_cb(); end - - def alpn_select_cb=(alpn_select_cb); end - - def enable_fallback_scsv(); end - - def max_version=(version); end - - def min_version=(version); end - - def tmp_dh=(tmp_dh); end - DEFAULT_TMP_DH_CALLBACK = ::T.let(nil, ::T.untyped) -end - -class OpenSSL::SSL::SSLSocket - def alpn_protocol(); end - - def finished_message(); end - - def peer_finished_message(); end - - def tmp_key(); end -end - -class OpenSSL::SSL::SSLSocket - def self.open(remote_host, remote_port, local_host=T.unsafe(nil), local_port=T.unsafe(nil), context: T.unsafe(nil)); end -end - -module OpenSSL::SSL::SocketForwarder - def fileno(); end -end - -module OpenSSL::Timestamp -end - -class OpenSSL::Timestamp::Factory - def additional_certs(); end - - def additional_certs=(additional_certs); end - - def allowed_digests(); end - - def allowed_digests=(allowed_digests); end - - def create_timestamp(arg, arg1, arg2); end - - def default_policy_id(); end - - def default_policy_id=(default_policy_id); end - - def gen_time(); end - - def gen_time=(gen_time); end - - def serial_number(); end - - def serial_number=(serial_number); end -end - -class OpenSSL::Timestamp::Factory -end - -class OpenSSL::Timestamp::Request - def algorithm(); end - - def algorithm=(algorithm); end - - def cert_requested=(cert_requested); end - - def cert_requested?(); end - - def initialize(*arg); end - - def message_imprint(); end - - def message_imprint=(message_imprint); end - - def nonce(); end - - def nonce=(nonce); end - - def policy_id(); end - - def policy_id=(policy_id); end - - def to_der(); end - - def version(); end - - def version=(version); end -end - -class OpenSSL::Timestamp::Request -end - -class OpenSSL::Timestamp::Response - def failure_info(); end - - def initialize(arg); end - - def status(); end - - def status_text(); end - - def to_der(); end - - def token(); end - - def token_info(); end - - def tsa_certificate(); end - - def verify(*arg); end - GRANTED = ::T.let(nil, ::T.untyped) - GRANTED_WITH_MODS = ::T.let(nil, ::T.untyped) - REJECTION = ::T.let(nil, ::T.untyped) - REVOCATION_NOTIFICATION = ::T.let(nil, ::T.untyped) - REVOCATION_WARNING = ::T.let(nil, ::T.untyped) - WAITING = ::T.let(nil, ::T.untyped) -end - -class OpenSSL::Timestamp::Response -end - -class OpenSSL::Timestamp::TimestampError -end - -class OpenSSL::Timestamp::TimestampError -end - -class OpenSSL::Timestamp::TokenInfo - def algorithm(); end - - def gen_time(); end - - def initialize(arg); end - - def message_imprint(); end - - def nonce(); end - - def ordering(); end - - def policy_id(); end - - def serial_number(); end - - def to_der(); end - - def version(); end -end - -class OpenSSL::Timestamp::TokenInfo -end - -module OpenSSL::Timestamp -end - -module OpenSSL::X509 - V_ERR_CA_KEY_TOO_SMALL = ::T.let(nil, ::T.untyped) - V_ERR_CA_MD_TOO_WEAK = ::T.let(nil, ::T.untyped) - V_ERR_CRL_PATH_VALIDATION_ERROR = ::T.let(nil, ::T.untyped) - V_ERR_DANE_NO_MATCH = ::T.let(nil, ::T.untyped) - V_ERR_DIFFERENT_CRL_SCOPE = ::T.let(nil, ::T.untyped) - V_ERR_EE_KEY_TOO_SMALL = ::T.let(nil, ::T.untyped) - V_ERR_EMAIL_MISMATCH = ::T.let(nil, ::T.untyped) - V_ERR_EXCLUDED_VIOLATION = ::T.let(nil, ::T.untyped) - V_ERR_HOSTNAME_MISMATCH = ::T.let(nil, ::T.untyped) - V_ERR_INVALID_CALL = ::T.let(nil, ::T.untyped) - V_ERR_INVALID_EXTENSION = ::T.let(nil, ::T.untyped) - V_ERR_INVALID_NON_CA = ::T.let(nil, ::T.untyped) - V_ERR_INVALID_POLICY_EXTENSION = ::T.let(nil, ::T.untyped) - V_ERR_IP_ADDRESS_MISMATCH = ::T.let(nil, ::T.untyped) - V_ERR_KEYUSAGE_NO_CRL_SIGN = ::T.let(nil, ::T.untyped) - V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE = ::T.let(nil, ::T.untyped) - V_ERR_NO_EXPLICIT_POLICY = ::T.let(nil, ::T.untyped) - V_ERR_NO_VALID_SCTS = ::T.let(nil, ::T.untyped) - V_ERR_OCSP_CERT_UNKNOWN = ::T.let(nil, ::T.untyped) - V_ERR_OCSP_VERIFY_FAILED = ::T.let(nil, ::T.untyped) - V_ERR_OCSP_VERIFY_NEEDED = ::T.let(nil, ::T.untyped) - V_ERR_PATH_LOOP = ::T.let(nil, ::T.untyped) - V_ERR_PERMITTED_VIOLATION = ::T.let(nil, ::T.untyped) - V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED = ::T.let(nil, ::T.untyped) - V_ERR_PROXY_PATH_LENGTH_EXCEEDED = ::T.let(nil, ::T.untyped) - V_ERR_PROXY_SUBJECT_NAME_VIOLATION = ::T.let(nil, ::T.untyped) - V_ERR_STORE_LOOKUP = ::T.let(nil, ::T.untyped) - V_ERR_SUBTREE_MINMAX = ::T.let(nil, ::T.untyped) - V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = ::T.let(nil, ::T.untyped) - V_ERR_SUITE_B_INVALID_ALGORITHM = ::T.let(nil, ::T.untyped) - V_ERR_SUITE_B_INVALID_CURVE = ::T.let(nil, ::T.untyped) - V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM = ::T.let(nil, ::T.untyped) - V_ERR_SUITE_B_INVALID_VERSION = ::T.let(nil, ::T.untyped) - V_ERR_SUITE_B_LOS_NOT_ALLOWED = ::T.let(nil, ::T.untyped) - V_ERR_UNABLE_TO_GET_CRL_ISSUER = ::T.let(nil, ::T.untyped) - V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION = ::T.let(nil, ::T.untyped) - V_ERR_UNHANDLED_CRITICAL_EXTENSION = ::T.let(nil, ::T.untyped) - V_ERR_UNNESTED_RESOURCE = ::T.let(nil, ::T.untyped) - V_ERR_UNSPECIFIED = ::T.let(nil, ::T.untyped) - V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX = ::T.let(nil, ::T.untyped) - V_ERR_UNSUPPORTED_CONSTRAINT_TYPE = ::T.let(nil, ::T.untyped) - V_ERR_UNSUPPORTED_EXTENSION_FEATURE = ::T.let(nil, ::T.untyped) - V_ERR_UNSUPPORTED_NAME_SYNTAX = ::T.let(nil, ::T.untyped) - V_FLAG_NO_CHECK_TIME = ::T.let(nil, ::T.untyped) - V_FLAG_PARTIAL_CHAIN = ::T.let(nil, ::T.untyped) - V_FLAG_SUITEB_128_LOS = ::T.let(nil, ::T.untyped) - V_FLAG_SUITEB_128_LOS_ONLY = ::T.let(nil, ::T.untyped) - V_FLAG_SUITEB_192_LOS = ::T.let(nil, ::T.untyped) - V_FLAG_TRUSTED_FIRST = ::T.let(nil, ::T.untyped) - V_FLAG_USE_CHECK_TIME = ::T.let(nil, ::T.untyped) -end - -class OpenSSL::X509::Attribute - include ::OpenSSL::Marshal - def ==(other); end -end - -class OpenSSL::X509::Attribute - extend ::OpenSSL::Marshal::ClassMethods -end - -class OpenSSL::X509::CRL - include ::OpenSSL::Marshal - include ::OpenSSL::X509::Extension::AuthorityKeyIdentifier - include ::OpenSSL::X509::Extension::Helpers - def ==(other); end -end - -class OpenSSL::X509::CRL - extend ::OpenSSL::Marshal::ClassMethods -end - -class OpenSSL::X509::Certificate - include ::OpenSSL::Marshal - include ::OpenSSL::X509::Extension::SubjectKeyIdentifier - include ::OpenSSL::X509::Extension::AuthorityKeyIdentifier - include ::OpenSSL::X509::Extension::CRLDistributionPoints - include ::OpenSSL::X509::Extension::AuthorityInfoAccess - include ::OpenSSL::X509::Extension::Helpers -end - -class OpenSSL::X509::Certificate - extend ::OpenSSL::Marshal::ClassMethods - def self.load(arg); end - - def self.load_file(path); end -end - -class OpenSSL::X509::Extension - include ::OpenSSL::Marshal - def ==(other); end - - def value_der(); end -end - -module OpenSSL::X509::Extension::AuthorityInfoAccess - include ::OpenSSL::X509::Extension::Helpers - def ca_issuer_uris(); end - - def ocsp_uris(); end -end - -module OpenSSL::X509::Extension::AuthorityInfoAccess -end - -module OpenSSL::X509::Extension::AuthorityKeyIdentifier - include ::OpenSSL::X509::Extension::Helpers - def authority_key_identifier(); end -end - -module OpenSSL::X509::Extension::AuthorityKeyIdentifier -end - -module OpenSSL::X509::Extension::CRLDistributionPoints - include ::OpenSSL::X509::Extension::Helpers - def crl_uris(); end -end - -module OpenSSL::X509::Extension::CRLDistributionPoints -end - -module OpenSSL::X509::Extension::Helpers - def find_extension(oid); end -end - -module OpenSSL::X509::Extension::Helpers -end - -module OpenSSL::X509::Extension::SubjectKeyIdentifier - include ::OpenSSL::X509::Extension::Helpers - def subject_key_identifier(); end -end - -module OpenSSL::X509::Extension::SubjectKeyIdentifier -end - -class OpenSSL::X509::Extension - extend ::OpenSSL::Marshal::ClassMethods -end - -class OpenSSL::X509::Name - include ::OpenSSL::Marshal - def to_utf8(); end -end - -class OpenSSL::X509::Name - extend ::OpenSSL::Marshal::ClassMethods -end - -class OpenSSL::X509::Request - include ::OpenSSL::Marshal - def ==(other); end -end - -class OpenSSL::X509::Request - extend ::OpenSSL::Marshal::ClassMethods -end - -class OpenSSL::X509::Revoked - def ==(other); end - - def to_der(); end -end - -module OpenSSL - def self.fips_mode(); end - - def self.fixed_length_secure_compare(arg, arg1); end - - def self.secure_compare(a, b); end -end - -class OpenStruct - def __id__!(); end - - def __send__!(*arg); end - - def class!(); end - - def clone!(freeze: T.unsafe(nil)); end - - def define_singleton_method!(*arg); end - - def delete_field!(name); end - - def dig!(name, *names); end - - def display!(*arg); end - - def dup!(); end - - def each_pair!(); end - - def encode_with(coder); end - - def encode_with!(coder); end - - def enum_for!(*arg); end - - def extend!(mod, *args); end - - def freeze!(); end - - def gem!(dep, *reqs); end - - def hash!(); end - - def init_with(coder); end - - def init_with!(coder); end - - def inspect!(); end - - def instance_eval!(*arg); end - - def instance_exec!(*arg); end - - def instance_variable_get!(arg); end - - def instance_variable_set!(arg, arg1); end - - def instance_variables!(); end - - def itself!(); end - - def marshal_dump!(); end - - def method!(arg); end - - def methods!(*arg); end - - def object_id!(); end - - def private_methods!(*arg); end - - def protected_methods!(*arg); end - - def public_method!(arg); end - - def public_methods!(*arg); end - - def public_send!(*arg); end - - def remove_instance_variable!(arg); end - - def send!(*arg); end - - def singleton_class!(); end - - def singleton_method!(arg); end - - def singleton_methods!(*arg); end - - def taint!(); end - - def tap!(); end - - def then!(); end - - def to_enum!(*arg); end - - def to_h!(&block); end - - def to_s!(); end - - def trust!(); end - - def untaint!(); end - - def untrust!(); end - - def yield_self!(); end - VERSION = ::T.let(nil, ::T.untyped) -end - -class OptionParser - def additional_message(typ, opt); end - - def require_exact(); end - - def require_exact=(require_exact); end - Version = ::T.let(nil, ::T.untyped) -end - -class OptionParser::List - def get_candidates(id); end -end - -class OptionParser::ParseError - def additional(); end - - def additional=(additional); end -end - -class PP - def self.width_for(out); end -end - -class Proc - def <<(arg); end - - def >>(arg); end - - def clone(); end -end - -class Process::Status - def self.wait(*arg); end -end - -class Process::Tms - def self.keyword_init?(); end -end - -module Process - def self._fork(); end -end - -module Psych - VERSION = ::T.let(nil, ::T.untyped) -end - -class Psych::Visitors::RestrictedYAMLTree - def visit_Symbol(sym); end - DEFAULT_PERMITTED_CLASSES = ::T.let(nil, ::T.untyped) -end - -class Psych::Visitors::RestrictedYAMLTree -end - -class Psych::Visitors::Visitor - def self.dispatch_cache(); end -end - -module Psych - def self.add_builtin_type(type_tag, &block); end - - def self.add_domain_type(domain, type_tag, &block); end - - def self.add_tag(tag, klass); end - - def self.config(); end - - def self.domain_types(*args, **arg, &block); end - - def self.domain_types=(*args, **arg, &block); end - - def self.dump_tags(*args, **arg, &block); end - - def self.dump_tags=(*args, **arg, &block); end - - def self.libyaml_version(); end - - def self.load_tags(*args, **arg, &block); end - - def self.load_tags=(*args, **arg, &block); end - - def self.remove_type(type_tag); end - - def self.safe_dump(o, io=T.unsafe(nil), options=T.unsafe(nil)); end - - def self.safe_load_file(filename, **kwargs); end - - def self.unsafe_load(yaml, filename: T.unsafe(nil), fallback: T.unsafe(nil), symbolize_names: T.unsafe(nil), freeze: T.unsafe(nil)); end - - def self.unsafe_load_file(filename, **kwargs); end -end - -module PublicSuffix - BANG = ::T.let(nil, ::T.untyped) - DOT = ::T.let(nil, ::T.untyped) - STAR = ::T.let(nil, ::T.untyped) - VERSION = ::T.let(nil, ::T.untyped) -end - -class PublicSuffix::List - DEFAULT_LIST_PATH = ::T.let(nil, ::T.untyped) -end - -class REXML::Light::Node - NAMESPLIT = ::T.let(nil, ::T.untyped) - PARENTS = ::T.let(nil, ::T.untyped) -end - -class REXML::Parsers::BaseParser - EXTERNAL_ID_PUBLIC = ::T.let(nil, ::T.untyped) - EXTERNAL_ID_SYSTEM = ::T.let(nil, ::T.untyped) - PUBLIC_ID = ::T.let(nil, ::T.untyped) - QNAME = ::T.let(nil, ::T.untyped) - QNAME_STR = ::T.let(nil, ::T.untyped) -end - -class REXML::Parsers::XPathParser - LOCAL_NAME_WILDCARD = ::T.let(nil, ::T.untyped) - PREFIX_WILDCARD = ::T.let(nil, ::T.untyped) -end - -class REXML::XPathParser - DEBUG = ::T.let(nil, ::T.untyped) -end - -class Ractor::ClosedError -end - -class Ractor::ClosedError -end - -class Ractor::Error -end - -class Ractor::Error -end - -class Ractor::IsolationError -end - -class Ractor::IsolationError -end - -class Ractor::MovedError -end - -class Ractor::MovedError -end - -class Ractor::MovedObject - def !(*arg); end - - def !=(*arg); end - - def ==(*arg); end - - def __id__(*arg); end - - def equal?(*arg); end -end - -class Ractor::MovedObject -end - -class Ractor::RemoteError - def ractor(); end -end - -class Ractor::RemoteError -end - -class Ractor::UnsafeError -end - -class Ractor::UnsafeError -end - -class Ractor - def self.new(*args, name: T.unsafe(nil), &block); end -end - -module Rake::DSL - include ::FileUtils::StreamUtils_ -end - -module Rake::FileUtilsExt - include ::FileUtils::StreamUtils_ - DEFAULT = ::T.let(nil, ::T.untyped) -end - -module Rake::FileUtilsExt - extend ::FileUtils::StreamUtils_ -end - -class Random::Base - include ::Random::Formatter - def bytes(arg); end - - def initialize(*arg); end - - def seed(); end -end - -class Random::Base - extend ::Random::Formatter -end - -class Random - def self.bytes(arg); end - - def self.seed(); end -end - -class Range - def %(arg); end - - def entries(); end - - def to_a(); end -end - -module RbConfig - def self.expand(val, config=T.unsafe(nil)); end - - def self.fire_update!(key, val, mkconf=T.unsafe(nil), conf=T.unsafe(nil)); end - - def self.ruby(); end -end - -class Refinement -end - -class Refinement -end - -class RubyVM::AbstractSyntaxTree::Node - def node_id(); end - - def pretty_print_children(q, names=T.unsafe(nil)); end - - def script_lines(); end - - def source(); end -end - -class RubyVM::InstructionSequence - def script_lines(); end -end - -module RubyVM::MJIT -end - -module RubyVM::MJIT - def self.enabled?(); end - - def self.pause(*arg); end - - def self.resume(); end -end - -class RubyVM - def self.keep_script_lines(); end - - def self.keep_script_lines=(keep_script_lines); end -end - -ScanError = StringScanner::Error - -class Set - def ==(other); end - - def ===(o); end - - def divide(&func); end - - def eql?(o); end - - def flatten_merge(set, seen=T.unsafe(nil)); end - - def pretty_print(pp); end - - def pretty_print_cycle(pp); end - - def reset(); end - InspectKey = ::T.let(nil, ::T.untyped) -end - -class SimpleDelegator - RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped) -end - -module Singleton - def _dump(depth=T.unsafe(nil)); end - - def clone(); end - - def dup(); end - VERSION = ::T.let(nil, ::T.untyped) -end - -module Singleton::SingletonClassMethods - def _load(str); end - - def clone(); end -end - -module Singleton - def self.__init__(klass); end -end - -class Socket - AF_CCITT = ::T.let(nil, ::T.untyped) - AF_CHAOS = ::T.let(nil, ::T.untyped) - AF_CNT = ::T.let(nil, ::T.untyped) - AF_COIP = ::T.let(nil, ::T.untyped) - AF_DATAKIT = ::T.let(nil, ::T.untyped) - AF_DECnet = ::T.let(nil, ::T.untyped) - AF_DLI = ::T.let(nil, ::T.untyped) - AF_E164 = ::T.let(nil, ::T.untyped) - AF_ECMA = ::T.let(nil, ::T.untyped) - AF_HYLINK = ::T.let(nil, ::T.untyped) - AF_IMPLINK = ::T.let(nil, ::T.untyped) - AF_ISO = ::T.let(nil, ::T.untyped) - AF_LAT = ::T.let(nil, ::T.untyped) - AF_LINK = ::T.let(nil, ::T.untyped) - AF_NATM = ::T.let(nil, ::T.untyped) - AF_NDRV = ::T.let(nil, ::T.untyped) - AF_NETBIOS = ::T.let(nil, ::T.untyped) - AF_NS = ::T.let(nil, ::T.untyped) - AF_OSI = ::T.let(nil, ::T.untyped) - AF_PPP = ::T.let(nil, ::T.untyped) - AF_PUP = ::T.let(nil, ::T.untyped) - AF_SIP = ::T.let(nil, ::T.untyped) - AF_SYSTEM = ::T.let(nil, ::T.untyped) - AF_VSOCK = ::T.let(nil, ::T.untyped) - AI_DEFAULT = ::T.let(nil, ::T.untyped) - AI_MASK = ::T.let(nil, ::T.untyped) - AI_V4MAPPED_CFG = ::T.let(nil, ::T.untyped) - EAI_BADHINTS = ::T.let(nil, ::T.untyped) - EAI_MAX = ::T.let(nil, ::T.untyped) - EAI_PROTOCOL = ::T.let(nil, ::T.untyped) - IFF_ALTPHYS = ::T.let(nil, ::T.untyped) - IFF_LINK0 = ::T.let(nil, ::T.untyped) - IFF_LINK1 = ::T.let(nil, ::T.untyped) - IFF_LINK2 = ::T.let(nil, ::T.untyped) - IFF_OACTIVE = ::T.let(nil, ::T.untyped) - IFF_SIMPLEX = ::T.let(nil, ::T.untyped) - IPPROTO_EON = ::T.let(nil, ::T.untyped) - IPPROTO_GGP = ::T.let(nil, ::T.untyped) - IPPROTO_HELLO = ::T.let(nil, ::T.untyped) - IPPROTO_MAX = ::T.let(nil, ::T.untyped) - IPPROTO_ND = ::T.let(nil, ::T.untyped) - IPPROTO_XTP = ::T.let(nil, ::T.untyped) - IPV6_DONTFRAG = ::T.let(nil, ::T.untyped) - IPV6_PATHMTU = ::T.let(nil, ::T.untyped) - IPV6_RECVPATHMTU = ::T.let(nil, ::T.untyped) - IPV6_USE_MIN_MTU = ::T.let(nil, ::T.untyped) - IP_DONTFRAG = ::T.let(nil, ::T.untyped) - IP_PORTRANGE = ::T.let(nil, ::T.untyped) - IP_RECVDSTADDR = ::T.let(nil, ::T.untyped) - IP_RECVIF = ::T.let(nil, ::T.untyped) - LOCAL_PEERCRED = ::T.let(nil, ::T.untyped) - MSG_EOF = ::T.let(nil, ::T.untyped) - MSG_FLUSH = ::T.let(nil, ::T.untyped) - MSG_HAVEMORE = ::T.let(nil, ::T.untyped) - MSG_HOLD = ::T.let(nil, ::T.untyped) - MSG_RCVMORE = ::T.let(nil, ::T.untyped) - MSG_SEND = ::T.let(nil, ::T.untyped) - PF_CCITT = ::T.let(nil, ::T.untyped) - PF_CHAOS = ::T.let(nil, ::T.untyped) - PF_CNT = ::T.let(nil, ::T.untyped) - PF_COIP = ::T.let(nil, ::T.untyped) - PF_DATAKIT = ::T.let(nil, ::T.untyped) - PF_DECnet = ::T.let(nil, ::T.untyped) - PF_DLI = ::T.let(nil, ::T.untyped) - PF_ECMA = ::T.let(nil, ::T.untyped) - PF_HYLINK = ::T.let(nil, ::T.untyped) - PF_IMPLINK = ::T.let(nil, ::T.untyped) - PF_ISO = ::T.let(nil, ::T.untyped) - PF_LAT = ::T.let(nil, ::T.untyped) - PF_LINK = ::T.let(nil, ::T.untyped) - PF_NATM = ::T.let(nil, ::T.untyped) - PF_NDRV = ::T.let(nil, ::T.untyped) - PF_NETBIOS = ::T.let(nil, ::T.untyped) - PF_NS = ::T.let(nil, ::T.untyped) - PF_OSI = ::T.let(nil, ::T.untyped) - PF_PIP = ::T.let(nil, ::T.untyped) - PF_PPP = ::T.let(nil, ::T.untyped) - PF_PUP = ::T.let(nil, ::T.untyped) - PF_RTIP = ::T.let(nil, ::T.untyped) - PF_SIP = ::T.let(nil, ::T.untyped) - PF_SYSTEM = ::T.let(nil, ::T.untyped) - PF_VSOCK = ::T.let(nil, ::T.untyped) - PF_XTP = ::T.let(nil, ::T.untyped) - SCM_CREDS = ::T.let(nil, ::T.untyped) - SO_DONTTRUNC = ::T.let(nil, ::T.untyped) - SO_NKE = ::T.let(nil, ::T.untyped) - SO_NOSIGPIPE = ::T.let(nil, ::T.untyped) - SO_NREAD = ::T.let(nil, ::T.untyped) - SO_USELOOPBACK = ::T.let(nil, ::T.untyped) - SO_WANTMORE = ::T.let(nil, ::T.untyped) - SO_WANTOOBFLAG = ::T.let(nil, ::T.untyped) - TCP_NOOPT = ::T.let(nil, ::T.untyped) - TCP_NOPUSH = ::T.let(nil, ::T.untyped) -end - -module Socket::Constants - AF_CCITT = ::T.let(nil, ::T.untyped) - AF_CHAOS = ::T.let(nil, ::T.untyped) - AF_CNT = ::T.let(nil, ::T.untyped) - AF_COIP = ::T.let(nil, ::T.untyped) - AF_DATAKIT = ::T.let(nil, ::T.untyped) - AF_DECnet = ::T.let(nil, ::T.untyped) - AF_DLI = ::T.let(nil, ::T.untyped) - AF_E164 = ::T.let(nil, ::T.untyped) - AF_ECMA = ::T.let(nil, ::T.untyped) - AF_HYLINK = ::T.let(nil, ::T.untyped) - AF_IMPLINK = ::T.let(nil, ::T.untyped) - AF_ISO = ::T.let(nil, ::T.untyped) - AF_LAT = ::T.let(nil, ::T.untyped) - AF_LINK = ::T.let(nil, ::T.untyped) - AF_NATM = ::T.let(nil, ::T.untyped) - AF_NDRV = ::T.let(nil, ::T.untyped) - AF_NETBIOS = ::T.let(nil, ::T.untyped) - AF_NS = ::T.let(nil, ::T.untyped) - AF_OSI = ::T.let(nil, ::T.untyped) - AF_PPP = ::T.let(nil, ::T.untyped) - AF_PUP = ::T.let(nil, ::T.untyped) - AF_SIP = ::T.let(nil, ::T.untyped) - AF_SYSTEM = ::T.let(nil, ::T.untyped) - AF_VSOCK = ::T.let(nil, ::T.untyped) - AI_DEFAULT = ::T.let(nil, ::T.untyped) - AI_MASK = ::T.let(nil, ::T.untyped) - AI_V4MAPPED_CFG = ::T.let(nil, ::T.untyped) - EAI_BADHINTS = ::T.let(nil, ::T.untyped) - EAI_MAX = ::T.let(nil, ::T.untyped) - EAI_PROTOCOL = ::T.let(nil, ::T.untyped) - IFF_ALTPHYS = ::T.let(nil, ::T.untyped) - IFF_LINK0 = ::T.let(nil, ::T.untyped) - IFF_LINK1 = ::T.let(nil, ::T.untyped) - IFF_LINK2 = ::T.let(nil, ::T.untyped) - IFF_OACTIVE = ::T.let(nil, ::T.untyped) - IFF_SIMPLEX = ::T.let(nil, ::T.untyped) - IPPROTO_EON = ::T.let(nil, ::T.untyped) - IPPROTO_GGP = ::T.let(nil, ::T.untyped) - IPPROTO_HELLO = ::T.let(nil, ::T.untyped) - IPPROTO_MAX = ::T.let(nil, ::T.untyped) - IPPROTO_ND = ::T.let(nil, ::T.untyped) - IPPROTO_XTP = ::T.let(nil, ::T.untyped) - IPV6_DONTFRAG = ::T.let(nil, ::T.untyped) - IPV6_PATHMTU = ::T.let(nil, ::T.untyped) - IPV6_RECVPATHMTU = ::T.let(nil, ::T.untyped) - IPV6_USE_MIN_MTU = ::T.let(nil, ::T.untyped) - IP_DONTFRAG = ::T.let(nil, ::T.untyped) - IP_PORTRANGE = ::T.let(nil, ::T.untyped) - IP_RECVDSTADDR = ::T.let(nil, ::T.untyped) - IP_RECVIF = ::T.let(nil, ::T.untyped) - LOCAL_PEERCRED = ::T.let(nil, ::T.untyped) - MSG_EOF = ::T.let(nil, ::T.untyped) - MSG_FLUSH = ::T.let(nil, ::T.untyped) - MSG_HAVEMORE = ::T.let(nil, ::T.untyped) - MSG_HOLD = ::T.let(nil, ::T.untyped) - MSG_RCVMORE = ::T.let(nil, ::T.untyped) - MSG_SEND = ::T.let(nil, ::T.untyped) - PF_CCITT = ::T.let(nil, ::T.untyped) - PF_CHAOS = ::T.let(nil, ::T.untyped) - PF_CNT = ::T.let(nil, ::T.untyped) - PF_COIP = ::T.let(nil, ::T.untyped) - PF_DATAKIT = ::T.let(nil, ::T.untyped) - PF_DECnet = ::T.let(nil, ::T.untyped) - PF_DLI = ::T.let(nil, ::T.untyped) - PF_ECMA = ::T.let(nil, ::T.untyped) - PF_HYLINK = ::T.let(nil, ::T.untyped) - PF_IMPLINK = ::T.let(nil, ::T.untyped) - PF_ISO = ::T.let(nil, ::T.untyped) - PF_LAT = ::T.let(nil, ::T.untyped) - PF_LINK = ::T.let(nil, ::T.untyped) - PF_NATM = ::T.let(nil, ::T.untyped) - PF_NDRV = ::T.let(nil, ::T.untyped) - PF_NETBIOS = ::T.let(nil, ::T.untyped) - PF_NS = ::T.let(nil, ::T.untyped) - PF_OSI = ::T.let(nil, ::T.untyped) - PF_PIP = ::T.let(nil, ::T.untyped) - PF_PPP = ::T.let(nil, ::T.untyped) - PF_PUP = ::T.let(nil, ::T.untyped) - PF_RTIP = ::T.let(nil, ::T.untyped) - PF_SIP = ::T.let(nil, ::T.untyped) - PF_SYSTEM = ::T.let(nil, ::T.untyped) - PF_VSOCK = ::T.let(nil, ::T.untyped) - PF_XTP = ::T.let(nil, ::T.untyped) - SCM_CREDS = ::T.let(nil, ::T.untyped) - SO_DONTTRUNC = ::T.let(nil, ::T.untyped) - SO_NKE = ::T.let(nil, ::T.untyped) - SO_NOSIGPIPE = ::T.let(nil, ::T.untyped) - SO_NREAD = ::T.let(nil, ::T.untyped) - SO_USELOOPBACK = ::T.let(nil, ::T.untyped) - SO_WANTMORE = ::T.let(nil, ::T.untyped) - SO_WANTOOBFLAG = ::T.let(nil, ::T.untyped) - TCP_NOOPT = ::T.let(nil, ::T.untyped) - TCP_NOPUSH = ::T.let(nil, ::T.untyped) -end - -module Spy - VERSION = ::T.let(nil, ::T.untyped) -end - -module Spy::Mock - CLASSES_NOT_TO_OVERRIDE = ::T.let(nil, ::T.untyped) - METHODS_NOT_TO_OVERRIDE = ::T.let(nil, ::T.untyped) -end - -class Spy::Subroutine - SPY_ARGS_PREFIX = ::T.let(nil, ::T.untyped) -end - -class Statsig::Network - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -module Statsig - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -class StatsigDriver - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -class StatsigOptions - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -class StatsigUser - extend ::T::Private::Methods::MethodHooks - extend ::T::Private::Methods::SingletonMethodHooks -end - -class String - include ::JSON::Ext::Generator::GeneratorMethods::String - def shellescape(); end - - def shellsplit(); end -end - -class String - extend ::JSON::Ext::Generator::GeneratorMethods::String::Extend -end - -class StringIO - def set_encoding_by_bom(); end - VERSION = ::T.let(nil, ::T.untyped) -end - -class StringIO - def self.new(*arg); end -end - -class StringScanner - def bol?(); end - - def fixed_anchor?(); end - - def initialize(*arg); end - Id = ::T.let(nil, ::T.untyped) - Version = ::T.let(nil, ::T.untyped) -end - -class Struct - def deconstruct(); end - - def deconstruct_keys(arg); end - - def filter(*arg); end -end - -Struct::Group = Etc::Group - -Struct::Passwd = Etc::Passwd - -class Struct - def self.new(*arg); end -end - -class Symbol - def name(); end -end - -class Tempfile - def _close(); end - RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped) -end - -class Tempfile::Remover - def call(*args); end - - def initialize(tmpfile); end -end - -class Tempfile::Remover -end - -class Thread - def native_thread_id(); end -end - -class Thread::Backtrace - def self.limit(); end -end - -class Thread::Queue - def initialize(*arg); end -end - -class Thread - def self.ignore_deadlock(); end - - def self.ignore_deadlock=(ignore_deadlock); end - - def self.new(*arg); end -end - -module Timeout - VERSION = ::T.let(nil, ::T.untyped) -end - -class TracePoint - def eval_script(); end - - def instruction_sequence(); end - - def parameters(); end -end - -class TracePoint - def self.allow_reentry(); end - - def self.new(*events); end -end - -class TrueClass - include ::JSON::Ext::Generator::GeneratorMethods::TrueClass -end - -module UNF - VERSION = ::T.let(nil, ::T.untyped) -end - -class UNF::Normalizer - include ::Singleton - def normalize(arg, arg1); end -end - -class UNF::Normalizer - extend ::Singleton::SingletonClassMethods - def self.normalize(string, form); end -end - -module URI - include ::URI::RFC2396_REGEXP -end - -class URI::FTP - def self.new2(user, password, host, port, path, typecode=T.unsafe(nil), arg_check=T.unsafe(nil)); end -end - -class URI::File - def check_password(user); end - - def check_user(user); end - - def check_userinfo(user); end - - def set_userinfo(v); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) -end - -class URI::HTTP - def authority(); end - - def origin(); end -end - -class URI::LDAP - def attributes(); end - - def attributes=(val); end - - def dn(); end - - def dn=(val); end - - def extensions(); end - - def extensions=(val); end - - def filter(); end - - def filter=(val); end - - def initialize(*arg); end - - def scope(); end - - def scope=(val); end - - def set_attributes(val); end - - def set_dn(val); end - - def set_extensions(val); end - - def set_filter(val); end - - def set_scope(val); end -end - -class URI::MailTo - def initialize(*arg); end -end - -class URI::RFC2396_Parser - def initialize(opts=T.unsafe(nil)); end -end - -class URI::RFC3986_Parser - def join(*uris); end - - def parse(uri); end - - def regexp(); end - - def split(uri); end - RFC3986_relative_ref = ::T.let(nil, ::T.untyped) -end - -module URI::Util - def self.make_components_hash(klass, array_hash); end -end - -class URI::WS - def request_uri(); end - COMPONENT = ::T.let(nil, ::T.untyped) - DEFAULT_PORT = ::T.let(nil, ::T.untyped) -end - -class URI::WS -end - -module URI - def self.for(scheme, *arguments, default: T.unsafe(nil)); end - - def self.get_encoding(label); end - - def self.register_scheme(scheme, klass); end -end - -class UnboundMethod - def private?(); end - - def protected?(); end - - def public?(); end -end - -module UnicodeNormalize -end - -module UnicodeNormalize -end - -module UserAgentParser - DefaultPatternsPath = ::T.let(nil, ::T.untyped) -end - -class UserAgentParser::Device - DEFAULT_FAMILY = ::T.let(nil, ::T.untyped) -end - -class UserAgentParser::OperatingSystem - DEFAULT_FAMILY = ::T.let(nil, ::T.untyped) -end - -class UserAgentParser::UserAgent - DEFAULT_FAMILY = ::T.let(nil, ::T.untyped) -end - -class UserAgentParser::Version - SEGMENTS_REGEX = ::T.let(nil, ::T.untyped) -end - -module Warning - extend ::Warning -end - -module WebMock - VERSION = ::T.let(nil, ::T.untyped) -end - -class WebMock::BodyPattern - BODY_FORMATS = ::T.let(nil, ::T.untyped) -end - -WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP = Net::HTTP - -class WebMock::Util::URI - ADDRESSABLE_URIS = ::T.let(nil, ::T.untyped) - NORMALIZED_URIS = ::T.let(nil, ::T.untyped) -end - -module WebMock::Util::URI::CharacterClasses - USERINFO = ::T.let(nil, ::T.untyped) -end - -class Zlib::Deflate - def initialize(*arg); end -end - -class Zlib::GzipReader - def initialize(*arg); end -end - -class Zlib::GzipReader - def self.zcat(*arg); end -end - -class Zlib::GzipWriter - def initialize(*arg); end -end - -class Zlib::InProgressError -end - -class Zlib::InProgressError -end - -class Zlib::Inflate - def initialize(*arg); end -end diff --git a/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi b/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi deleted file mode 100644 index 2a59e2d..0000000 --- a/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi +++ /dev/null @@ -1,108 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi sorbet-typed -# -# If you would like to make changes to this file, great! Please upstream any changes you make here: -# -# https://github.com/sorbet/sorbet-typed/edit/master/lib/minitest/all/minitest.rbi -# -# typed: strong - -module Minitest - class Runnable - end - - class Test < Runnable - include Minitest::Assertions - end - - sig { void } - def self.autorun; end - - sig { params(args: T::Array[String]).returns(T::Boolean) } - def self.run(args = []); end -end - -module Minitest::Assertions - extend T::Sig - - sig { params(test: T.untyped, msg: T.nilable(String)).returns(TrueClass) } - def assert(test, msg = nil); end - - sig do - params( - exp: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def assert_empty(exp, msg = nil); end - - sig do - params( - exp: BasicObject, - act: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def assert_equal(exp, act, msg = nil); end - - sig do - params( - collection: T::Enumerable[T.untyped], - obj: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def assert_includes(collection, obj, msg = nil); end - - sig do - params( - obj: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def assert_nil(obj, msg = nil); end - - sig do - params( - exp: T.untyped - ).returns(StandardError) - end - def assert_raises(*exp, &block); end - - sig { params(test: T.untyped, msg: T.nilable(String)).returns(TrueClass) } - def refute(test, msg = nil); end - - sig do - params( - exp: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def refute_empty(exp, msg = nil); end - - sig do - params( - exp: BasicObject, - act: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def refute_equal(exp, act, msg = nil); end - - sig do - params( - collection: T::Enumerable[T.untyped], - obj: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def refute_includes(collection, obj, msg = nil); end - - sig do - params( - obj: BasicObject, - msg: T.nilable(String) - ).returns(TrueClass) - end - def refute_nil(obj, msg = nil); end -end diff --git a/sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi b/sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi deleted file mode 100644 index 3933a68..0000000 --- a/sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi +++ /dev/null @@ -1,645 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi sorbet-typed -# -# If you would like to make changes to this file, great! Please upstream any changes you make here: -# -# https://github.com/sorbet/sorbet-typed/edit/master/lib/rake/all/rake.rbi -# -# typed: true - -module Rake - def self.add_rakelib(*files); end - def self.application; end - def self.application=(app); end - def self.each_dir_parent(dir); end - def self.from_pathname(path); end - def self.load_rakefile(path); end - def self.original_dir; end - def self.suggested_thread_count; end - def self.with_application(block_application = nil); end - extend Rake::FileUtilsExt -end -module Rake::Version -end -class Module - def rake_extension(method); end -end -class String - def ext(newext = nil); end - def pathmap(spec = nil, &block); end - def pathmap_explode; end - def pathmap_partial(n); end - def pathmap_replace(patterns, &block); end -end -module Rake::Win32 - def self.normalize(path); end - def self.win32_system_dir; end - def self.windows?; end -end -class Rake::Win32::Win32HomeError < RuntimeError -end -class Rake::LinkedList - def ==(other); end - def conj(item); end - def each; end - def empty?; end - def head; end - def initialize(head, tail = nil); end - def inspect; end - def self.cons(head, tail); end - def self.empty; end - def self.make(*args); end - def tail; end - def to_s; end - include Enumerable -end -class Rake::LinkedList::EmptyLinkedList < Rake::LinkedList - def empty?; end - def initialize; end - def self.cons(head, tail); end -end -class Rake::CpuCounter - def count; end - def count_with_default(default = nil); end - def self.count; end -end -class Rake::Scope < Rake::LinkedList - def path; end - def path_with_task_name(task_name); end - def trim(n); end -end -class Rake::Scope::EmptyScope < Rake::LinkedList::EmptyLinkedList - def path; end - def path_with_task_name(task_name); end -end -class Rake::TaskArgumentError < ArgumentError -end -class Rake::RuleRecursionOverflowError < StandardError - def add_target(target); end - def initialize(*args); end - def message; end -end -module Rake::TaskManager - def [](task_name, scopes = nil); end - def add_location(task); end - def attempt_rule(task_name, task_pattern, args, extensions, block, level); end - def clear; end - def create_rule(*args, &block); end - def current_scope; end - def define_task(task_class, *args, &block); end - def enhance_with_matching_rule(task_name, level = nil); end - def find_location; end - def generate_did_you_mean_suggestions(task_name); end - def generate_message_for_undefined_task(task_name); end - def generate_name; end - def get_description(task); end - def in_namespace(name); end - def initialize; end - def intern(task_class, task_name); end - def last_description; end - def last_description=(arg0); end - def lookup(task_name, initial_scope = nil); end - def lookup_in_scope(name, scope); end - def make_sources(task_name, task_pattern, extensions); end - def resolve_args(args); end - def resolve_args_with_dependencies(args, hash); end - def resolve_args_without_dependencies(args); end - def self.record_task_metadata; end - def self.record_task_metadata=(arg0); end - def synthesize_file_task(task_name); end - def tasks; end - def tasks_in_scope(scope); end - def trace_rule(level, message); end -end -module Rake::Cloneable - def initialize_copy(source); end -end -module FileUtils - def create_shell_runner(cmd); end - def ruby(*args, **options, &block); end - def safe_ln(*args, **options); end - def set_verbose_option(options); end - def sh(*cmd, &block); end - def sh_show_command(cmd); end - def split_all(path); end -end -module Rake::FileUtilsExt - def cd(*args, **options, &block); end - def chdir(*args, **options, &block); end - def chmod(*args, **options, &block); end - def chmod_R(*args, **options, &block); end - def chown(*args, **options, &block); end - def chown_R(*args, **options, &block); end - def copy(*args, **options, &block); end - def cp(*args, **options, &block); end - def cp_lr(*args, **options, &block); end - def cp_r(*args, **options, &block); end - def install(*args, **options, &block); end - def link(*args, **options, &block); end - def ln(*args, **options, &block); end - def ln_s(*args, **options, &block); end - def ln_sf(*args, **options, &block); end - def makedirs(*args, **options, &block); end - def mkdir(*args, **options, &block); end - def mkdir_p(*args, **options, &block); end - def mkpath(*args, **options, &block); end - def move(*args, **options, &block); end - def mv(*args, **options, &block); end - def nowrite(value = nil); end - def rake_check_options(options, *optdecl); end - def rake_output_message(message); end - def remove(*args, **options, &block); end - def rm(*args, **options, &block); end - def rm_f(*args, **options, &block); end - def rm_r(*args, **options, &block); end - def rm_rf(*args, **options, &block); end - def rmdir(*args, **options, &block); end - def rmtree(*args, **options, &block); end - def safe_unlink(*args, **options, &block); end - def self.nowrite_flag; end - def self.nowrite_flag=(arg0); end - def self.verbose_flag; end - def self.verbose_flag=(arg0); end - def symlink(*args, **options, &block); end - def touch(*args, **options, &block); end - def verbose(value = nil); end - def when_writing(msg = nil); end - extend Rake::FileUtilsExt - include FileUtils -end -class Rake::FileList - def &(*args, &block); end - def *(other); end - def +(*args, &block); end - def -(*args, &block); end - def <<(obj); end - def <=>(*args, &block); end - def ==(array); end - def [](*args, &block); end - def []=(*args, &block); end - def add(*filenames); end - def add_matching(pattern); end - def all?(*args, &block); end - def any?(*args, &block); end - def append(*args, &block); end - def assoc(*args, &block); end - def at(*args, &block); end - def bsearch(*args, &block); end - def bsearch_index(*args, &block); end - def chain(*args, &block); end - def chunk(*args, &block); end - def chunk_while(*args, &block); end - def clear(*args, &block); end - def clear_exclude; end - def collect!(*args, &block); end - def collect(*args, &block); end - def collect_concat(*args, &block); end - def combination(*args, &block); end - def compact!(*args, &block); end - def compact(*args, &block); end - def concat(*args, &block); end - def count(*args, &block); end - def cycle(*args, &block); end - def delete(*args, &block); end - def delete_at(*args, &block); end - def delete_if(*args, &block); end - def detect(*args, &block); end - def difference(*args, &block); end - def dig(*args, &block); end - def drop(*args, &block); end - def drop_while(*args, &block); end - def each(*args, &block); end - def each_cons(*args, &block); end - def each_entry(*args, &block); end - def each_index(*args, &block); end - def each_slice(*args, &block); end - def each_with_index(*args, &block); end - def each_with_object(*args, &block); end - def egrep(pattern, *options); end - def empty?(*args, &block); end - def entries(*args, &block); end - def exclude(*patterns, &block); end - def excluded_from_list?(fn); end - def existing!; end - def existing; end - def ext(newext = nil); end - def fetch(*args, &block); end - def fill(*args, &block); end - def filter!(*args, &block); end - def filter(*args, &block); end - def find(*args, &block); end - def find_all(*args, &block); end - def find_index(*args, &block); end - def first(*args, &block); end - def flat_map(*args, &block); end - def flatten!(*args, &block); end - def flatten(*args, &block); end - def grep(*args, &block); end - def grep_v(*args, &block); end - def group_by(*args, &block); end - def gsub!(pat, rep); end - def gsub(pat, rep); end - def import(array); end - def include(*filenames); end - def include?(*args, &block); end - def index(*args, &block); end - def initialize(*patterns); end - def inject(*args, &block); end - def insert(*args, &block); end - def inspect(*args, &block); end - def is_a?(klass); end - def join(*args, &block); end - def keep_if(*args, &block); end - def kind_of?(klass); end - def last(*args, &block); end - def lazy(*args, &block); end - def length(*args, &block); end - def map!(*args, &block); end - def map(*args, &block); end - def max(*args, &block); end - def max_by(*args, &block); end - def member?(*args, &block); end - def min(*args, &block); end - def min_by(*args, &block); end - def minmax(*args, &block); end - def minmax_by(*args, &block); end - def none?(*args, &block); end - def one?(*args, &block); end - def pack(*args, &block); end - def partition(&block); end - def pathmap(spec = nil, &block); end - def permutation(*args, &block); end - def pop(*args, &block); end - def prepend(*args, &block); end - def product(*args, &block); end - def push(*args, &block); end - def rassoc(*args, &block); end - def reduce(*args, &block); end - def reject!(*args, &block); end - def reject(*args, &block); end - def repeated_combination(*args, &block); end - def repeated_permutation(*args, &block); end - def replace(*args, &block); end - def resolve; end - def resolve_add(fn); end - def resolve_exclude; end - def reverse!(*args, &block); end - def reverse(*args, &block); end - def reverse_each(*args, &block); end - def rindex(*args, &block); end - def rotate!(*args, &block); end - def rotate(*args, &block); end - def sample(*args, &block); end - def select!(*args, &block); end - def select(*args, &block); end - def self.[](*args); end - def self.glob(pattern, *args); end - def shelljoin(*args, &block); end - def shift(*args, &block); end - def shuffle!(*args, &block); end - def shuffle(*args, &block); end - def size(*args, &block); end - def slice!(*args, &block); end - def slice(*args, &block); end - def slice_after(*args, &block); end - def slice_before(*args, &block); end - def slice_when(*args, &block); end - def sort!(*args, &block); end - def sort(*args, &block); end - def sort_by!(*args, &block); end - def sort_by(*args, &block); end - def sub!(pat, rep); end - def sub(pat, rep); end - def sum(*args, &block); end - def take(*args, &block); end - def take_while(*args, &block); end - def to_a; end - def to_ary; end - def to_h(*args, &block); end - def to_s; end - def to_set(*args, &block); end - def transpose(*args, &block); end - def union(*args, &block); end - def uniq!(*args, &block); end - def uniq(*args, &block); end - def unshift(*args, &block); end - def values_at(*args, &block); end - def zip(*args, &block); end - def |(*args, &block); end - include Rake::Cloneable -end -class Rake::Promise - def chore; end - def complete?; end - def discard; end - def error?; end - def initialize(args, &block); end - def recorder; end - def recorder=(arg0); end - def result?; end - def stat(*args); end - def value; end - def work; end -end -class Rake::ThreadPool - def __queue__; end - def future(*args, &block); end - def gather_history; end - def history; end - def initialize(thread_count); end - def join; end - def process_queue_item; end - def safe_thread_count; end - def start_thread; end - def stat(event, data = nil); end - def statistics; end -end -module Rake::PrivateReader - def self.included(base); end -end -module Rake::PrivateReader::ClassMethods - def private_reader(*names); end -end -class Rake::ThreadHistoryDisplay - def initialize(stats); end - def items; end - def rename(hash, key, renames); end - def show; end - def stats; end - def threads; end - extend Rake::PrivateReader::ClassMethods - include Rake::PrivateReader -end -module Rake::TraceOutput - def trace_on(out, *strings); end -end -class Rake::CommandLineOptionError < StandardError -end -class Rake::Application - def add_import(fn); end - def add_loader(ext, loader); end - def collect_command_line_tasks(args); end - def default_task_name; end - def deprecate(old_usage, new_usage, call_site); end - def display_cause_details(ex); end - def display_error_message(ex); end - def display_exception_backtrace(ex); end - def display_exception_details(ex); end - def display_exception_details_seen; end - def display_exception_message_details(ex); end - def display_prerequisites; end - def display_tasks_and_comments; end - def dynamic_width; end - def dynamic_width_stty; end - def dynamic_width_tput; end - def exit_because_of_exception(ex); end - def find_rakefile_location; end - def glob(path, &block); end - def handle_options(argv); end - def has_cause?(ex); end - def has_chain?(exception); end - def have_rakefile; end - def init(app_name = nil, argv = nil); end - def initialize; end - def invoke_task(task_string); end - def load_imports; end - def load_rakefile; end - def name; end - def options; end - def original_dir; end - def parse_task_string(string); end - def print_rakefile_directory(location); end - def rake_require(file_name, paths = nil, loaded = nil); end - def rakefile; end - def rakefile_location(backtrace = nil); end - def raw_load_rakefile; end - def run(argv = nil); end - def run_with_threads; end - def select_tasks_to_show(options, show_tasks, value); end - def select_trace_output(options, trace_option, value); end - def set_default_options; end - def sort_options(options); end - def standard_exception_handling; end - def standard_rake_options; end - def standard_system_dir; end - def system_dir; end - def terminal_columns; end - def terminal_columns=(arg0); end - def terminal_width; end - def thread_pool; end - def top_level; end - def top_level_tasks; end - def trace(*strings); end - def truncate(string, width); end - def truncate_output?; end - def tty_output=(arg0); end - def tty_output?; end - def unix?; end - def windows?; end - include Rake::TaskManager - include Rake::TraceOutput -end -class Rake::PseudoStatus - def >>(n); end - def exited?; end - def exitstatus; end - def initialize(code = nil); end - def stopped?; end - def to_i; end -end -class Rake::TaskArguments - def [](index); end - def each(&block); end - def extras; end - def fetch(*args, &block); end - def has_key?(key); end - def initialize(names, values, parent = nil); end - def inspect; end - def key?(key); end - def lookup(name); end - def method_missing(sym, *args); end - def names; end - def new_scope(names); end - def to_a; end - def to_hash; end - def to_s; end - def values_at(*keys); end - def with_defaults(defaults); end - include Enumerable -end -class Rake::InvocationChain < Rake::LinkedList - def append(invocation); end - def member?(invocation); end - def prefix; end - def self.append(invocation, chain); end - def to_s; end -end -class Rake::InvocationChain::EmptyInvocationChain < Rake::LinkedList::EmptyLinkedList - def append(invocation); end - def member?(obj); end - def to_s; end -end -module Rake::InvocationExceptionMixin - def chain; end - def chain=(value); end -end -class Rake::Task - def actions; end - def add_chain_to(exception, new_chain); end - def add_comment(comment); end - def add_description(description); end - def all_prerequisite_tasks; end - def already_invoked; end - def application; end - def application=(arg0); end - def arg_description; end - def arg_names; end - def clear; end - def clear_actions; end - def clear_args; end - def clear_comments; end - def clear_prerequisites; end - def collect_prerequisites(seen); end - def comment; end - def comment=(comment); end - def enhance(deps = nil, &block); end - def execute(args = nil); end - def first_sentence(string); end - def format_trace_flags; end - def full_comment; end - def initialize(task_name, app); end - def inspect; end - def investigation; end - def invoke(*args); end - def invoke_prerequisites(task_args, invocation_chain); end - def invoke_prerequisites_concurrently(task_args, invocation_chain); end - def invoke_with_call_chain(task_args, invocation_chain); end - def locations; end - def lookup_prerequisite(prerequisite_name); end - def name; end - def name_with_args; end - def needed?; end - def order_only_prerequisites; end - def prereqs; end - def prerequisite_tasks; end - def prerequisites; end - def reenable; end - def scope; end - def self.[](task_name); end - def self.clear; end - def self.create_rule(*args, &block); end - def self.define_task(*args, &block); end - def self.format_deps(deps); end - def self.scope_name(scope, task_name); end - def self.task_defined?(task_name); end - def self.tasks; end - def set_arg_names(args); end - def source; end - def sources; end - def sources=(arg0); end - def timestamp; end - def to_s; end - def transform_comments(separator, &block); end - def |(deps); end -end -class Rake::EarlyTime - def <=>(other); end - def self.allocate; end - def self.instance; end - def self.new(*arg0); end - def to_s; end - extend Singleton::SingletonClassMethods - include Comparable - include Singleton -end -class Rake::FileTask < Rake::Task - def needed?; end - def out_of_date?(stamp); end - def self.scope_name(scope, task_name); end - def timestamp; end -end -class Rake::FileCreationTask < Rake::FileTask - def needed?; end - def timestamp; end -end -class Rake::MultiTask < Rake::Task - def invoke_prerequisites(task_args, invocation_chain); end -end -module Rake::DSL - def cd(*args, **options, &block); end - def chdir(*args, **options, &block); end - def chmod(*args, **options, &block); end - def chmod_R(*args, **options, &block); end - def chown(*args, **options, &block); end - def chown_R(*args, **options, &block); end - def copy(*args, **options, &block); end - def cp(*args, **options, &block); end - def cp_lr(*args, **options, &block); end - def cp_r(*args, **options, &block); end - def desc(description); end - def directory(*args, &block); end - def file(*args, &block); end - def file_create(*args, &block); end - def import(*fns); end - def install(*args, **options, &block); end - def link(*args, **options, &block); end - def ln(*args, **options, &block); end - def ln_s(*args, **options, &block); end - def ln_sf(*args, **options, &block); end - def makedirs(*args, **options, &block); end - def mkdir(*args, **options, &block); end - def mkdir_p(*args, **options, &block); end - def mkpath(*args, **options, &block); end - def move(*args, **options, &block); end - def multitask(*args, &block); end - def mv(*args, **options, &block); end - def namespace(name = nil, &block); end - def nowrite(value = nil); end - def rake_check_options(options, *optdecl); end - def rake_output_message(message); end - def remove(*args, **options, &block); end - def rm(*args, **options, &block); end - def rm_f(*args, **options, &block); end - def rm_r(*args, **options, &block); end - def rm_rf(*args, **options, &block); end - def rmdir(*args, **options, &block); end - def rmtree(*args, **options, &block); end - def ruby(*args, **options, &block); end - def rule(*args, &block); end - def safe_ln(*args, **options); end - def safe_unlink(*args, **options, &block); end - def sh(*cmd, &block); end - def split_all(path); end - def symlink(*args, **options, &block); end - def task(*args, &block); end - def touch(*args, **options, &block); end - def verbose(value = nil); end - def when_writing(msg = nil); end - include Rake::FileUtilsExt -end -class Rake::DefaultLoader - def load(fn); end -end -class Rake::LateTime - def <=>(other); end - def self.allocate; end - def self.instance; end - def self.new(*arg0); end - def to_s; end - extend Singleton::SingletonClassMethods - include Comparable - include Singleton -end -class Rake::NameSpace - def [](name); end - def initialize(task_manager, scope_list); end - def scope; end - def tasks; end -end -module Rake::Backtrace - def self.collapse(backtrace); end -end -class Rake::TaskLib - include Rake::Cloneable - include Rake::DSL -end diff --git a/sorbet/rbi/sorbet-typed/lib/thor/all/thor.rbi b/sorbet/rbi/sorbet-typed/lib/thor/all/thor.rbi deleted file mode 100644 index d5789d8..0000000 --- a/sorbet/rbi/sorbet-typed/lib/thor/all/thor.rbi +++ /dev/null @@ -1,905 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi sorbet-typed -# -# If you would like to make changes to this file, great! Please upstream any changes you make here: -# -# https://github.com/sorbet/sorbet-typed/edit/master/lib/thor/all/thor.rbi -# -# typed: strong - -class Thor - include(::Thor::Base) - include(::Thor::Invocation) - include(::Thor::Shell) - extend(::Thor::Base::ClassMethods) - extend(::Thor::Invocation::ClassMethods) - - def help(command = T.unsafe(nil), subcommand = T.unsafe(nil)); end - - class << self - def check_unknown_options!(options = T.unsafe(nil)); end - def check_unknown_options?(config); end - def command_help(shell, command_name); end - def default_command(meth = T.unsafe(nil)); end - def default_task(meth = T.unsafe(nil)); end - def deprecation_warning(message); end - def desc(usage, description, options = T.unsafe(nil)); end - def disable_required_check!(*command_names); end - def disable_required_check?(command); end - def help(shell, subcommand = T.unsafe(nil)); end - def long_desc(long_description, options = T.unsafe(nil)); end - def map(mappings = T.unsafe(nil), **kw); end - def method_option(name, options = T.unsafe(nil)); end - def method_options(options = T.unsafe(nil)); end - def option(name, options = T.unsafe(nil)); end - def options(options = T.unsafe(nil)); end - def package_name(name, _ = T.unsafe(nil)); end - def printable_commands(all = T.unsafe(nil), subcommand = T.unsafe(nil)); end - def printable_tasks(all = T.unsafe(nil), subcommand = T.unsafe(nil)); end - def register(klass, subcommand_name, usage, description, options = T.unsafe(nil)); end - def stop_on_unknown_option!(*command_names); end - def stop_on_unknown_option?(command); end - def subcommand(subcommand, subcommand_class); end - def subcommand_classes; end - def subcommands; end - def subtask(subcommand, subcommand_class); end - def subtasks; end - def task_help(shell, command_name); end - - protected - - def banner(command, namespace = T.unsafe(nil), subcommand = T.unsafe(nil)); end - def baseclass; end - def create_command(meth); end - def create_task(meth); end - def disable_required_check; end - def dispatch(meth, given_args, given_opts, config); end - def dynamic_command_class; end - def find_command_possibilities(meth); end - def find_task_possibilities(meth); end - def initialize_added; end - def normalize_command_name(meth); end - def normalize_task_name(meth); end - def retrieve_command_name(args); end - def retrieve_task_name(args); end - def stop_on_unknown_option; end - def subcommand_help(cmd); end - def subtask_help(cmd); end - end -end - -module Thor::Actions - mixes_in_class_methods(::Thor::Actions::ClassMethods) - - def initialize(args = T.unsafe(nil), options = T.unsafe(nil), config = T.unsafe(nil)); end - - def action(instance); end - def add_file(destination, *args, &block); end - def add_link(destination, *args); end - def append_file(path, *args, &block); end - def append_to_file(path, *args, &block); end - def apply(path, config = T.unsafe(nil)); end - def behavior; end - def behavior=(_arg0); end - def chmod(path, mode, config = T.unsafe(nil)); end - def comment_lines(path, flag, *args); end - def copy_file(source, *args, &block); end - def create_file(destination, *args, &block); end - def create_link(destination, *args); end - def destination_root; end - def destination_root=(root); end - def directory(source, *args, &block); end - def empty_directory(destination, config = T.unsafe(nil)); end - def find_in_source_paths(file); end - def get(source, *args, &block); end - def gsub_file(path, flag, *args, &block); end - def in_root; end - def inject_into_class(path, klass, *args, &block); end - def inject_into_file(destination, *args, &block); end - def inject_into_module(path, module_name, *args, &block); end - def insert_into_file(destination, *args, &block); end - def inside(dir = T.unsafe(nil), config = T.unsafe(nil), &block); end - def link_file(source, *args); end - def prepend_file(path, *args, &block); end - def prepend_to_file(path, *args, &block); end - def relative_to_original_destination_root(path, remove_dot = T.unsafe(nil)); end - def remove_dir(path, config = T.unsafe(nil)); end - def remove_file(path, config = T.unsafe(nil)); end - def run(command, config = T.unsafe(nil)); end - def run_ruby_script(command, config = T.unsafe(nil)); end - def source_paths; end - def template(source, *args, &block); end - def thor(command, *args); end - def uncomment_lines(path, flag, *args); end - - protected - - def _cleanup_options_and_set(options, key); end - def _shared_configuration; end - - private - - def capture(*args); end - def concat(string); end - def output_buffer; end - def output_buffer=(_arg0); end - def with_output_buffer(buf = T.unsafe(nil)); end - - class << self - def included(base); end - end -end - -class Thor::Actions::CapturableERB < ::ERB - def set_eoutvar(compiler, eoutvar = T.unsafe(nil)); end -end - -module Thor::Actions::ClassMethods - def add_runtime_options!; end - def source_paths; end - def source_paths_for_search; end - def source_root(path = T.unsafe(nil)); end -end - -class Thor::Actions::CreateFile < ::Thor::Actions::EmptyDirectory - def initialize(base, destination, data, config = T.unsafe(nil)); end - - def data; end - def identical?; end - def invoke!; end - def render; end - - protected - - def force_on_collision?; end - def force_or_skip_or_conflict(force, skip, &block); end - def on_conflict_behavior(&block); end -end - -class Thor::Actions::CreateLink < ::Thor::Actions::CreateFile - def data; end - def exists?; end - def identical?; end - def invoke!; end -end - -class Thor::Actions::Directory < ::Thor::Actions::EmptyDirectory - def initialize(base, source, destination = T.unsafe(nil), config = T.unsafe(nil), &block); end - - def invoke!; end - def revoke!; end - def source; end - - protected - - def execute!; end - def file_level_lookup(previous_lookup); end - def files(lookup); end -end - -class Thor::Actions::EmptyDirectory - def initialize(base, destination, config = T.unsafe(nil)); end - - def base; end - def config; end - def destination; end - def exists?; end - def given_destination; end - def invoke!; end - def relative_destination; end - def revoke!; end - - protected - - def convert_encoded_instructions(filename); end - def destination=(destination); end - def invoke_with_conflict_check(&block); end - def on_conflict_behavior; end - def on_file_clash_behavior; end - def pretend?; end - def say_status(status, color); end -end - -class Thor::Actions::InjectIntoFile < ::Thor::Actions::EmptyDirectory - def initialize(base, destination, data, config); end - - def behavior; end - def flag; end - def invoke!; end - def replacement; end - def revoke!; end - - protected - - def replace!(regexp, string, force); end - def say_status(behavior, warning: T.unsafe(nil), color: T.unsafe(nil)); end -end - -Thor::Actions::WARNINGS = T.let(T.unsafe(nil), T::Hash[T.untyped, T.untyped]) - -class Thor::AmbiguousCommandError < ::Thor::Error -end - -Thor::AmbiguousTaskError = Thor::AmbiguousCommandError - -class Thor::Argument - def initialize(name, options = T.unsafe(nil)); end - - def banner; end - def default; end - def description; end - def enum; end - def human_name; end - def name; end - def required; end - def required?; end - def show_default?; end - def type; end - def usage; end - - protected - - def default_banner; end - def valid_type?(type); end - def validate!; end -end - -Thor::Argument::VALID_TYPES = T.let(T.unsafe(nil), T::Array[T.untyped]) - -class Thor::Arguments - def initialize(arguments = T.unsafe(nil)); end - - def parse(args); end - def remaining; end - - private - - def check_requirement!; end - def current_is_value?; end - def last?; end - def no_or_skip?(arg); end - def parse_array(name); end - def parse_hash(name); end - def parse_numeric(name); end - def parse_string(name); end - def peek; end - def shift; end - def unshift(arg); end - - class << self - def parse(*args); end - def split(args); end - end -end - -Thor::Arguments::NUMERIC = T.let(T.unsafe(nil), Regexp) - -module Thor::Base - include(::Thor::Invocation) - include(::Thor::Shell) - - mixes_in_class_methods(::Thor::Base::ClassMethods) - - def initialize(args = T.unsafe(nil), local_options = T.unsafe(nil), config = T.unsafe(nil)); end - - def args; end - def args=(_arg0); end - def options; end - def options=(_arg0); end - def parent_options; end - def parent_options=(_arg0); end - - class << self - def included(base); end - def register_klass_file(klass); end - def shell; end - def shell=(_arg0); end - def subclass_files; end - def subclasses; end - end -end - -module Thor::Base::ClassMethods - def all_commands; end - def all_tasks; end - def allow_incompatible_default_type!; end - def argument(name, options = T.unsafe(nil)); end - def arguments; end - def attr_accessor(*_arg0); end - def attr_reader(*_arg0); end - def attr_writer(*_arg0); end - def check_default_type; end - def check_default_type!; end - def check_unknown_options; end - def check_unknown_options!; end - def check_unknown_options?(config); end - def class_option(name, options = T.unsafe(nil)); end - def class_options(options = T.unsafe(nil)); end - def commands; end - def disable_required_check?(command_name); end - def exit_on_failure?; end - def group(name = T.unsafe(nil)); end - def handle_argument_error(command, error, args, arity); end - def handle_no_command_error(command, has_namespace = T.unsafe(nil)); end - def handle_no_task_error(command, has_namespace = T.unsafe(nil)); end - def namespace(name = T.unsafe(nil)); end - def no_commands(&block); end - def no_commands?; end - def no_commands_context; end - def no_tasks(&block); end - def public_command(*names); end - def public_task(*names); end - def remove_argument(*names); end - def remove_class_option(*names); end - def remove_command(*names); end - def remove_task(*names); end - def start(given_args = T.unsafe(nil), config = T.unsafe(nil)); end - def stop_on_unknown_option?(command_name); end - def strict_args_position; end - def strict_args_position!; end - def strict_args_position?(config); end - def tasks; end - - protected - - def baseclass; end - def basename; end - def build_option(name, options, scope); end - def build_options(options, scope); end - def class_options_help(shell, groups = T.unsafe(nil)); end - def create_command(meth); end - def create_task(meth); end - def dispatch(command, given_args, given_opts, config); end - def find_and_refresh_command(name); end - def find_and_refresh_task(name); end - def from_superclass(method, default = T.unsafe(nil)); end - def inherited(klass); end - def initialize_added; end - def is_thor_reserved_word?(word, type); end - def method_added(meth); end - def print_options(shell, options, group_name = T.unsafe(nil)); end -end - -class Thor::Command < ::Struct - Elem = type_member {{fixed: T.untyped}} - - def initialize(name, description, long_description, usage, options = T.unsafe(nil)); end - - def formatted_usage(klass, namespace = T.unsafe(nil), subcommand = T.unsafe(nil)); end - def hidden?; end - def run(instance, args = T.unsafe(nil)); end - - protected - - def handle_argument_error?(instance, error, caller); end - def handle_no_method_error?(instance, error, caller); end - def local_method?(instance, name); end - def not_debugging?(instance); end - def private_method?(instance); end - def public_method?(instance); end - def required_arguments_for(klass, usage); end - def required_options; end - def sans_backtrace(backtrace, caller); end - - private - - def initialize_copy(other); end -end - -Thor::Command::FILE_REGEXP = T.let(T.unsafe(nil), Regexp) - -module Thor::CoreExt -end - -class Thor::CoreExt::HashWithIndifferentAccess < ::Hash - K = type_member {{fixed: T.untyped}} - V = type_member {{fixed: T.untyped}} - Elem = type_member {{fixed: T.untyped}} - - def initialize(hash = T.unsafe(nil)); end - - def [](key); end - def []=(key, value); end - def delete(key); end - def fetch(key, *args); end - def key?(key); end - def merge(other); end - def merge!(other); end - def replace(other_hash); end - def reverse_merge(other); end - def reverse_merge!(other_hash); end - def to_hash; end - def values_at(*indices); end - - protected - - def convert_key(key); end - def method_missing(method, *args); end -end - -Thor::Correctable = DidYouMean::Correctable - -class Thor::DynamicCommand < ::Thor::Command - Elem = type_member {{fixed: T.untyped}} - - def initialize(name, options = T.unsafe(nil)); end - - def run(instance, args = T.unsafe(nil)); end -end - -Thor::DynamicTask = Thor::DynamicCommand - -class Thor::Error < ::StandardError -end - -class Thor::Group - include(::Thor::Base) - include(::Thor::Invocation) - include(::Thor::Shell) - extend(::Thor::Base::ClassMethods) - extend(::Thor::Invocation::ClassMethods) - - - protected - - def _invoke_for_class_method(klass, command = T.unsafe(nil), *args, &block); end - - class << self - def class_options_help(shell, groups = T.unsafe(nil)); end - def desc(description = T.unsafe(nil)); end - def get_options_from_invocations(group_options, base_options); end - def handle_argument_error(command, error, _args, arity); end - def help(shell); end - def invocation_blocks; end - def invocations; end - def invoke(*names, &block); end - def invoke_from_option(*names, &block); end - def printable_commands(*_arg0); end - def printable_tasks(*_arg0); end - def remove_invocation(*names); end - - protected - - def banner; end - def baseclass; end - def create_command(meth); end - def create_task(meth); end - def dispatch(command, given_args, given_opts, config); end - def self_command; end - def self_task; end - end -end - -Thor::HELP_MAPPINGS = T.let(T.unsafe(nil), T::Array[T.untyped]) - -class Thor::HiddenCommand < ::Thor::Command - Elem = type_member {{fixed: T.untyped}} - - def hidden?; end -end - -Thor::HiddenTask = Thor::HiddenCommand - -module Thor::Invocation - mixes_in_class_methods(::Thor::Invocation::ClassMethods) - - def initialize(args = T.unsafe(nil), options = T.unsafe(nil), config = T.unsafe(nil), &block); end - - def current_command_chain; end - def invoke(name = T.unsafe(nil), *args); end - def invoke_all; end - def invoke_command(command, *args); end - def invoke_task(command, *args); end - def invoke_with_padding(*args); end - - protected - - def _parse_initialization_options(args, opts, config); end - def _retrieve_class_and_command(name, sent_command = T.unsafe(nil)); end - def _retrieve_class_and_task(name, sent_command = T.unsafe(nil)); end - def _shared_configuration; end - - class << self - def included(base); end - end -end - -module Thor::Invocation::ClassMethods - def prepare_for_invocation(key, name); end -end - -class Thor::InvocationError < ::Thor::Error -end - -module Thor::LineEditor - class << self - def best_available; end - def readline(prompt, options = T.unsafe(nil)); end - end -end - -class Thor::LineEditor::Basic - def initialize(prompt, options); end - - def options; end - def prompt; end - def readline; end - - private - - def echo?; end - def get_input; end - - class << self - def available?; end - end -end - -class Thor::LineEditor::Readline < ::Thor::LineEditor::Basic - def readline; end - - private - - def add_to_history?; end - def completion_options; end - def completion_proc; end - def use_path_completion?; end - - class << self - def available?; end - end -end - -class Thor::LineEditor::Readline::PathCompletion - def initialize(text); end - - def matches; end - - private - - def absolute_matches; end - def base_path; end - def glob_pattern; end - def relative_matches; end - def text; end -end - -class Thor::MalformattedArgumentError < ::Thor::InvocationError -end - -class Thor::NestedContext - def initialize; end - - def enter; end - def entered?; end - - private - - def pop; end - def push; end -end - -class Thor::NoKwargSpellChecker < ::DidYouMean::SpellChecker - def initialize(dictionary); end -end - -class Thor::Option < ::Thor::Argument - def initialize(name, options = T.unsafe(nil)); end - - def aliases; end - def array?; end - def boolean?; end - def group; end - def hash?; end - def hide; end - def human_name; end - def lazy_default; end - def numeric?; end - def repeatable; end - def string?; end - def switch_name; end - def usage(padding = T.unsafe(nil)); end - - protected - - def dasherize(str); end - def dasherized?; end - def undasherize(str); end - def validate!; end - def validate_default_type!; end - - class << self - def parse(key, value); end - end -end - -Thor::Option::VALID_TYPES = T.let(T.unsafe(nil), T::Array[T.untyped]) - -class Thor::Options < ::Thor::Arguments - def initialize(hash_options = T.unsafe(nil), defaults = T.unsafe(nil), stop_on_unknown = T.unsafe(nil), disable_required_check = T.unsafe(nil)); end - - def check_unknown!; end - def parse(args); end - def peek; end - def remaining; end - - protected - - def assign_result!(option, result); end - def current_is_switch?; end - def current_is_switch_formatted?; end - def current_is_value?; end - def normalize_switch(arg); end - def parse_boolean(switch); end - def parse_peek(switch, option); end - def parsing_options?; end - def switch?(arg); end - def switch_option(arg); end - - class << self - def to_switches(options); end - end -end - -Thor::Options::EQ_RE = T.let(T.unsafe(nil), Regexp) - -Thor::Options::LONG_RE = T.let(T.unsafe(nil), Regexp) - -Thor::Options::OPTS_END = T.let(T.unsafe(nil), String) - -Thor::Options::SHORT_NUM = T.let(T.unsafe(nil), Regexp) - -Thor::Options::SHORT_RE = T.let(T.unsafe(nil), Regexp) - -Thor::Options::SHORT_SQ_RE = T.let(T.unsafe(nil), Regexp) - -module Thor::RakeCompat - include(::FileUtils::StreamUtils_) - include(::FileUtils) - # include(::Rake::FileUtilsExt) - # include(::Rake::DSL) - - class << self - def included(base); end - def rake_classes; end - end -end - -class Thor::RequiredArgumentMissingError < ::Thor::InvocationError -end - -module Thor::Sandbox -end - -module Thor::Shell - def initialize(args = T.unsafe(nil), options = T.unsafe(nil), config = T.unsafe(nil)); end - - def ask(*args, &block); end - def error(*args, &block); end - def file_collision(*args, &block); end - def no?(*args, &block); end - def print_in_columns(*args, &block); end - def print_table(*args, &block); end - def print_wrapped(*args, &block); end - def say(*args, &block); end - def say_status(*args, &block); end - def set_color(*args, &block); end - def shell; end - def shell=(_arg0); end - def terminal_width(*args, &block); end - def with_padding; end - def yes?(*args, &block); end - - protected - - def _shared_configuration; end -end - -class Thor::Shell::Basic - def initialize; end - - def ask(statement, *args); end - def base; end - def base=(_arg0); end - def error(statement); end - def file_collision(destination); end - def indent(count = T.unsafe(nil)); end - def mute; end - def mute?; end - def no?(statement, color = T.unsafe(nil)); end - def padding; end - def padding=(value); end - def print_in_columns(array); end - def print_table(array, options = T.unsafe(nil)); end - def print_wrapped(message, options = T.unsafe(nil)); end - def say(message = T.unsafe(nil), color = T.unsafe(nil), force_new_line = T.unsafe(nil)); end - def say_status(status, message, log_status = T.unsafe(nil)); end - def set_color(string, *_arg1); end - def terminal_width; end - def yes?(statement, color = T.unsafe(nil)); end - - protected - - def answer_match(possibilities, answer, case_insensitive); end - def as_unicode; end - def ask_filtered(statement, color, options); end - def ask_simply(statement, color, options); end - def can_display_colors?; end - def dynamic_width; end - def dynamic_width_stty; end - def dynamic_width_tput; end - def file_collision_help; end - def git_merge_tool; end - def is?(value); end - def lookup_color(color); end - def merge(destination, content); end - def merge_tool; end - def prepare_message(message, *color); end - def quiet?; end - def show_diff(destination, content); end - def stderr; end - def stdout; end - def truncate(string, width); end - def unix?; end -end - -Thor::Shell::Basic::DEFAULT_TERMINAL_WIDTH = T.let(T.unsafe(nil), Integer) - -class Thor::Shell::Color < ::Thor::Shell::Basic - def set_color(string, *colors); end - - protected - - def are_colors_disabled?; end - def can_display_colors?; end - def diff_lcs_loaded?; end - def output_diff_line(diff); end - def show_diff(destination, content); end -end - -Thor::Shell::Color::BLACK = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::BLUE = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::BOLD = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::CLEAR = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::CYAN = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::GREEN = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::MAGENTA = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_BLACK = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_BLUE = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_CYAN = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_GREEN = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_MAGENTA = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_RED = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_WHITE = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::ON_YELLOW = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::RED = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::WHITE = T.let(T.unsafe(nil), String) - -Thor::Shell::Color::YELLOW = T.let(T.unsafe(nil), String) - -class Thor::Shell::HTML < ::Thor::Shell::Basic - def ask(statement, color = T.unsafe(nil)); end - def set_color(string, *colors); end - - protected - - def can_display_colors?; end - def diff_lcs_loaded?; end - def output_diff_line(diff); end - def show_diff(destination, content); end -end - -Thor::Shell::HTML::BLACK = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::BLUE = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::BOLD = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::CYAN = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::GREEN = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::MAGENTA = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_BLACK = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_BLUE = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_CYAN = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_GREEN = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_MAGENTA = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_RED = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_WHITE = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::ON_YELLOW = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::RED = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::WHITE = T.let(T.unsafe(nil), String) - -Thor::Shell::HTML::YELLOW = T.let(T.unsafe(nil), String) - -Thor::Shell::SHELL_DELEGATED_METHODS = T.let(T.unsafe(nil), T::Array[T.untyped]) - -Thor::TEMPLATE_EXTNAME = T.let(T.unsafe(nil), String) - -Thor::THOR_RESERVED_WORDS = T.let(T.unsafe(nil), T::Array[T.untyped]) - -Thor::Task = Thor::Command - -class Thor::UndefinedCommandError < ::Thor::Error - include(::DidYouMean::Correctable) - - def initialize(command, all_commands, namespace); end - - def all_commands; end - def command; end -end - -class Thor::UndefinedCommandError::SpellChecker - def initialize(error); end - - def corrections; end - def error; end - def spell_checker; end -end - -Thor::UndefinedTaskError = Thor::UndefinedCommandError - -class Thor::UnknownArgumentError < ::Thor::Error - include(::DidYouMean::Correctable) - - def initialize(switches, unknown); end - - def switches; end - def unknown; end -end - -class Thor::UnknownArgumentError::SpellChecker - def initialize(error); end - - def corrections; end - def error; end - def spell_checker; end -end - -module Thor::Util - class << self - def camel_case(str); end - def escape_globs(path); end - def escape_html(string); end - def find_by_namespace(namespace); end - def find_class_and_command_by_namespace(namespace, fallback = T.unsafe(nil)); end - def find_class_and_task_by_namespace(namespace, fallback = T.unsafe(nil)); end - def globs_for(path); end - def load_thorfile(path, content = T.unsafe(nil), debug = T.unsafe(nil)); end - def namespace_from_thor_class(constant); end - def namespaces_in_content(contents, file = T.unsafe(nil)); end - def ruby_command; end - def snake_case(str); end - def thor_classes_in(klass); end - def thor_root; end - def thor_root_glob; end - def user_home; end - end -end diff --git a/sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi b/sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi deleted file mode 100644 index d5624a2..0000000 --- a/sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi +++ /dev/null @@ -1,35 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi sorbet-typed -# -# If you would like to make changes to this file, great! Please upstream any changes you make here: -# -# https://github.com/sorbet/sorbet-typed/edit/master/lib/yard/all/yard.rbi -# -# typed: strict - -sig { returns(YARD::Logger) } -def log; end - -class YARD::CodeObjects::Base - def initialize(namespace, name, *arg2); end -end -class YARD::CodeObjects::NamespaceObject < YARD::CodeObjects::Base - def mixins(*scopes); end -end -class YARD::CodeObjects::ClassObject < YARD::CodeObjects::NamespaceObject -end -class YARD::CodeObjects::ConstantObject < YARD::CodeObjects::Base -end -class YARD::CodeObjects::Proxy - def initialize(namespace, name, type = nil); end -end -class YARD::Handlers::Base - def handlers; end - def self.handlers; end -end -class YARD::Handlers::Ruby::Base < YARD::Handlers::Base -end -class YARD::Handlers::Ruby::AttributeHandler < YARD::Handlers::Ruby::Base -end -class YARD::Handlers::Ruby::MethodHandler < YARD::Handlers::Ruby::Base -end diff --git a/sorbet/rbi/todo.rbi b/sorbet/rbi/todo.rbi deleted file mode 100644 index fd3aec2..0000000 --- a/sorbet/rbi/todo.rbi +++ /dev/null @@ -1,8 +0,0 @@ -# This file is autogenerated. Do not edit it by hand. Regenerate it with: -# srb rbi todo - -# typed: strong -module Gem::Ext::BuildError; end -module T::Private::Methods::MethodHooks; end -module T::Private::Methods::SingletonMethodHooks; end -module YARD::Logger; end diff --git a/sorbet/tapioca/config.yml b/sorbet/tapioca/config.yml deleted file mode 100644 index 886ae58..0000000 --- a/sorbet/tapioca/config.yml +++ /dev/null @@ -1,13 +0,0 @@ -gem: - # Add your `gem` command parameters here: - # - # exclude: - # - gem_name - # doc: true - # workers: 5 -dsl: - # Add your `dsl` command parameters here: - # - # exclude: - # - SomeGeneratorName - # workers: 5 diff --git a/sorbet/tapioca/require.rb b/sorbet/tapioca/require.rb deleted file mode 100644 index 9a1b5f7..0000000 --- a/sorbet/tapioca/require.rb +++ /dev/null @@ -1,4 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -# Add your extra requires here (`bin/tapioca require` can be used to boostrap this list) diff --git a/test/data_adapter_test.rb b/test/data_adapter_test.rb index 3039354..df67dc1 100644 --- a/test/data_adapter_test.rb +++ b/test/data_adapter_test.rb @@ -1,4 +1,4 @@ -# typed: false + require_relative 'test_helper' require_relative './dummy_data_adapter' diff --git a/test/dummy_data_adapter.rb b/test/dummy_data_adapter.rb index 95c29b4..6cd63f1 100644 --- a/test/dummy_data_adapter.rb +++ b/test/dummy_data_adapter.rb @@ -1,4 +1,4 @@ -# typed: true + require 'interfaces/data_store' diff --git a/test/dynamic_config_test.rb b/test/dynamic_config_test.rb index 93f79ab..8cdd01c 100644 --- a/test/dynamic_config_test.rb +++ b/test/dynamic_config_test.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/evaluation_details_test.rb b/test/evaluation_details_test.rb index 1982bb4..e49696f 100644 --- a/test/evaluation_details_test.rb +++ b/test/evaluation_details_test.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/layer_exposure_test.rb b/test/layer_exposure_test.rb index 2292432..e8c55d6 100644 --- a/test/layer_exposure_test.rb +++ b/test/layer_exposure_test.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'json' diff --git a/test/layer_test.rb b/test/layer_test.rb index 4ad1286..f61ab00 100644 --- a/test/layer_test.rb +++ b/test/layer_test.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/local_overrides_test.rb b/test/local_overrides_test.rb index 6ee0db5..1acd891 100644 --- a/test/local_overrides_test.rb +++ b/test/local_overrides_test.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/manual_exposure_test.rb b/test/manual_exposure_test.rb index abaecf3..4c5ed80 100644 --- a/test/manual_exposure_test.rb +++ b/test/manual_exposure_test.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'json' diff --git a/test/mock_server.rb b/test/mock_server.rb index d32d93b..c3193b0 100644 --- a/test/mock_server.rb +++ b/test/mock_server.rb @@ -1,4 +1,4 @@ -# typed: ignore + require 'sinatra/base' MIN_DCS_REQUEST_TIME = 3 diff --git a/test/sorbet_test.rb b/test/sorbet_test.rb deleted file mode 100644 index 3672970..0000000 --- a/test/sorbet_test.rb +++ /dev/null @@ -1,174 +0,0 @@ -#typed: ignore - -require_relative 'test_helper' -require 'minitest' -require 'minitest/autorun' -require 'webmock/minitest' -require 'sorbet-runtime' - -require 'statsig' - -class BadClass - extend T::Sig - - sig { returns(String) } - - def bad_sig_builder_method - # Bad because it does not return a string - end - - sig { override.params(x: Integer).void } - - def bad_sig_validation_method(x) - # Bad because it is marked as override, but has no parent class - end - - sig { override.params(x: Integer).void } - - def bad_sig_validation_method_two(x) - # Bad because it is marked as override, but has no parent class - end - - sig { override.params(x: Integer).void } - - def bad_sig_validation_method_three(x) - # Bad because it is marked as override, but has no parent class - end -end - -# All these tests would throw if not for the requiring of -# statsig which has custom handlers for each of these -class SorbetTest < BaseTest - suite :SorbetTest - - def setup - reset_for_test - end - - def teardown - reset_for_test - end - - # Test inline_type_error_handler - - def test_inline_type_error_handler_throws_when_statsig_is_not_initialized - assert_raises TypeError do - T.assert_type!(1, String) - end - end - - def test_inline_type_error_handler_throws_when_logging_is_disabled - opts = StatsigOptions::new(local_mode: true, disable_sorbet_logging_handlers: true) - Statsig.initialize("secret-key", opts) - - assert_raises TypeError do - T.assert_type!(1, String) - end - end - - def test_inline_type_error_handler_logs_to_console - Statsig.initialize("secret-key", StatsigOptions::new(local_mode: true)) - - assert_output(/T.assert_type!: Expected type String, got type Integer with value 1/) do - T.assert_type!(1, String) - end - end - - # Test call_validation_error_handler - - def test_call_validation_error_handler_throws_when_statsig_is_not_initialized - assert_raises TypeError do - Statsig.initialize('secret-key', StatsigOptions.new(local_mode: true), 1) - end - end - - def test_call_validation_error_handler_throws_when_logging_is_disabled - opts = StatsigOptions::new(local_mode: true, disable_sorbet_logging_handlers: true) - Statsig.initialize("secret-key", opts) - - assert_raises TypeError do - Statsig.initialize('secret-key', StatsigOptions.new(local_mode: true), 1) - end - end - - def test_call_validation_error_handler_logs_to_console - Statsig.initialize("secret-key", StatsigOptions::new(local_mode: true)) - - assert_output(/Parameter 'error_callback': Expected type T.nilable\(T.any\(Method, Proc\)\), got type Integer with value 1/) do - Statsig.initialize('secret-key', StatsigOptions.new(local_mode: true), 1) - end - end - - # Test sig_builder_error_handler - - def test_sig_builder_error_handler_throws_when_statsig_is_not_initialized - assert_raises TypeError do - BadClass.new.bad_sig_builder_method - end - end - - def test_sig_builder_error_handler_throws_when_logging_is_disabled - opts = StatsigOptions::new(local_mode: true, disable_sorbet_logging_handlers: true) - Statsig.initialize("secret-key", opts) - - assert_raises TypeError do - BadClass.new.bad_sig_builder_method - end - end - - def test_sig_builder_error_handler_logs_to_console - Statsig.initialize("secret-key", StatsigOptions::new(local_mode: true)) - - assert_output(/Return value: Expected type String, got type NilClass/) do - BadClass.new.bad_sig_builder_method - end - end - - # Test sig_validation_error_handler - - def test_sig_validation_error_handler_throws_when_statsig_is_not_initialized - called = false - begin - BadClass.new.bad_sig_validation_method(1) - rescue - called = true - end - - assert_equal(true, called) - end - - def test_sig_validation_error_handler_throws_when_logging_is_disabled - opts = StatsigOptions::new(local_mode: true, disable_sorbet_logging_handlers: true) - Statsig.initialize("secret-key", opts) - - called = false - begin - BadClass.new.bad_sig_validation_method_two(1) - rescue - called = true - end - - assert_equal(true, called) - - end - - def test_sig_validation_error_handler_logs_to_console - Statsig.initialize("secret-key", StatsigOptions::new(local_mode: true)) - - assert_output(/You marked `bad_sig_validation_method_three` as .override, but that method doesn't already exist in this class/) do - BadClass.new.bad_sig_validation_method_three(1) - end - end - - private - - def reset_for_test - Statsig.shutdown - - T::Configuration.call_validation_error_handler = nil - T::Configuration.inline_type_error_handler = nil - T::Configuration.sig_builder_error_handler = nil - T::Configuration.sig_validation_error_handler = nil - end - -end \ No newline at end of file diff --git a/test/statsig_e2e_test.rb b/test/statsig_e2e_test.rb index 3c336d0..df33b9f 100644 --- a/test/statsig_e2e_test.rb +++ b/test/statsig_e2e_test.rb @@ -1,4 +1,4 @@ -# typed: false + require_relative 'test_helper' require 'json' diff --git a/test/test_concurrency.rb b/test/test_concurrency.rb index c897948..6575016 100644 --- a/test/test_concurrency.rb +++ b/test/test_concurrency.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'json' diff --git a/test/test_country_lookup.rb b/test/test_country_lookup.rb index e2abe74..dc4c741 100644 --- a/test/test_country_lookup.rb +++ b/test/test_country_lookup.rb @@ -1,4 +1,4 @@ -# typed: false + require_relative 'test_helper' require 'minitest' diff --git a/test/test_diagnostics.rb b/test/test_diagnostics.rb index 0940191..2fdc855 100644 --- a/test/test_diagnostics.rb +++ b/test/test_diagnostics.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/test_eval_user_provided_hashes.rb b/test/test_eval_user_provided_hashes.rb index 0314f1d..bdff6be 100644 --- a/test/test_eval_user_provided_hashes.rb +++ b/test/test_eval_user_provided_hashes.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/test_helper.rb b/test/test_helper.rb index c4e18c1..97af938 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,4 +1,4 @@ -# typed: ignore + require 'simplecov' require 'simplecov-lcov' diff --git a/test/test_logging.rb b/test/test_logging.rb index de8e17e..d452a05 100644 --- a/test/test_logging.rb +++ b/test/test_logging.rb @@ -1,4 +1,4 @@ -# typed: false + require_relative 'test_helper' require 'minitest' diff --git a/test/test_network.rb b/test/test_network.rb index ef2df56..b6ac7c8 100644 --- a/test/test_network.rb +++ b/test/test_network.rb @@ -1,4 +1,4 @@ -# typed: false + require_relative 'test_helper' require 'minitest' diff --git a/test/test_network_timeout.rb b/test/test_network_timeout.rb index d3c3119..eb4bcf3 100644 --- a/test/test_network_timeout.rb +++ b/test/test_network_timeout.rb @@ -1,4 +1,4 @@ -# typed: ignore + require_relative 'test_helper' require 'minitest' diff --git a/test/test_statsig.rb b/test/test_statsig.rb index 7621492..e00e7f3 100644 --- a/test/test_statsig.rb +++ b/test/test_statsig.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' diff --git a/test/test_store.rb b/test/test_store.rb index f187c2f..9f8b743 100644 --- a/test/test_store.rb +++ b/test/test_store.rb @@ -1,4 +1,4 @@ -# typed: false + require_relative 'test_helper' require 'minitest/autorun' diff --git a/test/test_symbol_hashes.rb b/test/test_symbol_hashes.rb index 85869cd..99fe450 100644 --- a/test/test_symbol_hashes.rb +++ b/test/test_symbol_hashes.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'json' diff --git a/test/test_user_fields.rb b/test/test_user_fields.rb index 03e2240..7c4f570 100644 --- a/test/test_user_fields.rb +++ b/test/test_user_fields.rb @@ -1,4 +1,4 @@ -# typed: true + require_relative 'test_helper' require 'minitest' From 678e8c69fda4f9b55dff588ad4ba33e9b75a0d39 Mon Sep 17 00:00:00 2001 From: tore-statsig <74584483+tore-statsig@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:03:11 -0800 Subject: [PATCH 02/16] symbolize (#268) Co-authored-by: Daniel Loomb --- lib/client_initialize_helpers.rb | 55 ++++--- lib/dynamic_config.rb | 2 +- lib/evaluation_helpers.rb | 1 - lib/evaluator.rb | 265 +++++++++++++++---------------- lib/layer.rb | 2 +- lib/network.rb | 2 +- lib/spec_store.rb | 148 +++++++++-------- lib/statsig_driver.rb | 8 +- lib/statsig_event.rb | 14 +- lib/statsig_logger.rb | 34 ++-- lib/statsig_user.rb | 68 +++----- test/dynamic_config_test.rb | 17 +- test/layer_exposure_test.rb | 10 +- test/layer_test.rb | 12 +- test/manual_exposure_test.rb | 24 +-- test/test_diagnostics.rb | 3 +- test/test_logging.rb | 10 +- test/test_symbol_hashes.rb | 3 +- 18 files changed, 330 insertions(+), 348 deletions(-) diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index d95ff95..f716278 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -11,13 +11,12 @@ class ResponseFormatter def initialize(evaluator, user, hash, client_sdk_key) @evaluator = evaluator @user = user - @specs = evaluator.spec_store.get_raw_specs @hash = hash @client_sdk_key = client_sdk_key end - def get_responses(key) - @specs[key] + def get_responses(entities) + entities .map { |name, spec| to_response(name, spec) } .delete_if { |v| v.nil? }.to_h end @@ -33,7 +32,7 @@ def filter_segments_from_secondary_exposures(secondary_exposures) def to_response(config_name, config_spec) target_app_id = @evaluator.spec_store.get_app_id_for_sdk_key(@client_sdk_key) - config_target_apps = config_spec['targetAppIDs'] + config_target_apps = config_spec[:targetAppIDs] unless target_app_id.nil? || (!config_target_apps.nil? && config_target_apps.include?(target_app_id)) return nil @@ -44,8 +43,8 @@ def to_response(config_name, config_spec) return nil end - category = config_spec['type'] - entity_type = config_spec['entity'] + category = config_spec[:type] + entity_type = config_spec[:entity] result = {} @@ -60,7 +59,7 @@ def to_response(config_name, config_spec) result["group_name"] = eval_result.group_name result["id_type"] = eval_result.id_type when 'dynamic_config' - id_type = config_spec['idType'] + id_type = config_spec[:idType] result['value'] = eval_result.json_value result["group"] = eval_result.rule_id result["group_name"] = eval_result.group_name @@ -76,22 +75,22 @@ def to_response(config_name, config_spec) if entity_type == 'layer' populate_layer_fields(config_spec, eval_result, result) - result.delete('id_type') # not exposed for layer configs in /initialize + result.delete(:id_type) # not exposed for layer configs in /initialize end hashed_name = hash_name(config_name) [hashed_name, result.merge( { - "name" => hashed_name, - "rule_id" => eval_result.rule_id, - "secondary_exposures" => clean_exposures(eval_result.secondary_exposures) + :name => hashed_name, + :rule_id => eval_result.rule_id, + :secondary_exposures => clean_exposures(eval_result.secondary_exposures) }).compact] end def clean_exposures(exposures) seen = {} exposures.reject do |exposure| - key = "#{exposure["gate"]}|#{exposure["gateValue"]}|#{exposure["ruleID"]}}" + key = "#{exposure[:gate]}|#{exposure[:gateValue]}|#{exposure[:ruleID]}}" should_reject = seen[key] seen[key] = true should_reject == true @@ -99,40 +98,40 @@ def clean_exposures(exposures) end def populate_experiment_fields(config_name, config_spec, eval_result, result) - result["is_user_in_experiment"] = eval_result.is_experiment_group - result["is_experiment_active"] = config_spec['isActive'] == true + result[:is_user_in_experiment] = eval_result.is_experiment_group + result[:is_experiment_active] = config_spec[:isActive] == true - if config_spec['hasSharedParams'] != true + if config_spec[:hasSharedParams] != true return end - result["is_in_layer"] = true - result["explicit_parameters"] = config_spec["explicitParameters"] || [] + result[:is_in_layer] = true + result[:explicit_parameters] = config_spec[:explicitParameters] || [] - layer_name = @specs[:experiment_to_layer][config_name] - if layer_name.nil? || @specs[:layers][layer_name].nil? + layer_name = @evaluator.spec_store.experiment_to_layer[config_name] + if layer_name.nil? || @evaluator.spec_store.layers[layer_name].nil? return end - layer = @specs[:layers][layer_name] - result["value"] = layer["defaultValue"].merge(result["value"]) + layer = @evaluator.spec_store.layers[layer_name] + result[:value] = layer[:defaultValue].merge(result[:value]) end def populate_layer_fields(config_spec, eval_result, result) delegate = eval_result.config_delegate - result["explicit_parameters"] = config_spec["explicitParameters"] || [] + result[:explicit_parameters] = config_spec[:explicitParameters] || [] if delegate.nil? == false && delegate.empty? == false - delegate_spec = @specs[:configs][delegate] + delegate_spec = @evaluator.spec_store.configs[delegate] delegate_result = @evaluator.eval_spec(@user, delegate_spec) - result["allocated_experiment_name"] = hash_name(delegate) - result["is_user_in_experiment"] = delegate_result.is_experiment_group - result["is_experiment_active"] = delegate_spec['isActive'] == true - result["explicit_parameters"] = delegate_spec["explicitParameters"] || [] + result[:allocated_experiment_name] = hash_name(delegate) + result[:is_user_in_experiment] = delegate_result.is_experiment_group + result[:is_experiment_active] = delegate_spec[:isActive] == true + result[:explicit_parameters] = delegate_spec[:explicitParameters] || [] end - result["undelegated_secondary_exposures"] = clean_exposures(eval_result.undelegated_sec_exps || []) + result[:undelegated_secondary_exposures] = clean_exposures(eval_result.undelegated_sec_exps || []) end def hash_name(name) diff --git a/lib/dynamic_config.rb b/lib/dynamic_config.rb index a07a34d..17c363c 100644 --- a/lib/dynamic_config.rb +++ b/lib/dynamic_config.rb @@ -41,7 +41,7 @@ class DynamicConfig # end def initialize(name, value = {}, rule_id = '', group_name = nil, id_type = '', evaluation_details = nil) @name = name - @value = value + @value = JSON.parse(JSON.generate(value)) @rule_id = rule_id @group_name = group_name @id_type = id_type diff --git a/lib/evaluation_helpers.rb b/lib/evaluation_helpers.rb index f8e246e..cdcf1e6 100644 --- a/lib/evaluation_helpers.rb +++ b/lib/evaluation_helpers.rb @@ -9,7 +9,6 @@ def self.compare_numbers(a, b, func) # returns true if array has any element that evaluates to true with value using func lambda, ignoring case def self.match_string_in_array(array, value, ignore_case, func) - return false unless array.is_a?(Array) && !value.nil? str_value = value.to_s array.any?{ |s| !s.nil? && ((ignore_case && func.call(str_value.downcase, s.to_s.downcase)) || func.call(str_value, s.to_s)) } rescue false end diff --git a/lib/evaluator.rb b/lib/evaluator.rb index d51a3f5..a6995cc 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -67,14 +67,13 @@ def check_gate(user, gate_name) unless @spec_store.has_gate?(gate_name) return Statsig::ConfigResult.new(gate_name, evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) end - eval_spec(user, @spec_store.get_gate(gate_name)) end # sig { params(user: StatsigUser, config_name: String, user_persisted_values: T.nilable(UserPersistedValues)).returns(ConfigResult) } def get_config(user, config_name, user_persisted_values: nil) if @config_overrides.key?(config_name) - id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)['idType'] : '' + id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)[:idType] : '' return Statsig::ConfigResult.new( config_name, false, @@ -106,7 +105,7 @@ def get_config(user, config_name, user_persisted_values: nil) config = @spec_store.get_config(config_name) # If persisted values is provided and the experiment is active, return sticky values if exists. - if !user_persisted_values.nil? && config['isActive'] == true + if !user_persisted_values.nil? && config[:isActive] == true sticky_result = Statsig::ConfigResult.from_user_persisted_values(config_name, user_persisted_values) return sticky_result unless sticky_result.nil? @@ -114,15 +113,14 @@ def get_config(user, config_name, user_persisted_values: nil) evaluation = eval_spec(user, config) if evaluation.is_experiment_group @persistent_storage_utils.add_evaluation_to_user_persisted_values(user_persisted_values, config_name, evaluation) - @persistent_storage_utils.save_to_storage(user, config['idType'], user_persisted_values) + @persistent_storage_utils.save_to_storage(user, config[:idType], user_persisted_values) end # Otherwise, remove from persisted storage else - @persistent_storage_utils.remove_experiment_from_storage(user, config['idType'], config_name) + @persistent_storage_utils.remove_experiment_from_storage(user, config[:idType], config_name) evaluation = eval_spec(user, config) end - - return evaluation + evaluation end def get_layer(user, layer_name) @@ -142,15 +140,15 @@ def list_gates end def list_configs - @spec_store.configs.map { |name, config| name if config['entity'] == 'dynamic_config' }.compact + @spec_store.configs.map { |name, config| name if config[:entity] == 'dynamic_config' }.compact end def list_experiments - @spec_store.configs.map { |name, config| name if config['entity'] == 'experiment' }.compact + @spec_store.configs.map { |name, config| name if config[:entity] == 'experiment' }.compact end def list_autotunes - @spec_store.configs.map { |name, config| name if config['entity'] == 'autotune' }.compact + @spec_store.configs.map { |name, config| name if config[:entity] == 'autotune' }.compact end def list_layers @@ -166,37 +164,27 @@ def get_client_initialize_response(user, hash, client_sdk_key) evaluated_keys = {} if user.user_id.nil? == false - evaluated_keys['userID'] = user.user_id + evaluated_keys[:userID] = user.user_id end if user.custom_ids.nil? == false - evaluated_keys['customIDs'] = user.custom_ids + evaluated_keys[:customIDs] = user.custom_ids end { - "feature_gates" => formatter.get_responses(:gates), - "dynamic_configs" => formatter.get_responses(:configs), - "layer_configs" => formatter.get_responses(:layers), - "sdkParams" => {}, - "has_updates" => true, - "generator" => "statsig-ruby-sdk", - "evaluated_keys" => evaluated_keys, - "time" => 0, - "hash_used" => hash, - "user_hash" => user.to_hash_without_stable_id() + 'feature_gates' => formatter.get_responses(@spec_store.gates), + 'dynamic_configs' => formatter.get_responses(@spec_store.configs), + 'layer_configs' => formatter.get_responses(@spec_store.layers), + 'sdkParams' => {}, + 'has_updates' => true, + 'generator' => 'statsig-ruby-sdk', + 'evaluated_keys' => evaluated_keys, + 'time' => 0, + 'hash_used' => hash, + 'user_hash' => user.to_hash_without_stable_id() } end - def clean_exposures(exposures) - seen = {} - exposures.reject do |exposure| - key = "#{exposure["gate"]}|#{exposure["gateValue"]}|#{exposure["ruleID"]}}" - should_reject = seen[key] - seen[key] = true - should_reject == true - end - end - def shutdown @spec_store.shutdown end @@ -213,16 +201,16 @@ def override_config(config, value) def eval_spec(user, config) default_rule_id = 'default' exposures = [] - if config['enabled'] + if config[:enabled] i = 0 - until i >= config['rules'].length do - rule = config['rules'][i] + until i >= config[:rules].length do + rule = config[:rules][i] result = eval_rule(user, rule) return Statsig::ConfigResult.new( - config['name'], + config[:name], false, - config['defaultValue'], - default_rule_id, + config[:defaultValue], + '', exposures, evaluation_details: EvaluationDetails.new( @spec_store.last_config_sync_time, @@ -230,21 +218,21 @@ def eval_spec(user, config) EvaluationReason::UNSUPPORTED, ), group_name: nil, - id_type: config['idType'], - target_app_ids: config['targetAppIDs'] + id_type: config[:idType], + target_app_ids: config[:targetAppIDs] ) if result == UNSUPPORTED_EVALUATION exposures = exposures + result.secondary_exposures if result.gate_value - if (delegated_result = eval_delegate(config['name'], user, rule, exposures)) + if (delegated_result = eval_delegate(config[:name], user, rule, exposures)) return delegated_result end - pass = eval_pass_percent(user, rule, config['salt']) + pass = eval_pass_percent(user, rule, config[:salt]) return Statsig::ConfigResult.new( - config['name'], + config[:name], pass, - pass ? result.json_value : config['defaultValue'], + pass ? result.json_value : config[:defaultValue], result.rule_id, exposures, evaluation_details: EvaluationDetails.new( @@ -254,8 +242,8 @@ def eval_spec(user, config) ), is_experiment_group: result.is_experiment_group, group_name: result.group_name, - id_type: config['idType'], - target_app_ids: config['targetAppIDs'] + id_type: config[:idType], + target_app_ids: config[:targetAppIDs] ) end @@ -266,9 +254,9 @@ def eval_spec(user, config) end Statsig::ConfigResult.new( - config['name'], + config[:name], false, - config['defaultValue'], + config[:defaultValue], default_rule_id, exposures, evaluation_details: EvaluationDetails.new( @@ -277,8 +265,8 @@ def eval_spec(user, config) @spec_store.init_reason ), group_name: nil, - id_type: config['idType'], - target_app_ids: config['targetAppIDs'] + id_type: config[:idType], + target_app_ids: config[:targetAppIDs] ) end @@ -288,15 +276,15 @@ def eval_rule(user, rule) exposures = [] pass = true i = 0 - until i >= rule['conditions'].length do - result = eval_condition(user, rule['conditions'][i]) + until i >= rule[:conditions].length do + result = eval_condition(user, rule[:conditions][i]) if result == UNSUPPORTED_EVALUATION return UNSUPPORTED_EVALUATION end if result.is_a?(Hash) - exposures = exposures + result['exposures'] if result['exposures'].is_a? Array - pass = false if result['value'] == false + exposures = exposures + result[:exposures] + pass = false if result[:value] == false elsif result == false pass = false end @@ -306,21 +294,21 @@ def eval_rule(user, rule) Statsig::ConfigResult.new( '', pass, - rule['returnValue'], - rule['id'], + rule[:returnValue], + rule[:id], exposures, evaluation_details: EvaluationDetails.new( @spec_store.last_config_sync_time, @spec_store.initial_config_sync_time, @spec_store.init_reason ), - is_experiment_group: rule["isExperimentGroup"] == true, - group_name: rule['groupName'] + is_experiment_group: rule[:isExperimentGroup] == true, + group_name: rule[:groupName] ) end def eval_delegate(name, user, rule, exposures) - return nil unless (delegate = rule['configDelegate']) + return nil unless (delegate = rule[:configDelegate]) return nil unless (config = @spec_store.get_config(delegate)) delegated_result = self.eval_spec(user, config) @@ -330,135 +318,129 @@ def eval_delegate(name, user, rule, exposures) delegated_result.config_delegate = delegate delegated_result.secondary_exposures = exposures + delegated_result.secondary_exposures delegated_result.undelegated_sec_exps = exposures - delegated_result.explicit_parameters = config['explicitParameters'] + delegated_result.explicit_parameters = config[:explicitParameters] delegated_result end def eval_condition(user, condition) value = nil - field = condition['field'] - target = condition['targetValue'] - type = condition['type'] - operator = condition['operator'] - additional_values = condition['additionalValues'] + field = condition[:field] + target = condition[:targetValue] + type = condition[:type] + operator = condition[:operator] + additional_values = condition[:additionalValues] additional_values = Hash.new unless additional_values.is_a? Hash - id_type = condition['idType'] - - return UNSUPPORTED_EVALUATION unless type.is_a? String - type = type.downcase + id_type = condition[:idType] case type - when 'public' + when :public return true - when 'fail_gate', 'pass_gate' + when :fail_gate, :pass_gate other_gate_result = check_gate(user, target) return UNSUPPORTED_EVALUATION if other_gate_result == UNSUPPORTED_EVALUATION gate_value = other_gate_result&.gate_value == true new_exposure = { - 'gate' => target, - 'gateValue' => gate_value ? 'true' : 'false', - 'ruleID' => other_gate_result&.rule_id + gate: target, + gateValue: gate_value ? 'true' : 'false', + ruleID: other_gate_result&.rule_id } exposures = other_gate_result&.secondary_exposures&.append(new_exposure) return { - 'value' => type == 'pass_gate' ? gate_value : !gate_value, - 'exposures' => exposures + value: type == :pass_gate ? gate_value : !gate_value, + exposures: exposures } - when 'ip_based' + when :ip_based value = get_value_from_user(user, field) || get_value_from_ip(user, field) - when 'ua_based' + when :ua_based value = get_value_from_user(user, field) || get_value_from_ua(user, field) - when 'user_field' + when :user_field value = get_value_from_user(user, field) - when 'environment_field' + when :environment_field value = get_value_from_environment(user, field) - when 'current_time' + when :current_time value = Time.now.to_i # epoch time in seconds - when 'user_bucket' + when :user_bucket begin - salt = additional_values['salt'] + salt = additional_values[:salt] unit_id = user.get_unit_id(id_type) || '' # there are only 1000 user buckets as opposed to 10k for gate pass % value = compute_user_hash("#{salt}.#{unit_id}") % 1000 rescue return false end - when 'unit_id' + when :unit_id value = user.get_unit_id(id_type) else return UNSUPPORTED_EVALUATION end - return UNSUPPORTED_EVALUATION if !operator.is_a?(String) - operator = operator.downcase - case operator # numerical comparison - when 'gt' + when :gt return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a > b }) - when 'gte' + when :gte return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a >= b }) - when 'lt' + when :lt return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a < b }) - when 'lte' + when :lte return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a <= b }) # version comparison # need to check for nil or empty value because Version takes them as valid values - when 'version_gt' + when :version_gt return false if value.to_s.empty? return (Gem::Version.new(value) > Gem::Version.new(target) rescue false) - when 'version_gte' + when :version_gte return false if value.to_s.empty? return (Gem::Version.new(value) >= Gem::Version.new(target) rescue false) - when 'version_lt' + when :version_lt return false if value.to_s.empty? return (Gem::Version.new(value) < Gem::Version.new(target) rescue false) - when 'version_lte' + when :version_lte return false if value.to_s.empty? return (Gem::Version.new(value) <= Gem::Version.new(target) rescue false) - when 'version_eq' + when :version_eq return false if value.to_s.empty? return (Gem::Version.new(value) == Gem::Version.new(target) rescue false) - when 'version_neq' + when :version_neq return false if value.to_s.empty? return (Gem::Version.new(value) != Gem::Version.new(target) rescue false) # array operations - when 'any' + when :any return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a == b }) - when 'none' + when :none return !EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a == b }) - when 'any_case_sensitive' + when :any_case_sensitive return EvaluationHelpers::match_string_in_array(target, value, false, ->(a, b) { a == b }) - when 'none_case_sensitive' + when :none_case_sensitive return !EvaluationHelpers::match_string_in_array(target, value, false, ->(a, b) { a == b }) # string - when 'str_starts_with_any' + when :str_starts_with_any return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.start_with?(b) }) - when 'str_ends_with_any' + when :str_ends_with_any return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.end_with?(b) }) - when 'str_contains_any' + when :str_contains_any return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) - when 'str_contains_none' + when :str_contains_none return !EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) - when 'str_matches' + when :str_matches return (value.is_a?(String) && !(value =~ Regexp.new(target)).nil? rescue false) - when 'eq' + when :eq return value == target - when 'neq' + when :neq return value != target # dates - when 'before' + when :before return EvaluationHelpers::compare_times(value, target, ->(a, b) { a < b }) - when 'after' + when :after return EvaluationHelpers::compare_times(value, target, ->(a, b) { a > b }) - when 'on' + when :on return EvaluationHelpers::compare_times(value, target, ->(a, b) { a.year == b.year && a.month == b.month && a.day == b.day }) - when 'in_segment_list', 'not_in_segment_list' + when :in_segment_list, :not_in_segment_list begin is_in_list = false id_list = @spec_store.get_id_list(target) @@ -466,7 +448,7 @@ def eval_condition(user, condition) hashed_id = Digest::SHA256.base64digest(value.to_s)[0, 8] is_in_list = id_list.ids.include?(hashed_id) end - return is_in_list if operator == 'in_segment_list' + return is_in_list if operator == :in_segment_list return !is_in_list rescue return false @@ -477,32 +459,34 @@ def eval_condition(user, condition) end def get_value_from_user(user, field) - return nil unless user.instance_of?(StatsigUser) && field.is_a?(String) - - user_lookup_table = user&.value_lookup - return nil unless user_lookup_table.is_a?(Hash) - return user_lookup_table[field.downcase] if user_lookup_table.has_key?(field.downcase) && !user_lookup_table[field.downcase].nil? - - user_custom = user_lookup_table['custom'] - if user_custom.is_a?(Hash) - user_custom.each do |key, value| - return value if key.to_s.downcase.casecmp?(field.downcase) && !value.nil? - end + value = case field.downcase + when 'userid', 'user_id' + user.user_id + when 'email' + user.email + when 'ip' + user.ip + when 'useragent', 'user_agent' + user.user_agent + when 'country' + user.country + when 'locale' + user.locale + when 'appversion', 'app_version' + user.app_version + else + nil end - - private_attributes = user_lookup_table['privateAttributes'] - if private_attributes.is_a?(Hash) - private_attributes.each do |key, value| - return value if key.to_s.downcase.casecmp?(field.downcase) && !value.nil? - end + if value.nil? + value = user.custom[field] if user.custom.is_a?(Hash) + value = user.custom[field.to_sym] if value.nil? && user.custom.is_a?(Hash) + value = user.private_attributes[field] if value.nil? && user.private_attributes.is_a?(Hash) + value = user.private_attributes[field.to_sym] if value.nil? && user.private_attributes.is_a?(Hash) end - - nil + value end def get_value_from_environment(user, field) - return nil unless user.instance_of?(StatsigUser) && field.is_a?(String) - field = field.downcase return nil unless user.statsig_environment.is_a? Hash user.statsig_environment.each do |key, value| return value if key.to_s.downcase == (field) @@ -511,7 +495,7 @@ def get_value_from_environment(user, field) end def get_value_from_ip(user, field) - return nil unless user.is_a?(StatsigUser) && field.is_a?(String) && field.downcase == 'country' + return nil unless field == 'country' ip = get_value_from_user(user, 'ip') return nil unless ip.is_a?(String) @@ -519,8 +503,7 @@ def get_value_from_ip(user, field) end def get_value_from_ua(user, field) - return nil unless user.is_a?(StatsigUser) && field.is_a?(String) - ua = get_value_from_user(user, 'userAgent') + ua = get_value_from_user(user, 'user_agent') return nil unless ua.is_a?(String) case field.downcase @@ -542,12 +525,12 @@ def get_value_from_ua(user, field) end def eval_pass_percent(user, rule, config_salt) - return false unless config_salt.is_a?(String) && !rule['passPercentage'].nil? + return false unless config_salt.is_a?(String) && !rule[:passPercentage].nil? begin - unit_id = user.get_unit_id(rule['idType']) || '' - rule_salt = rule['salt'] || rule['id'] || '' + unit_id = user.get_unit_id(rule[:idType]) || '' + rule_salt = rule[:salt] || rule[:id] || '' hash = compute_user_hash("#{config_salt}.#{rule_salt}.#{unit_id}") - return (hash % 10000) < (rule['passPercentage'].to_f * 100) + return (hash % 10000) < (rule[:passPercentage].to_f * 100) rescue return false end diff --git a/lib/layer.rb b/lib/layer.rb index bf62919..2eb1b4c 100644 --- a/lib/layer.rb +++ b/lib/layer.rb @@ -32,7 +32,7 @@ class Layer # end def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_experiment = nil, exposure_log_func = nil) @name = name - @value = value + @value = JSON.parse(JSON.generate(value)) @rule_id = rule_id @group_name = group_name @allocated_experiment = allocated_experiment diff --git a/lib/network.rb b/lib/network.rb index 7d8010b..ae0563a 100644 --- a/lib/network.rb +++ b/lib/network.rb @@ -133,7 +133,7 @@ def request(method, endpoint, body, retries = 0, backoff = 1) end def post_logs(events) - json_body = JSON.generate({ 'events' => events, 'statsigMetadata' => Statsig.get_statsig_metadata }) + json_body = JSON.generate({ :events => events, :statsigMetadata => Statsig.get_statsig_metadata }) post('log_event', json_body, @post_logs_retry_limit) rescue StandardError diff --git a/lib/spec_store.rb b/lib/spec_store.rb index 6ef3a56..1309222 100644 --- a/lib/spec_store.rb +++ b/lib/spec_store.rb @@ -12,6 +12,13 @@ class SpecStore attr_accessor :last_config_sync_time attr_accessor :initial_config_sync_time attr_accessor :init_reason + attr_accessor :gates + attr_accessor :configs + attr_accessor :layers + attr_accessor :id_lists + attr_accessor :experiment_to_layer + attr_accessor :sdk_keys_to_app_ids + attr_accessor :hashed_sdk_keys_to_app_ids def initialize(network, options, error_callback, diagnostics, error_boundary, logger, secret_key) @init_reason = EvaluationReason::UNINITIALIZED @@ -23,15 +30,13 @@ def initialize(network, options, error_callback, diagnostics, error_boundary, lo @rulesets_sync_interval = options.rulesets_sync_interval @id_lists_sync_interval = options.idlists_sync_interval @rules_updated_callback = options.rules_updated_callback - @specs = { - :gates => {}, - :configs => {}, - :layers => {}, - :id_lists => {}, - :experiment_to_layer => {}, - :sdk_keys_to_app_ids => {}, - :hashed_sdk_keys_to_app_ids => {} - } + @gates = {} + @configs = {} + @layers = {} + @id_lists = {} + @experiment_to_layer = {} + @sdk_keys_to_app_ids = {} + @hashed_sdk_keys_to_app_ids = {} @diagnostics = diagnostics @error_boundary = error_boundary @logger = logger @@ -96,70 +101,55 @@ def shutdown end def has_gate?(gate_name) - @specs[:gates].key?(gate_name) + @gates.key?(gate_name) end def has_config?(config_name) - @specs[:configs].key?(config_name) + @configs.key?(config_name) end def has_layer?(layer_name) - @specs[:layers].key?(layer_name) + @layers.key?(layer_name) end def get_gate(gate_name) return nil unless has_gate?(gate_name) - @specs[:gates][gate_name] + @gates[gate_name] end def get_config(config_name) return nil unless has_config?(config_name) - @specs[:configs][config_name] + @configs[config_name] end def get_layer(layer_name) return nil unless has_layer?(layer_name) - @specs[:layers][layer_name] - end - - def gates - @specs[:gates] - end - - def configs - @specs[:configs] - end - - def layers - @specs[:layers] + @layers[layer_name] end def get_id_list(list_name) - @specs[:id_lists][list_name] + @id_lists[list_name] end def has_sdk_key?(sdk_key) - @specs[:sdk_keys_to_app_ids].key?(sdk_key) + @sdk_keys_to_app_ids.key?(sdk_key) end def has_hashed_sdk_key?(hashed_sdk_key) - @specs[:hashed_sdk_keys_to_app_ids].key?(hashed_sdk_key) + @hashed_sdk_keys_to_app_ids.key?(hashed_sdk_key) end def get_app_id_for_sdk_key(sdk_key) if sdk_key.nil? return nil end - hashed_sdk_key = Statsig::HashUtils.djb2(sdk_key) + hashed_sdk_key = Statsig::HashUtils.djb2(sdk_key).to_sym if has_hashed_sdk_key?(hashed_sdk_key) - return @specs[:hashed_sdk_keys_to_app_ids][hashed_sdk_key] + return @hashed_sdk_keys_to_app_ids[hashed_sdk_key] end - return nil unless has_sdk_key?(sdk_key) - @specs[:sdk_keys_to_app_ids][sdk_key] - end - - def get_raw_specs - @specs + key = sdk_key.to_sym + return nil unless has_sdk_key?(key) + @sdk_keys_to_app_ids[key] end def maybe_restart_background_threads @@ -285,43 +275,41 @@ def process_specs(specs_string, from_adapter: false) return false end - specs_json = JSON.parse(specs_string) + specs_json = JSON.parse(specs_string, {:symbolize_names => true}) return false unless specs_json.is_a? Hash - hashed_sdk_key_used = specs_json['hashed_sdk_key_used'] + hashed_sdk_key_used = specs_json[:hashed_sdk_key_used] unless hashed_sdk_key_used.nil? or hashed_sdk_key_used == Statsig::HashUtils.djb2(@secret_key) err_boundary.log_exception(Statsig::InvalidSDKKeyResponse.new) return false end - @last_config_sync_time = specs_json['time'] || @last_config_sync_time - return false unless specs_json['has_updates'] == true && - !specs_json['feature_gates'].nil? && - !specs_json['dynamic_configs'].nil? && - !specs_json['layer_configs'].nil? + @last_config_sync_time = specs_json[:time] || @last_config_sync_time + return false unless specs_json[:has_updates] == true && + !specs_json[:feature_gates].nil? && + !specs_json[:dynamic_configs].nil? && + !specs_json[:layer_configs].nil? - new_gates = {} - new_configs = {} - new_layers = {} - new_exp_to_layer = {} - specs_json['feature_gates'].each { |gate| new_gates[gate['name']] = gate } - specs_json['dynamic_configs'].each { |config| new_configs[config['name']] = config } - specs_json['layer_configs'].each { |layer| new_layers[layer['name']] = layer } - specs_json['diagnostics']&.each { |key, value| @diagnostics.sample_rates[key] = value } + new_gates = process_configs(specs_json[:feature_gates]) + new_configs = process_configs(specs_json[:dynamic_configs]) + new_layers = process_configs(specs_json[:layer_configs]) + + new_exp_to_layer = {} + specs_json[:diagnostics]&.each { |key, value| @diagnostics.sample_rates[key.to_s] = value } - if specs_json['layers'].is_a?(Hash) - specs_json['layers'].each { |layer_name, experiments| + if specs_json[:layers].is_a?(Hash) + specs_json[:layers].each { |layer_name, experiments| experiments.each { |experiment_name| new_exp_to_layer[experiment_name] = layer_name } } end - @specs[:gates] = new_gates - @specs[:configs] = new_configs - @specs[:layers] = new_layers - @specs[:experiment_to_layer] = new_exp_to_layer - @specs[:sdk_keys_to_app_ids] = specs_json['sdk_keys_to_app_ids'] || {} - @specs[:hashed_sdk_keys_to_app_ids] = specs_json['hashed_sdk_keys_to_app_ids'] || {} + @gates = new_gates + @configs = new_configs + @layers = new_layers + @experiment_to_layer = new_exp_to_layer + @sdk_keys_to_app_ids = specs_json[:sdk_keys_to_app_ids] || {} + @hashed_sdk_keys_to_app_ids = specs_json[:hashed_sdk_keys_to_app_ids] || {} unless from_adapter save_config_specs_to_storage_adapter(specs_string) @@ -329,6 +317,40 @@ def process_specs(specs_string, from_adapter: false) true end + def process_configs(configs) + configs.each_with_object({}) do |config, new_configs| + new_configs[config[:name]] = process_config(config) + end + end + + def process_config(config) + config[:rules] = process_rules(config[:rules]) if config.key?(:rules) + config + end + + def process_rules(rules) + rules.map do |rule| + rule[:conditions] = process_conditions(rule[:conditions]) if rule.key?(:conditions) + rule + end + end + + def process_conditions(conditions) + conditions.map do |condition| + # try symbols for perf + condition[:operator] = condition[:operator].downcase.to_sym unless condition[:operator].nil? + condition[:type] = condition[:type].downcase.to_sym unless condition[:type].nil? + + if condition[:targetValue].is_a?(Array) + # target values are really sets, which will be more performant for evaluation + # for now, create the set + condition[:targetValue] = condition[:targetValue].to_set + end + + condition + end + end + def get_id_lists_from_adapter tracker = @diagnostics.track('data_store_id_lists', 'fetch') cached_values = @options.data_store.get(Interfaces::IDataStore::ID_LISTS_KEY) @@ -373,7 +395,7 @@ def get_id_lists_from_network end def process_id_lists(new_id_lists, from_adapter: false) - local_id_lists = @specs[:id_lists] + local_id_lists = @id_lists if !new_id_lists.is_a?(Hash) || !local_id_lists.is_a?(Hash) return end @@ -481,7 +503,7 @@ def process_single_id_list(list, content, content_length = nil, from_adapter: fa begin tracker = @diagnostics.track(from_adapter ? 'data_store_id_list' : 'get_id_list', 'process', { url: list.url }) unless content.is_a?(String) && (content[0] == '-' || content[0] == '+') - @specs[:id_lists].delete(list.name) + @id_lists.delete(list.name) tracker.end(success: false) return false end diff --git a/lib/statsig_driver.rb b/lib/statsig_driver.rb index 7146ad9..a3d8632 100644 --- a/lib/statsig_driver.rb +++ b/lib/statsig_driver.rb @@ -59,7 +59,7 @@ def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: if skip_evaluation gate = @store.get_gate(gate_name) return FeatureGate.new(gate_name) if gate.nil? - return FeatureGate.new(gate['name'], target_app_ids: gate['targetAppIDs']) + return FeatureGate.new(gate[:name], target_app_ids: gate[:targetAppIDs]) end user = verify_inputs(user, gate_name, 'gate_name') @@ -98,7 +98,7 @@ def check_gate(user, gate_name, options = Statsig::CheckGateOptions.new) def manually_log_gate_exposure(user, gate_name) @err_boundary.capture(task: lambda { res = @evaluator.check_gate(user, gate_name) - context = { 'is_manual_exposure' => true } + context = { :is_manual_exposure => true } @logger.log_gate_exposure(user, gate_name, res.gate_value, res.rule_id, res.secondary_exposures, res.evaluation_details, context) }) end @@ -127,7 +127,7 @@ def get_experiment(user, experiment_name, options = Statsig::GetExperimentOption def manually_log_config_exposure(user, config_name) @err_boundary.capture(task: lambda { res = @evaluator.get_config(user, config_name) - context = { 'is_manual_exposure' => true } + context = { :is_manual_exposure => true } @logger.log_config_exposure(user, res.name, res.rule_id, res.secondary_exposures, res.evaluation_details, context) }, caller: __method__.to_s) end @@ -166,7 +166,7 @@ def manually_log_layer_parameter_exposure(user, layer_name, parameter_name) @err_boundary.capture(task: lambda { res = @evaluator.get_layer(user, layer_name) layer = Layer.new(layer_name, res.json_value, res.rule_id, res.group_name, res.config_delegate) - context = { 'is_manual_exposure' => true } + context = { :is_manual_exposure => true } @logger.log_layer_exposure(user, layer, parameter_name, res, context) }, caller: __method__.to_s) end diff --git a/lib/statsig_event.rb b/lib/statsig_event.rb index a9079a8..2226c8b 100644 --- a/lib/statsig_event.rb +++ b/lib/statsig_event.rb @@ -21,13 +21,13 @@ def user=(value) def serialize { - 'eventName' => @event_name, - 'metadata' => @metadata, - 'value' => @value, - 'user' => @user, - 'time' => @time, - 'statsigMetadata' => @statsig_metadata, - 'secondaryExposures' => @secondary_exposures + :eventName => @event_name, + :metadata => @metadata, + :value => @value, + :user => @user, + :time => @time, + :statsigMetadata => @statsig_metadata, + :secondaryExposures => @secondary_exposures } end end \ No newline at end of file diff --git a/lib/statsig_logger.rb b/lib/statsig_logger.rb index 0c5a9ab..f8eadd5 100644 --- a/lib/statsig_logger.rb +++ b/lib/statsig_logger.rb @@ -6,7 +6,7 @@ $config_exposure_event = 'statsig::config_exposure' $layer_exposure_event = 'statsig::layer_exposure' $diagnostics_event = 'statsig::diagnostics' -$ignored_metadata_keys = ['serverTime', 'configSyncTime', 'initTime', 'reason'] +$ignored_metadata_keys = [:serverTime, :configSyncTime, :initTime, :reason] module Statsig class StatsigLogger def initialize(network, options, error_boundary) @@ -41,9 +41,9 @@ def log_gate_exposure(user, gate_name, value, rule_id, secondary_exposures, eval event = StatsigEvent.new($gate_exposure_event) event.user = user metadata = { - 'gate' => gate_name, - 'gateValue' => value.to_s, - 'ruleID' => rule_id, + :gate => gate_name, + :gateValue => value.to_s, + :ruleID => rule_id, } return false if not is_unique_exposure(user, $gate_exposure_event, metadata) event.metadata = metadata @@ -59,8 +59,8 @@ def log_config_exposure(user, config_name, rule_id, secondary_exposures, eval_de event = StatsigEvent.new($config_exposure_event) event.user = user metadata = { - 'config' => config_name, - 'ruleID' => rule_id, + :config => config_name, + :ruleID => rule_id, } return false if not is_unique_exposure(user, $config_exposure_event, metadata) event.metadata = metadata @@ -83,11 +83,11 @@ def log_layer_exposure(user, layer, parameter_name, config_evaluation, context = event = StatsigEvent.new($layer_exposure_event) event.user = user metadata = { - 'config' => layer.name, - 'ruleID' => layer.rule_id, - 'allocatedExperiment' => allocated_experiment, - 'parameterName' => parameter_name, - 'isExplicitParameter' => String(is_explicit), + :config => layer.name, + :ruleID => layer.rule_id, + :allocatedExperiment => allocated_experiment, + :parameterName => parameter_name, + :isExplicitParameter => String(is_explicit), } return false if not is_unique_exposure(user, $layer_exposure_event, metadata) event.metadata = metadata @@ -164,10 +164,10 @@ def safe_add_eval_details(eval_details, event) return end - event.metadata['reason'] = eval_details.reason - event.metadata['configSyncTime'] = eval_details.config_sync_time - event.metadata['initTime'] = eval_details.init_time - event.metadata['serverTime'] = eval_details.server_time + event.metadata[:reason] = eval_details.reason + event.metadata[:configSyncTime] = eval_details.config_sync_time + event.metadata[:initTime] = eval_details.init_time + event.metadata[:serverTime] = eval_details.server_time end def safe_add_exposure_context(context, event) @@ -175,8 +175,8 @@ def safe_add_exposure_context(context, event) return end - if context['is_manual_exposure'] - event.metadata['isManualExposure'] = 'true' + if context[:is_manual_exposure] + event.metadata[:isManualExposure] = 'true' end end diff --git a/lib/statsig_user.rb b/lib/statsig_user.rb index 945cc76..f3b71d0 100644 --- a/lib/statsig_user.rb +++ b/lib/statsig_user.rb @@ -83,20 +83,20 @@ def initialize(user_hash) def serialize(for_logging) hash = { - 'userID' => @user_id, - 'email' => @email, - 'ip' => @ip, - 'userAgent' => @user_agent, - 'country' => @country, - 'locale' => @locale, - 'appVersion' => @app_version, - 'custom' => @custom, - 'statsigEnvironment' => @statsig_environment, - 'privateAttributes' => @private_attributes, - 'customIDs' => @custom_ids, + :userID => @user_id, + :email => @email, + :ip => @ip, + :userAgent => @user_agent, + :country => @country, + :locale => @locale, + :appVersion => @app_version, + :custom => @custom, + :statsigEnvironment => @statsig_environment, + :privateAttributes => @private_attributes, + :customIDs => @custom_ids, } if for_logging - hash.delete('privateAttributes') + hash.delete(:privateAttributes) end hash.compact end @@ -104,34 +104,34 @@ def serialize(for_logging) def to_hash_without_stable_id() hash = {} if @user_id != nil - hash['userID'] = @user_id + hash[:userID] = @user_id end if @email != nil - hash['email'] = @email + hash[:email] = @email end if @ip != nil - hash['ip'] = @ip + hash[:ip] = @ip end if @user_agent != nil - hash['userAgent'] = @user_agent + hash[:userAgent] = @user_agent end if @country != nil - hash['country'] = @country + hash[:country] = @country end if @locale != nil - hash['locale'] = @locale + hash[:locale] = @locale end if @app_version != nil - hash['appVersion'] = @app_version + hash[:appVersion] = @app_version end if @custom != nil - hash['custom'] = Statsig::HashUtils.sortHash(@custom) + hash[:custom] = Statsig::HashUtils.sortHash(@custom) end if @statsig_environment != nil - hash['statsigEnvironment'] = @statsig_environment.clone.sort_by { |key| key }.to_h + hash[:statsigEnvironment] = @statsig_environment.clone.sort_by { |key| key }.to_h end if @private_attributes != nil - hash['privateAttributes'] = Statsig::HashUtils.sortHash(@private_attributes) + hash[:privateAttributes] = Statsig::HashUtils.sortHash(@private_attributes) end custom_ids = {} if @custom_ids != nil @@ -140,32 +140,12 @@ def to_hash_without_stable_id() custom_ids.delete("stableID") end end - hash['customIDs'] = custom_ids.sort_by { |key| key }.to_h + hash[:customIDs] = custom_ids.sort_by { |key| key }.to_h return Statsig::HashUtils.djb2ForHash(hash.sort_by { |key| key }.to_h) end - def value_lookup - { - 'userID' => @user_id, - 'userid' => @user_id, - 'user_id' => @user_id, - 'email' => @email, - 'ip' => @ip, - 'userAgent' => @user_agent, - 'useragent' => @user_agent, - 'user_agent' => @user_agent, - 'country' => @country, - 'locale' => @locale, - 'appVersion' => @app_version, - 'appversion' => @app_version, - 'app_version' => @app_version, - 'custom' => @custom, - 'privateAttributes' => @private_attributes, - } - end - def get_unit_id(id_type) - if id_type.is_a?(String) && id_type.downcase != 'userid' + if id_type.is_a?(String) && id_type != 'userID' return nil unless @custom_ids.is_a? Hash return @custom_ids[id_type] || @custom_ids[id_type.downcase] diff --git a/test/dynamic_config_test.rb b/test/dynamic_config_test.rb index 8cdd01c..17f10d3 100644 --- a/test/dynamic_config_test.rb +++ b/test/dynamic_config_test.rb @@ -16,8 +16,8 @@ def setup "number" => 2, "string" => 'string', "object" => { - key: 'value', - key2: 123, + "key": 'value', + "key2": 123, }, "boolStr1" => 'true', "boolStr2" => 'FALSE', @@ -33,8 +33,8 @@ def test_typed_getter assert(@config.get_typed('number', 0) == 2) assert(@config.get_typed('string', 'default') == 'string') assert(@config.get_typed("object", {}) == { - key: 'value', - key2: 123, + "key" => 'value', + "key2" => 123, }) assert(@config.get_typed("arr", []) == [1, 2, 'three']) @@ -51,18 +51,17 @@ def test_getter assert(@config.get('number', 0) == 2) assert(@config.get('string', 'default') == 'string') assert(@config.get("object", {}) == { - key: 'value', - key2: 123, + "key" => 'value', + "key2" => 123, }) assert(@config.get("arr", []) == [1, 2, 'three']) - assert(@config.get("bool", "string") == true) assert(@config.get("number", "string") == 2) assert(@config.get("string", 6) == 'string') assert(@config.get("numberStr2", 3.3) == '3.3') assert(@config.get("object", "string") == { - key: 'value', - key2: 123, + "key" => 'value', + "key2" => 123, }) assert(@config.get("arr", 12) == [1, 2, 'three']) end diff --git a/test/layer_exposure_test.rb b/test/layer_exposure_test.rb index e8c55d6..0868ff3 100644 --- a/test/layer_exposure_test.rb +++ b/test/layer_exposure_test.rb @@ -143,12 +143,12 @@ def test_logs_user_and_event_name :post, 'https://statsigapi.net/v1/log_event', :body => hash_including( - 'events' => [ + :events => [ hash_including( - 'eventName' => 'statsig::layer_exposure', - 'user' => { - 'userID' => 'dloomb', - 'email' => 'dan@loomb.com', + :eventName => 'statsig::layer_exposure', + :user => { + :userID => 'dloomb', + :email => 'dan@loomb.com', }, ), ]), diff --git a/test/layer_test.rb b/test/layer_test.rb index f61ab00..c855b9d 100644 --- a/test/layer_test.rb +++ b/test/layer_test.rb @@ -32,8 +32,8 @@ def test_typed_getter assert(@layer.get_typed('number', 0) == 2) assert(@layer.get_typed('string', 'default') == 'string') assert(@layer.get_typed("object", {}) == { - key: 'value', - key2: 123, + "key" => 'value', + "key2" => 123, }) assert(@layer.get_typed("arr", []) == [1, 2, 'three']) @@ -50,8 +50,8 @@ def test_getter assert(@layer.get('number', 0) == 2) assert(@layer.get('string', 'default') == 'string') assert(@layer.get("object", {}) == { - key: 'value', - key2: 123, + "key" => 'value', + "key2" => 123, }) assert(@layer.get("arr", []) == [1, 2, 'three']) @@ -60,8 +60,8 @@ def test_getter assert(@layer.get("string", 6) == 'string') assert(@layer.get("numberStr2", 3.3) == '3.3') assert(@layer.get("object", "string") == { - key: 'value', - key2: 123, + "key" => 'value', + "key2" => 123, }) assert(@layer.get("arr", 12) == [1, 2, 'three']) end diff --git a/test/manual_exposure_test.rb b/test/manual_exposure_test.rb index 4c5ed80..01ef51d 100644 --- a/test/manual_exposure_test.rb +++ b/test/manual_exposure_test.rb @@ -83,23 +83,23 @@ def test_manual_exposure_logging assert_equal(4, events.size) gate_exposure = events[0] - assert_equal('statsig::gate_exposure', gate_exposure['eventName']) - assert_equal('always_on_gate', gate_exposure['metadata']['gate']) - assert_equal('true', gate_exposure['metadata']['isManualExposure']) + assert_equal('statsig::gate_exposure', gate_exposure[:eventName]) + assert_equal('always_on_gate', gate_exposure[:metadata][:gate]) + assert_equal('true', gate_exposure[:metadata][:isManualExposure]) config_exposure = events[1] - assert_equal('statsig::config_exposure', config_exposure['eventName']) - assert_equal('test_config', config_exposure['metadata']['config']) - assert_equal('true', config_exposure['metadata']['isManualExposure']) + assert_equal('statsig::config_exposure', config_exposure[:eventName]) + assert_equal('test_config', config_exposure[:metadata][:config]) + assert_equal('true', config_exposure[:metadata][:isManualExposure]) experiment_exposure = events[2] - assert_equal('statsig::config_exposure', experiment_exposure['eventName']) - assert_equal('sample_experiment', experiment_exposure['metadata']['config']) - assert_equal('true', experiment_exposure['metadata']['isManualExposure']) + assert_equal('statsig::config_exposure', experiment_exposure[:eventName]) + assert_equal('sample_experiment', experiment_exposure[:metadata][:config]) + assert_equal('true', experiment_exposure[:metadata][:isManualExposure]) layer_exposure = events[3] - assert_equal('statsig::layer_exposure', layer_exposure['eventName']) - assert_equal('a_layer', layer_exposure['metadata']['config']) - assert_equal('true', layer_exposure['metadata']['isManualExposure']) + assert_equal('statsig::layer_exposure', layer_exposure[:eventName]) + assert_equal('a_layer', layer_exposure[:metadata][:config]) + assert_equal('true', layer_exposure[:metadata][:isManualExposure]) end end \ No newline at end of file diff --git a/test/test_diagnostics.rb b/test/test_diagnostics.rb index 2fdc855..8246ba8 100644 --- a/test/test_diagnostics.rb +++ b/test/test_diagnostics.rb @@ -30,7 +30,7 @@ def setup @events = [] stub_request(:post, 'https://statsigapi.net/v1/log_event').to_return(status: 200, body: lambda { |request| - @events.push(*JSON.parse(request.body)['events']) + @events.push(*JSON.parse(request.body)["events"]) return '' }) end @@ -261,7 +261,6 @@ def test_diagnostics_sampling driver.manually_sync_rulesets end logger.flush - assert( @events.length < 10 && @events.length.positive?, "Expected between 0 and 10 events, received #{@events.length}" diff --git a/test/test_logging.rb b/test/test_logging.rb index d452a05..0565fc9 100644 --- a/test/test_logging.rb +++ b/test/test_logging.rb @@ -117,7 +117,7 @@ def test_exposure_event 'ruleID' => 'another_rule_id' }], unrecognized_eval, - { 'is_manual_exposure' => true }, + { :is_manual_exposure => true }, ) logger.log_config_exposure( @@ -130,7 +130,7 @@ def test_exposure_event 'ruleID' => 'another_rule_id_2' }], override_eval, - { 'is_manual_exposure' => false }, + { :is_manual_exposure => false }, ) logger.log_layer_exposure( @@ -150,7 +150,7 @@ def test_exposure_event assert_instance_of(Array, events) assert_equal(3, events.size) - gate_exposure = events[0] + gate_exposure = JSON.parse(JSON.generate(events[0])) assert(gate_exposure['eventName'] == 'statsig::gate_exposure') assert_equal( { @@ -172,7 +172,7 @@ def test_exposure_event 'ruleID' => 'another_rule_id' }], gate_exposure['secondaryExposures']) - config_exposure = events[1] + config_exposure = JSON.parse(JSON.generate(events[1])) assert(config_exposure['eventName'] == 'statsig::config_exposure') assert_equal( { @@ -192,7 +192,7 @@ def test_exposure_event }], config_exposure['secondaryExposures']) - layer_exposure = events[2] + layer_exposure = JSON.parse(JSON.generate(events[2])) assert_equal('statsig::layer_exposure', layer_exposure['eventName']) assert_equal( { diff --git a/test/test_symbol_hashes.rb b/test/test_symbol_hashes.rb index 99fe450..d5d6e6e 100644 --- a/test/test_symbol_hashes.rb +++ b/test/test_symbol_hashes.rb @@ -42,7 +42,8 @@ def test_fails_when_just_user_id end def test_passes_from_private_attributes - result = Statsig.check_gate(StatsigUser.new({ :userID => "this_user_fails", :private_attributes => { :email => "a@statsig.com" } }), "a_gate") + user = StatsigUser.new({ :userID => "this_user_fails", :private_attributes => { :email => "a@statsig.com" } }) + result = Statsig.check_gate(user, "a_gate") assert_equal(true, result) end From 0658ab746fcc2b9b718abf220273772797ef8bde Mon Sep 17 00:00:00 2001 From: sroyal-statsig <76536058+sroyal-statsig@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:24:07 -0800 Subject: [PATCH 03/16] Setup Get All Evals (#273) --- lib/evaluator.rb | 26 +++++++++++++++++++++++++- lib/statsig.rb | 15 ++++++++++++++- lib/statsig_driver.rb | 10 ++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/evaluator.rb b/lib/evaluator.rb index a6995cc..2fa79af 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -185,6 +185,30 @@ def get_client_initialize_response(user, hash, client_sdk_key) } end + def get_all_evaluations(user) + if @spec_store.is_ready_for_checks == false + return nil + end + + formatter = ClientInitializeHelpers::ResponseFormatter.new(self, user, 'none', nil) + + { + feature_gates: formatter.get_responses(:gates), + dynamic_configs: => formatter.get_responses(:configs), + layer_configs: => formatter.get_responses(:layers), + } + end + + def clean_exposures(exposures) + seen = {} + exposures.reject do |exposure| + key = "#{exposure["gate"]}|#{exposure["gateValue"]}|#{exposure["ruleID"]}}" + should_reject = seen[key] + seen[key] = true + should_reject == true + end + end + def shutdown @spec_store.shutdown end @@ -540,4 +564,4 @@ def compute_user_hash(user_hash) Digest::SHA256.digest(user_hash).unpack('Q>')[0] end end -end \ No newline at end of file +end diff --git a/lib/statsig.rb b/lib/statsig.rb index f816403..5431e56 100644 --- a/lib/statsig.rb +++ b/lib/statsig.rb @@ -319,6 +319,19 @@ def self.get_client_initialize_response(user, hash: 'sha256', client_sdk_key: ni @shared_instance&.get_client_initialize_response(user, hash, client_sdk_key) end + # sig { params(user: StatsigUser).returns(T.any(T::Hash[String, T.untyped], NilClass)) } + ## + # Gets all evaluated values for the given user. + # + # @param user A StatsigUser object used for the evaluation + # + # @note See Ruby Documentation: https://docs.statsig.com/server/rubySDK) + def self.get_all_evaluations(user) + ensure_initialized + @shared_instance&.get_all_evaluations(user) + end + + # sig { returns(T::Hash[String, String]) } ## # Internal Statsig metadata for this SDK @@ -363,4 +376,4 @@ def self.bind_sorbet_loggers(options) return end -end \ No newline at end of file +end diff --git a/lib/statsig_driver.rb b/lib/statsig_driver.rb index a3d8632..d7de6c3 100644 --- a/lib/statsig_driver.rb +++ b/lib/statsig_driver.rb @@ -266,6 +266,16 @@ def get_client_initialize_response(user, hash, client_sdk_key) }, recover: -> { nil }, caller: __method__.to_s) end + # @param [StatsigUser] user + # @return [Hash] + def get_all_evaluations(user) + @err_boundary.capture(task: lambda { + validate_user(user) + normalize_user(user) + @evaluator.get_all_evaluations(user) + }, recover: -> { nil }, caller: __method__.to_s) + end + def maybe_restart_background_threads if @options.local_mode return From d545fcca13ca72c906e12f9e08ba4028b50ba829 Mon Sep 17 00:00:00 2001 From: Stephen Royal Date: Fri, 19 Jan 2024 15:27:57 -0800 Subject: [PATCH 04/16] update --- lib/evaluator.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 2fa79af..0fc80bf 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -193,9 +193,9 @@ def get_all_evaluations(user) formatter = ClientInitializeHelpers::ResponseFormatter.new(self, user, 'none', nil) { - feature_gates: formatter.get_responses(:gates), - dynamic_configs: => formatter.get_responses(:configs), - layer_configs: => formatter.get_responses(:layers), + feature_gates: formatter.get_responses(@spec_store.gates), + dynamic_configs: formatter.get_responses(@spec_store.configs), + layer_configs: formatter.get_responses(@spec_store.layers), } end From 9eba87c069b36aabe6c95776d46fd1c1e6e64de6 Mon Sep 17 00:00:00 2001 From: sroyal-statsig <76536058+sroyal-statsig@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:31:53 -0800 Subject: [PATCH 05/16] Clean up client Init Helper (#277) --- lib/client_initialize_helpers.rb | 93 ++++++++++++++------------------ lib/evaluator.rb | 30 +++++------ 2 files changed, 52 insertions(+), 71 deletions(-) diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index f716278..a380523 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -4,90 +4,75 @@ # require 'sorbet-runtime' -module ClientInitializeHelpers +module Statsig class ResponseFormatter # extend T::Sig - def initialize(evaluator, user, hash, client_sdk_key) - @evaluator = evaluator - @user = user - @hash = hash - @client_sdk_key = client_sdk_key - end - - def get_responses(entities) + def self.get_responses(entities, evaluator, user, client_sdk_key, hash) entities - .map { |name, spec| to_response(name, spec) } + .map { |name, spec| to_response(name, spec, evaluator, user, client_sdk_key, hash) } .delete_if { |v| v.nil? }.to_h end - private - - # sig { params(secondary_exposures: T::Array[T::Hash[String, String]]).returns(T::Array[T::Hash[String, String]]) } - def filter_segments_from_secondary_exposures(secondary_exposures) - secondary_exposures.reject do |exposure| - exposure['gate'].to_s.start_with?('segment:') - end - end - - def to_response(config_name, config_spec) - target_app_id = @evaluator.spec_store.get_app_id_for_sdk_key(@client_sdk_key) + def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash) + target_app_id = evaluator.spec_store.get_app_id_for_sdk_key(client_sdk_key) config_target_apps = config_spec[:targetAppIDs] unless target_app_id.nil? || (!config_target_apps.nil? && config_target_apps.include?(target_app_id)) return nil end - eval_result = @evaluator.eval_spec(@user, config_spec) - if eval_result.nil? + category = config_spec[:type] + entity_type = config_spec[:entity] + if entity_type == 'segment' || entity_type == 'holdout' return nil end - category = config_spec[:type] - entity_type = config_spec[:entity] + eval_result = evaluator.eval_spec(user, config_spec) + if eval_result.nil? + return nil + end result = {} case category - when 'feature_gate' - if entity_type == 'segment' || entity_type == 'holdout' - return nil - end - - result['value'] = eval_result.gate_value - result["group_name"] = eval_result.group_name - result["id_type"] = eval_result.id_type - when 'dynamic_config' + when :feature_gate + result[:value] = eval_result.gate_value + result[:group_name] = eval_result.group_name + result[:id_type] = eval_result.id_type + when :dynamic_config id_type = config_spec[:idType] - result['value'] = eval_result.json_value - result["group"] = eval_result.rule_id - result["group_name"] = eval_result.group_name - result["id_type"] = eval_result.id_type - result["is_device_based"] = id_type.is_a?(String) && id_type.downcase == 'stableid' + result[:value] = eval_result.json_value + result[:group] = eval_result.rule_id + result[:group_name] = eval_result.group_name + result[:id_type] = eval_result.id_type + result[:is_device_based] = id_type.is_a?(String) && id_type.downcase == 'stableid' else return nil end if entity_type == 'experiment' - populate_experiment_fields(config_name, config_spec, eval_result, result) + populate_experiment_fields(config_name, config_spec, eval_result, result, evaluator) end if entity_type == 'layer' - populate_layer_fields(config_spec, eval_result, result) + populate_layer_fields(config_spec, eval_result, result, evaluator, user) result.delete(:id_type) # not exposed for layer configs in /initialize end - hashed_name = hash_name(config_name) - [hashed_name, result.merge( + hashed_name = hash_name(config_name, hash) + result.merge( { :name => hashed_name, :rule_id => eval_result.rule_id, :secondary_exposures => clean_exposures(eval_result.secondary_exposures) - }).compact] + }).compact end - def clean_exposures(exposures) + private + + def self.clean_exposures(exposures) seen = {} exposures.reject do |exposure| key = "#{exposure[:gate]}|#{exposure[:gateValue]}|#{exposure[:ruleID]}}" @@ -97,7 +82,7 @@ def clean_exposures(exposures) end end - def populate_experiment_fields(config_name, config_spec, eval_result, result) + def self.populate_experiment_fields(config_name, config_spec, eval_result, result, evaluator) result[:is_user_in_experiment] = eval_result.is_experiment_group result[:is_experiment_active] = config_spec[:isActive] == true @@ -108,22 +93,22 @@ def populate_experiment_fields(config_name, config_spec, eval_result, result) result[:is_in_layer] = true result[:explicit_parameters] = config_spec[:explicitParameters] || [] - layer_name = @evaluator.spec_store.experiment_to_layer[config_name] - if layer_name.nil? || @evaluator.spec_store.layers[layer_name].nil? + layer_name = evaluator.spec_store.experiment_to_layer[config_name] + if layer_name.nil? || evaluator.spec_store.layers[layer_name].nil? return end - layer = @evaluator.spec_store.layers[layer_name] + layer = evaluator.spec_store.layers[layer_name] result[:value] = layer[:defaultValue].merge(result[:value]) end - def populate_layer_fields(config_spec, eval_result, result) + def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user) delegate = eval_result.config_delegate result[:explicit_parameters] = config_spec[:explicitParameters] || [] if delegate.nil? == false && delegate.empty? == false - delegate_spec = @evaluator.spec_store.configs[delegate] - delegate_result = @evaluator.eval_spec(@user, delegate_spec) + delegate_spec = evaluator.spec_store.configs[delegate] + delegate_result = evaluator.eval_spec(user, delegate_spec) result[:allocated_experiment_name] = hash_name(delegate) result[:is_user_in_experiment] = delegate_result.is_experiment_group @@ -134,8 +119,8 @@ def populate_layer_fields(config_spec, eval_result, result) result[:undelegated_secondary_exposures] = clean_exposures(eval_result.undelegated_sec_exps || []) end - def hash_name(name) - case @hash + def self.hash_name(name, hash) + case hash when 'none' return name when 'sha256' diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 0fc80bf..af15b35 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -160,8 +160,6 @@ def get_client_initialize_response(user, hash, client_sdk_key) return nil end - formatter = ClientInitializeHelpers::ResponseFormatter.new(self, user, hash, client_sdk_key) - evaluated_keys = {} if user.user_id.nil? == false evaluated_keys[:userID] = user.user_id @@ -172,16 +170,16 @@ def get_client_initialize_response(user, hash, client_sdk_key) end { - 'feature_gates' => formatter.get_responses(@spec_store.gates), - 'dynamic_configs' => formatter.get_responses(@spec_store.configs), - 'layer_configs' => formatter.get_responses(@spec_store.layers), - 'sdkParams' => {}, - 'has_updates' => true, - 'generator' => 'statsig-ruby-sdk', - 'evaluated_keys' => evaluated_keys, - 'time' => 0, - 'hash_used' => hash, - 'user_hash' => user.to_hash_without_stable_id() + feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, hash, client_sdk_key), + dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, hash, client_sdk_key), + layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, hash, client_sdk_key), + sdkParams: {}, + has_updates: true, + generator: 'statsig-ruby-sdk', + evaluated_keys: evaluated_keys, + time: 0, + hash_used: hash, + user_hash: user.to_hash_without_stable_id() } end @@ -190,12 +188,10 @@ def get_all_evaluations(user) return nil end - formatter = ClientInitializeHelpers::ResponseFormatter.new(self, user, 'none', nil) - { - feature_gates: formatter.get_responses(@spec_store.gates), - dynamic_configs: formatter.get_responses(@spec_store.configs), - layer_configs: formatter.get_responses(@spec_store.layers), + feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, nil, 'none'), + dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, nil, 'none'), + layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, nil, 'none'), } end From fb62326c5e76b16738f866cf8cc4c0a8b5b59fd6 Mon Sep 17 00:00:00 2001 From: Daniel Loomb Date: Mon, 22 Jan 2024 10:42:00 -0800 Subject: [PATCH 06/16] Update client_initialize_helpers.rb --- lib/client_initialize_helpers.rb | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index a380523..3b11ac8 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -8,13 +8,13 @@ module Statsig class ResponseFormatter # extend T::Sig - def self.get_responses(entities, evaluator, user, client_sdk_key, hash) + def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) entities - .map { |name, spec| to_response(name, spec, evaluator, user, client_sdk_key, hash) } + .map { |name, spec| to_response(name, spec, evaluator, user, client_sdk_key, hash_algo) } .delete_if { |v| v.nil? }.to_h end - def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash) + def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash_algo) target_app_id = evaluator.spec_store.get_app_id_for_sdk_key(client_sdk_key) config_target_apps = config_spec[:targetAppIDs] @@ -57,17 +57,17 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, end if entity_type == 'layer' - populate_layer_fields(config_spec, eval_result, result, evaluator, user) + populate_layer_fields(config_spec, eval_result, result, evaluator, user, hash_algo) result.delete(:id_type) # not exposed for layer configs in /initialize end - hashed_name = hash_name(config_name, hash) - result.merge( - { - :name => hashed_name, - :rule_id => eval_result.rule_id, - :secondary_exposures => clean_exposures(eval_result.secondary_exposures) - }).compact + hashed_name = hash_name(config_name, hash_algo) + + result[:name] = hashed_name + result[:rule_id] = eval_result.rule_id + result[:secondary_exposures] = clean_exposures(eval_result.secondary_exposures) + + [hashed_name, result] end private @@ -102,7 +102,7 @@ def self.populate_experiment_fields(config_name, config_spec, eval_result, resul result[:value] = layer[:defaultValue].merge(result[:value]) end - def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user) + def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user, hash_algo) delegate = eval_result.config_delegate result[:explicit_parameters] = config_spec[:explicitParameters] || [] @@ -110,7 +110,7 @@ def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user delegate_spec = evaluator.spec_store.configs[delegate] delegate_result = evaluator.eval_spec(user, delegate_spec) - result[:allocated_experiment_name] = hash_name(delegate) + result[:allocated_experiment_name] = hash_name(delegate, hash_algo) result[:is_user_in_experiment] = delegate_result.is_experiment_group result[:is_experiment_active] = delegate_spec[:isActive] == true result[:explicit_parameters] = delegate_spec[:explicitParameters] || [] @@ -119,8 +119,8 @@ def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user result[:undelegated_secondary_exposures] = clean_exposures(eval_result.undelegated_sec_exps || []) end - def self.hash_name(name, hash) - case hash + def self.hash_name(name, hash_algo) + case hash_algo when 'none' return name when 'sha256' From 38726a1e45103653146d5ed96100e8464888637d Mon Sep 17 00:00:00 2001 From: Daniel <95646168+daniel-statsig@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:49:05 -0800 Subject: [PATCH 07/16] Remove all Sorbet comments. Update classes to not use Sorbet (#283) --- lib/client_initialize_helpers.rb | 5 - lib/config_result.rb | 8 -- lib/diagnostics.rb | 37 +----- lib/dynamic_config.rb | 23 ---- lib/error_boundary.rb | 5 - lib/evaluation_details.rb | 1 - lib/evaluator.rb | 49 +++----- lib/feature_gate.rb | 24 ---- lib/layer.rb | 19 --- lib/network.rb | 29 +---- lib/statsig.rb | 182 +++++++++++---------------- lib/statsig_driver.rb | 62 +++------ lib/statsig_options.rb | 50 -------- lib/statsig_user.rb | 25 +--- lib/uri_helper.rb | 8 -- lib/user_persistent_storage_utils.rb | 17 --- test/data_adapter_test.rb | 2 - test/statsig_e2e_test.rb | 2 - test/test_helper.rb | 2 - 19 files changed, 110 insertions(+), 440 deletions(-) diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index 3b11ac8..fe1b1e2 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -1,12 +1,7 @@ - - require_relative 'hash_utils' -# require 'sorbet-runtime' - module Statsig class ResponseFormatter - # extend T::Sig def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) entities diff --git a/lib/config_result.rb b/lib/config_result.rb index 381f61b..e027e75 100644 --- a/lib/config_result.rb +++ b/lib/config_result.rb @@ -1,10 +1,5 @@ - - -# require 'sorbet-runtime' - module Statsig class ConfigResult - # extend T::Sig attr_accessor :name attr_accessor :gate_value @@ -48,7 +43,6 @@ def initialize( @target_app_ids = target_app_ids end - # sig { params(config_name: String, user_persisted_values: UserPersistedValues).returns(T.nilable(ConfigResult)) } def self.from_user_persisted_values(config_name, user_persisted_values) sticky_values = user_persisted_values[config_name] return nil if sticky_values.nil? @@ -56,7 +50,6 @@ def self.from_user_persisted_values(config_name, user_persisted_values) from_hash(config_name, sticky_values) end - # sig { params(config_name: String, hash: Hash).returns(ConfigResult) } def self.from_hash(config_name, hash) new( config_name, @@ -71,7 +64,6 @@ def self.from_hash(config_name, hash) ) end - # sig { returns(Hash) } def to_hash { json_value: @json_value, diff --git a/lib/diagnostics.rb b/lib/diagnostics.rb index 7a356bb..8805cd8 100644 --- a/lib/diagnostics.rb +++ b/lib/diagnostics.rb @@ -1,18 +1,10 @@ - - -# require 'sorbet-runtime' - module Statsig class Diagnostics - # extend T::Sig - # sig { returns(String) } attr_accessor :context - # sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) } attr_reader :markers - # sig { returns(T::Hash[String, Numeric]) } attr_accessor :sample_rates def initialize(context) @@ -21,15 +13,6 @@ def initialize(context) @sample_rates = {} end - # sig do - # params( - # key: String, - # action: String, - # step: T.any(String, NilClass), - # tags: T::Hash[Symbol, T.untyped] - # ).void - # end - def mark(key, action, step, tags) marker = { key: key, @@ -47,21 +30,12 @@ def mark(key, action, step, tags) @markers.push(marker) end - # sig do - # params( - # key: String, - # step: T.any(String, NilClass), - # tags: T::Hash[Symbol, T.untyped] - # ).returns(Tracker) - # end def track(key, step = nil, tags = {}) tracker = Tracker.new(self, key, step, tags) tracker.start(**tags) tracker end - # sig { returns(T::Hash[Symbol, T.untyped]) } - def serialize { context: @context.clone, @@ -101,16 +75,7 @@ class Context API_CALL_KEYS = %w[check_gate get_config get_experiment get_layer].freeze class Tracker - # extend T::Sig - - # sig do - # params( - # diagnostics: Diagnostics, - # key: String, - # step: T.any(String, NilClass), - # tags: T::Hash[Symbol, T.untyped] - # ).void - # end + def initialize(diagnostics, key, step, tags = {}) @diagnostics = diagnostics @key = key diff --git a/lib/dynamic_config.rb b/lib/dynamic_config.rb index 17c363c..e4f425f 100644 --- a/lib/dynamic_config.rb +++ b/lib/dynamic_config.rb @@ -1,7 +1,3 @@ - - -# require 'sorbet-runtime' - ## # Contains the current experiment/dynamic config values from Statsig # @@ -9,36 +5,19 @@ # # Experiments Documentation: https://docs.statsig.com/experiments-plus class DynamicConfig - # extend T::Sig - # sig { returns(String) } attr_accessor :name - # sig { returns(T::Hash[String, T.untyped]) } attr_accessor :value - # sig { returns(String) } attr_accessor :rule_id - # sig { returns(T.nilable(String)) } attr_accessor :group_name - # sig { returns(String) } attr_accessor :id_type - # sig { returns(T.nilable(Statsig::EvaluationDetails)) } attr_accessor :evaluation_details - # sig do - # params( - # name: String, - # value: T::Hash[String, T.untyped], - # rule_id: String, - # group_name: T.nilable(String), - # id_type: String, - # evaluation_details: T.nilable(Statsig::EvaluationDetails) - # ).void - # end def initialize(name, value = {}, rule_id = '', group_name = nil, id_type = '', evaluation_details = nil) @name = name @value = JSON.parse(JSON.generate(value)) @@ -48,7 +27,6 @@ def initialize(name, value = {}, rule_id = '', group_name = nil, id_type = '', e @evaluation_details = evaluation_details end - # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found. # @@ -59,7 +37,6 @@ def get(index, default_value) @value[index] end - # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found # or is found to have a different type from the default_value. diff --git a/lib/error_boundary.rb b/lib/error_boundary.rb index 45e4de7..f94bb67 100644 --- a/lib/error_boundary.rb +++ b/lib/error_boundary.rb @@ -1,15 +1,10 @@ - - require 'statsig_errors' -# require 'sorbet-runtime' $endpoint = 'https://statsigapi.net/v1/sdk_exception' module Statsig class ErrorBoundary - # extend T::Sig - # sig { params(sdk_key: String).void } def initialize(sdk_key) @sdk_key = sdk_key @seen = Set.new diff --git a/lib/evaluation_details.rb b/lib/evaluation_details.rb index b20bda2..187daa6 100644 --- a/lib/evaluation_details.rb +++ b/lib/evaluation_details.rb @@ -1,4 +1,3 @@ - module Statsig module EvaluationReason diff --git a/lib/evaluator.rb b/lib/evaluator.rb index af15b35..5690885 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -1,6 +1,3 @@ - - -# require 'sorbet-runtime' require 'config_result' require 'country_lookup' require 'digest' @@ -15,25 +12,15 @@ module Statsig class Evaluator - # extend T::Sig UNSUPPORTED_EVALUATION = :unsupported_eval attr_accessor :spec_store - # sig { returns(StatsigOptions) } attr_accessor :options - # sig { returns(UserPersistentStorageUtils) } attr_accessor :persistent_storage_utils - # sig do - # params( - # store: SpecStore, - # options: StatsigOptions, - # persistent_storage_utils: UserPersistentStorageUtils, - # ).void - # end def initialize(store, options, persistent_storage_utils) UAParser.initialize_async CountryLookup.initialize_async @@ -70,7 +57,6 @@ def check_gate(user, gate_name) eval_spec(user, @spec_store.get_gate(gate_name)) end - # sig { params(user: StatsigUser, config_name: String, user_persisted_values: T.nilable(UserPersistedValues)).returns(ConfigResult) } def get_config(user, config_name, user_persisted_values: nil) if @config_overrides.key?(config_name) id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)[:idType] : '' @@ -217,7 +203,6 @@ def override_config(config, value) @config_overrides[config] = value end - # sig { params(user: StatsigUser, config: Hash).returns(ConfigResult) } def eval_spec(user, config) default_rule_id = 'default' exposures = [] @@ -480,23 +465,23 @@ def eval_condition(user, condition) def get_value_from_user(user, field) value = case field.downcase - when 'userid', 'user_id' - user.user_id - when 'email' - user.email - when 'ip' - user.ip - when 'useragent', 'user_agent' - user.user_agent - when 'country' - user.country - when 'locale' - user.locale - when 'appversion', 'app_version' - user.app_version - else - nil - end + when 'userid', 'user_id' + user.user_id + when 'email' + user.email + when 'ip' + user.ip + when 'useragent', 'user_agent' + user.user_agent + when 'country' + user.country + when 'locale' + user.locale + when 'appversion', 'app_version' + user.app_version + else + nil + end if value.nil? value = user.custom[field] if user.custom.is_a?(Hash) value = user.custom[field.to_sym] if value.nil? && user.custom.is_a?(Hash) diff --git a/lib/feature_gate.rb b/lib/feature_gate.rb index 1468fd6..f4959de 100644 --- a/lib/feature_gate.rb +++ b/lib/feature_gate.rb @@ -1,42 +1,19 @@ - - -# require 'sorbet-runtime' - class FeatureGate - # extend T::Sig - # sig { returns(String) } attr_accessor :name - # sig { returns(T::Boolean) } attr_accessor :value - # sig { returns(String) } attr_accessor :rule_id - # sig { returns(T.nilable(String)) } attr_accessor :group_name - # sig { returns(String) } attr_accessor :id_type - # sig { returns(T.nilable(Statsig::EvaluationDetails)) } attr_accessor :evaluation_details - # sig { returns(T.nilable(T::Array[String])) } attr_accessor :target_app_ids - # sig do - # params( - # name: String, - # value: T::Boolean, - # rule_id: String, - # group_name: T.nilable(String), - # id_type: String, - # evaluation_details: T.nilable(Statsig::EvaluationDetails), - # target_app_ids: T.nilable(T::Array[String]) - # ).void - # end def initialize( name, value: false, @@ -55,7 +32,6 @@ def initialize( @target_app_ids = target_app_ids end - # sig { params(res: Statsig::ConfigResult).returns(FeatureGate) } def self.from_config_result(res) new( res.name, diff --git a/lib/layer.rb b/lib/layer.rb index 2eb1b4c..e7e528f 100644 --- a/lib/layer.rb +++ b/lib/layer.rb @@ -1,6 +1,3 @@ - - -# require 'sorbet-runtime' ## # Contains the current values from Statsig. # Will contain layer default values for all shared parameters in that layer. @@ -9,27 +6,13 @@ # # Layers Documentation: https://docs.statsig.com/layers class Layer - # extend T::Sig - # sig { returns(String) } attr_accessor :name - # sig { returns(String) } attr_accessor :rule_id - # sig { returns(String) } attr_accessor :group_name - # sig do - # params( - # name: String, - # value: T::Hash[String, T.untyped], - # rule_id: String, - # group_name: T.nilable(String), - # allocated_experiment: T.nilable(String), - # exposure_log_func: T.any(Method, Proc, NilClass) - # ).void - # end def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_experiment = nil, exposure_log_func = nil) @name = name @value = JSON.parse(JSON.generate(value)) @@ -39,7 +22,6 @@ def initialize(name, value = {}, rule_id = '', group_name = nil, allocated_exper @exposure_log_func = exposure_log_func end - # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found. # @@ -55,7 +37,6 @@ def get(index, default_value) @value[index] end - # sig { params(index: String, default_value: T.untyped).returns(T.untyped) } ## # Get the value for the given key (index), falling back to the default_value if it cannot be found # or is found to have a different type from the default_value. diff --git a/lib/network.rb b/lib/network.rb index ae0563a..66d8353 100644 --- a/lib/network.rb +++ b/lib/network.rb @@ -1,9 +1,7 @@ - - require 'http' require 'json' require 'securerandom' -# require 'sorbet-runtime' + require 'uri_helper' require 'connection_pool' @@ -20,9 +18,7 @@ def initialize(msg = nil, http_code = nil) end class Network - # extend T::Sig - # sig { params(server_secret: String, options: StatsigOptions, backoff_mult: Integer).void } def initialize(server_secret, options, backoff_mult = 10) super() URIHelper.initialize(options) @@ -54,41 +50,18 @@ def initialize(server_secret, options, backoff_mult = 10) end end - # sig do - # params(since_time: Integer) - # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - # end def download_config_specs(since_time) get("download_config_specs/#{@server_secret}.json?sinceTime=#{since_time}") end - # class HttpMethod < T::Enum - # enums do - # GET = new - # POST = new - # end - # end - - # sig do - # params(endpoint: String, retries: Integer, backoff: Integer) - # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - # end def get(endpoint, retries = 0, backoff = 1) request(:GET, endpoint, nil, retries, backoff) end - # sig do - # params(endpoint: String, body: String, retries: Integer, backoff: Integer) - # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - # end def post(endpoint, body, retries = 0, backoff = 1) request(:POST, endpoint, body, retries, backoff) end - # sig do - # params(method: HttpMethod, endpoint: String, body: T.nilable(String), retries: Integer, backoff: Integer) - # .returns([T.any(HTTP::Response, NilClass), T.any(StandardError, NilClass)]) - # end def request(method, endpoint, body, retries = 0, backoff = 1) if @local_mode return nil, nil diff --git a/lib/statsig.rb b/lib/statsig.rb index 5431e56..e1f7331 100644 --- a/lib/statsig.rb +++ b/lib/statsig.rb @@ -1,11 +1,9 @@ require 'statsig_driver' -# require 'sorbet-runtime' + require 'statsig_errors' module Statsig - # extend T::Sig - # sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void } ## # Initializes the Statsig SDK. # @@ -19,45 +17,50 @@ def self.initialize(secret_key, options = nil, error_callback = nil) return @shared_instance end - self.bind_sorbet_loggers(options) - @shared_instance = StatsigDriver.new(secret_key, options, error_callback) end - # class GetGateOptions < T::Struct - # prop :disable_log_exposure, T::Boolean, default: false - # prop :skip_evaluation, T::Boolean, default: false - # end + class GetGateOptions + attr_accessor :disable_log_exposure, :skip_evaluation + + def initialize(disable_log_exposure: false, skip_evaluation: false) + @disable_log_exposure = disable_log_exposure + @skip_evaluation = skip_evaluation + end + end - # sig { params(user: StatsigUser, gate_name: String, options: GetGateOptions).returns(FeatureGate) } ## # Gets the gate, evaluated against the given user. An exposure event will automatically be logged for the gate. # - # @param user A StatsigUser object used for the evaluation - # @param gate_name The name of the gate being checked - # @param options Additional options for evaluating the gate + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] gate_name The name of the gate being checked + # @param [GetGateOptions] options Additional options for evaluating the gate + # @return [FeatureGate] def self.get_gate(user, gate_name, options) ensure_initialized - @shared_instance&.get_gate(user, gate_name, options) + @shared_instance&.get_gate(user, gate_name, options: options) end - # class CheckGateOptions < T::Struct - # prop :disable_log_exposure, T::Boolean, default: false - # end + class CheckGateOptions + attr_accessor :disable_log_exposure + + def initialize(disable_log_exposure: false) + @disable_log_exposure = disable_log_exposure + end + end - # sig { params(user: StatsigUser, gate_name: String, options: CheckGateOptions).returns(T::Boolean) } ## # Gets the boolean result of a gate, evaluated against the given user. An exposure event will automatically be logged for the gate. # - # @param user A StatsigUser object used for the evaluation - # @param gate_name The name of the gate being checked - # @param options Additional options for evaluating the gate - def self.check_gate(user, gate_name, options) + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] gate_name The name of the gate being checked + # @param [CheckGateOptions] options Additional options for evaluating the gate + # @return [Boolean] + def self.check_gate(user, gate_name, options: nil) ensure_initialized - @shared_instance&.check_gate(user, gate_name, options) + @shared_instance&.check_gate(user, gate_name, options: options) end - # sig { params(user: StatsigUser, gate_name: String).returns(T::Boolean) } ## # Gets the boolean result of a gate, evaluated against the given user. # @@ -65,10 +68,9 @@ def self.check_gate(user, gate_name, options) # @param gate_name The name of the gate being checked def self.check_gate_with_exposure_logging_disabled(user, gate_name) ensure_initialized - @shared_instance&.check_gate(user, gate_name, { disable_log_exposure: true }) + @shared_instance&.check_gate(user, gate_name, options: CheckGateOptions.new(disable_log_exposure: true)) end - # sig { params(user: StatsigUser, gate_name: String).void } ## # Logs an exposure event for the gate # @@ -79,34 +81,37 @@ def self.manually_log_gate_exposure(user, gate_name) @shared_instance&.manually_log_gate_exposure(user, gate_name) end - # class GetConfigOptions < T::Struct - # prop :disable_log_exposure, T::Boolean, default: false - # end + class GetConfigOptions + attr_accessor :disable_log_exposure + + def initialize(disable_log_exposure: false) + @disable_log_exposure = disable_log_exposure + end + end - # sig { params(user: StatsigUser, dynamic_config_name: String, options: GetConfigOptions).returns(DynamicConfig) } ## # Get the values of a dynamic config, evaluated against the given user. An exposure event will automatically be logged for the dynamic config. # - # @param user A StatsigUser object used for the evaluation - # @param dynamic_config_name The name of the dynamic config - # @param options Additional options for evaluating the config - def self.get_config(user, dynamic_config_name, options) + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] dynamic_config_name The name of the dynamic config + # @param [GetConfigOptions] options Additional options for evaluating the config + # @return [DynamicConfig] + def self.get_config(user, dynamic_config_name, options: nil) ensure_initialized - @shared_instance&.get_config(user, dynamic_config_name, options) + @shared_instance&.get_config(user, dynamic_config_name, options: options) end - # sig { params(user: StatsigUser, dynamic_config_name: String).returns(DynamicConfig) } ## # Get the values of a dynamic config, evaluated against the given user. # - # @param user A StatsigUser object used for the evaluation - # @param dynamic_config_name The name of the dynamic config + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] dynamic_config_name The name of the dynamic config + # @return [DynamicConfig] def self.get_config_with_exposure_logging_disabled(user, dynamic_config_name) ensure_initialized - @shared_instance&.get_config(user, dynamic_config_name, {disable_log_exposure: true}) + @shared_instance&.get_config(user, dynamic_config_name, options: GetConfigOptions.new(disable_log_exposure: true)) end - # sig { params(user: StatsigUser, dynamic_config: String).void } ## # Logs an exposure event for the dynamic config # @@ -117,35 +122,36 @@ def self.manually_log_config_exposure(user, dynamic_config) @shared_instance&.manually_log_config_exposure(user, dynamic_config) end - # class GetExperimentOptions < T::Struct - # prop :disable_log_exposure, T::Boolean, default: false - # prop :user_persisted_values, T.nilable(T::Hash[String, Hash]), default: nil - # end + class GetExperimentOptions + attr_accessor :disable_log_exposure, :user_persisted_values + + def initialize(disable_log_exposure: false, user_persisted_values: nil) + @disable_log_exposure = disable_log_exposure + @user_persisted_values = user_persisted_values + end + end - # sig { params(user: StatsigUser, experiment_name: String, options: GetExperimentOptions).returns(DynamicConfig) } ## # Get the values of an experiment, evaluated against the given user. An exposure event will automatically be logged for the experiment. # - # @param user A StatsigUser object used for the evaluation - # @param experiment_name The name of the experiment - # @param options Additional options for evaluating the experiment - def self.get_experiment(user, experiment_name, options) + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] experiment_name The name of the experiment + # @param [GetExperimentOptions] options Additional options for evaluating the experiment + def self.get_experiment(user, experiment_name, options: nil) ensure_initialized - @shared_instance&.get_experiment(user, experiment_name, options) + @shared_instance&.get_experiment(user, experiment_name, options: options) end - # sig { params(user: StatsigUser, experiment_name: String).returns(DynamicConfig) } ## # Get the values of an experiment, evaluated against the given user. # - # @param user A StatsigUser object used for the evaluation - # @param experiment_name The name of the experiment + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] experiment_name The name of the experiment def self.get_experiment_with_exposure_logging_disabled(user, experiment_name) ensure_initialized - @shared_instance&.get_experiment(user, experiment_name, {disable_log_exposure: true}) + @shared_instance&.get_experiment(user, experiment_name, options: GetExperimentOptions.new(disable_log_exposure: true)) end - # sig { params(user: StatsigUser, experiment_name: String).void } ## # Logs an exposure event for the experiment # @@ -156,29 +162,31 @@ def self.manually_log_experiment_exposure(user, experiment_name) @shared_instance&.manually_log_config_exposure(user, experiment_name) end - # sig { params(user: StatsigUser, id_type: String).returns(UserPersistedValues) } def self.get_user_persisted_values(user, id_type) ensure_initialized @shared_instance&.get_user_persisted_values(user, id_type) end - # class GetLayerOptions < T::Struct - # prop :disable_log_exposure, T::Boolean, default: false - # end + class GetLayerOptions + attr_accessor :disable_log_exposure + + def initialize(disable_log_exposure: false) + @disable_log_exposure = disable_log_exposure + end + end - # sig { params(user: StatsigUser, layer_name: String, options: GetLayerOptions).returns(Layer) } ## # Get the values of a layer, evaluated against the given user. # Exposure events will be fired when get or get_typed is called on the resulting Layer class. # - # @param user A StatsigUser object used for the evaluation - # @param layer_name The name of the layer - def self.get_layer(user, layer_name, options = GetLayerOptions.new) + # @param [StatsigUser] user A StatsigUser object used for the evaluation + # @param [String] layer_name The name of the layer + # @param [GetLayerOptions] options Configuration of how this method call should behave + def self.get_layer(user, layer_name, options: nil) ensure_initialized - @shared_instance&.get_layer(user, layer_name, options) + @shared_instance&.get_layer(user, layer_name, options: options) end - # sig { params(user: StatsigUser, layer_name: String).returns(Layer) } ## # Get the values of a layer, evaluated against the given user. # @@ -186,10 +194,9 @@ def self.get_layer(user, layer_name, options = GetLayerOptions.new) # @param layer_name The name of the layer def self.get_layer_with_exposure_logging_disabled(user, layer_name) ensure_initialized - @shared_instance&.get_layer(user, layer_name, GetLayerOptions.new(disable_log_exposure: true)) + @shared_instance&.get_layer(user, layer_name, options: GetLayerOptions.new(disable_log_exposure: true)) end - # sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void } ## # Logs an exposure event for the parameter in the given layer # @@ -201,10 +208,6 @@ def self.manually_log_layer_parameter_exposure(user, layer_name, parameter_name) @shared_instance&.manually_log_layer_parameter_exposure(user, layer_name, parameter_name) end - # sig { params(user: StatsigUser, - # event_name: String, - # value: T.any(String, Integer, Float, NilClass), - # metadata: T.any(T::Hash[String, T.untyped], NilClass)).void } ## # Logs an event to Statsig with the provided values. # @@ -227,7 +230,6 @@ def self.sync_idlists @shared_instance&.manually_sync_idlists end - # sig { returns(T::Array[String]) } ## # Returns a list of all gate names # @@ -236,7 +238,6 @@ def self.list_gates @shared_instance&.list_gates end - # sig { returns(T::Array[String]) } ## # Returns a list of all config names # @@ -245,7 +246,6 @@ def self.list_configs @shared_instance&.list_configs end - # sig { returns(T::Array[String]) } ## # Returns a list of all experiment names # @@ -254,7 +254,6 @@ def self.list_experiments @shared_instance&.list_experiments end - # sig { returns(T::Array[String]) } ## # Returns a list of all autotune names # @@ -263,7 +262,6 @@ def self.list_autotunes @shared_instance&.list_autotunes end - # sig { returns(T::Array[String]) } ## # Returns a list of all layer names # @@ -272,7 +270,6 @@ def self.list_layers @shared_instance&.list_layers end - # sig { void } ## # Stops all Statsig activity and flushes any pending events. def self.shutdown @@ -282,7 +279,6 @@ def self.shutdown @shared_instance = nil end - # sig { params(gate_name: String, gate_value: T::Boolean).void } ## # Sets a value to be returned for the given gate instead of the actual evaluated value. # @@ -293,7 +289,6 @@ def self.override_gate(gate_name, gate_value) @shared_instance&.override_gate(gate_name, gate_value) end - # sig { params(config_name: String, config_value: Hash).void } ## # Sets a value to be returned for the given dynamic config/experiment instead of the actual evaluated value. # @@ -304,7 +299,6 @@ def self.override_config(config_name, config_value) @shared_instance&.override_config(config_name, config_value) end - # sig { params(user: StatsigUser, hash: String, client_sdk_key: T.any(String, NilClass)).returns(T.any(T::Hash[String, T.untyped], NilClass)) } ## # Gets all evaluated values for the given user. # These values can then be given to a Statsig Client SDK via bootstrapping. @@ -319,7 +313,6 @@ def self.get_client_initialize_response(user, hash: 'sha256', client_sdk_key: ni @shared_instance&.get_client_initialize_response(user, hash, client_sdk_key) end - # sig { params(user: StatsigUser).returns(T.any(T::Hash[String, T.untyped], NilClass)) } ## # Gets all evaluated values for the given user. # @@ -331,8 +324,6 @@ def self.get_all_evaluations(user) @shared_instance&.get_all_evaluations(user) end - - # sig { returns(T::Hash[String, String]) } ## # Internal Statsig metadata for this SDK def self.get_statsig_metadata @@ -351,29 +342,4 @@ def self.ensure_initialized end end - # sig { params(options: T.any(StatsigOptions, NilClass)).void } - def self.bind_sorbet_loggers(options) - if options&.disable_sorbet_logging_handlers == true - return - end - - # T::Configuration.call_validation_error_handler = lambda do |signature, opts| - # puts "[Type Error] " + opts[:pretty_message] - # end - # - # T::Configuration.inline_type_error_handler = lambda do |error, opts| - # puts "[Type Error] " + error.message - # end - # - # T::Configuration.sig_builder_error_handler = lambda do |error, location| - # puts "[Type Error] " + error.message - # end - # - # T::Configuration.sig_validation_error_handler = lambda do |error, opts| - # puts "[Type Error] " + error.message - # end - - return - end - end diff --git a/lib/statsig_driver.rb b/lib/statsig_driver.rb index d7de6c3..534ba6a 100644 --- a/lib/statsig_driver.rb +++ b/lib/statsig_driver.rb @@ -1,5 +1,3 @@ - - require 'config_result' require 'evaluator' require 'network' @@ -13,13 +11,11 @@ require 'feature_gate' require 'error_boundary' require 'layer' -# require 'sorbet-runtime' + require 'diagnostics' class StatsigDriver - # extend T::Sig - # sig { params(secret_key: String, options: T.any(StatsigOptions, NilClass), error_callback: T.any(Method, Proc, NilClass)).void } def initialize(secret_key, options = nil, error_callback = nil) unless secret_key.start_with?('secret-') raise Statsig::ValueError.new('Invalid secret key provided. Provide your project secret key from the Statsig console') @@ -47,14 +43,6 @@ def initialize(secret_key, options = nil, error_callback = nil) }, caller: __method__.to_s) end - # sig do - # params( - # user: StatsigUser, - # gate_name: String, - # disable_log_exposure: T::Boolean, - # skip_evaluation: T::Boolean - # ).returns(FeatureGate) - # end def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: false) if skip_evaluation gate = @store.get_gate(gate_name) @@ -76,25 +64,25 @@ def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: FeatureGate.from_config_result(res) end - # sig { params(user: StatsigUser, gate_name: String, options: Statsig::GetGateOptions).returns(FeatureGate) } - def get_gate(user, gate_name, options = Statsig::GetGateOptions.new) + def get_gate(user, gate_name, options: nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { - get_gate_impl(user, gate_name, disable_log_exposure: options.disable_log_exposure, skip_evaluation: options.skip_evaluation) + get_gate_impl(user, gate_name, + disable_log_exposure: options&.disable_log_exposure == true, + skip_evaluation: options&.skip_evaluation == true + ) }, caller: __method__.to_s) }, recover: -> { false }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, gate_name: String, options: Statsig::CheckGateOptions).returns(T::Boolean) } - def check_gate(user, gate_name, options = Statsig::CheckGateOptions.new) + def check_gate(user, gate_name, options: nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { - get_gate_impl(user, gate_name, disable_log_exposure: options.disable_log_exposure).value + get_gate_impl(user, gate_name, disable_log_exposure: options&.disable_log_exposure == true).value }, caller: __method__.to_s) }, recover: -> { false }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, gate_name: String).void } def manually_log_gate_exposure(user, gate_name) @err_boundary.capture(task: lambda { res = @evaluator.check_gate(user, gate_name) @@ -103,27 +91,24 @@ def manually_log_gate_exposure(user, gate_name) }) end - # sig { params(user: StatsigUser, dynamic_config_name: String, options: Statsig::GetConfigOptions).returns(DynamicConfig) } - def get_config(user, dynamic_config_name, options = Statsig::GetConfigOptions.new) + def get_config(user, dynamic_config_name, options: nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { user = verify_inputs(user, dynamic_config_name, "dynamic_config_name") - get_config_impl(user, dynamic_config_name, options.disable_log_exposure) + get_config_impl(user, dynamic_config_name, options&.disable_log_exposure == true) }, caller: __method__.to_s) }, recover: -> { DynamicConfig.new(dynamic_config_name) }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, experiment_name: String, options: Statsig::GetExperimentOptions).returns(DynamicConfig) } - def get_experiment(user, experiment_name, options = Statsig::GetExperimentOptions.new) + def get_experiment(user, experiment_name, options: nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { user = verify_inputs(user, experiment_name, "experiment_name") - get_config_impl(user, experiment_name, options.disable_log_exposure, user_persisted_values: options.user_persisted_values) + get_config_impl(user, experiment_name, options&.disable_log_exposure == true, user_persisted_values: options&.user_persisted_values) }, caller: __method__.to_s) }, recover: -> { DynamicConfig.new(experiment_name) }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, config_name: String).void } def manually_log_config_exposure(user, config_name) @err_boundary.capture(task: lambda { res = @evaluator.get_config(user, config_name) @@ -132,7 +117,6 @@ def manually_log_config_exposure(user, config_name) }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, id_type: String).returns(Statsig::UserPersistedValues) } def get_user_persisted_values(user, id_type) @err_boundary.capture(task: lambda { persisted_values = @persistent_storage_utils.get_user_persisted_values(user, id_type) @@ -142,8 +126,7 @@ def get_user_persisted_values(user, id_type) }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, layer_name: String, options: Statsig::GetLayerOptions).returns(Layer) } - def get_layer(user, layer_name, options = Statsig::GetLayerOptions.new) + def get_layer(user, layer_name, options: nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { user = verify_inputs(user, layer_name, "layer_name") @@ -153,15 +136,16 @@ def get_layer(user, layer_name, options = Statsig::GetLayerOptions.new) res = Statsig::ConfigResult.new(layer_name) end - exposure_log_func = !options.disable_log_exposure ? lambda { |layer, parameter_name| + exposures_disabled = options&.disable_log_exposure != true + exposure_log_func = !exposures_disabled ? lambda { |layer, parameter_name| @logger.log_layer_exposure(user, layer, parameter_name, res) } : nil + Layer.new(res.name, res.json_value, res.rule_id, res.group_name, res.config_delegate, exposure_log_func) }, caller: __method__.to_s) }, recover: lambda { Layer.new(layer_name) }, caller: __method__.to_s) end - # sig { params(user: StatsigUser, layer_name: String, parameter_name: String).void } def manually_log_layer_parameter_exposure(user, layer_name, parameter_name) @err_boundary.capture(task: lambda { res = @evaluator.get_layer(user, layer_name) @@ -200,35 +184,30 @@ def manually_sync_idlists }, caller: __method__.to_s) end - # sig { returns(T::Array[String]) } def list_gates @err_boundary.capture(task: lambda { @evaluator.list_gates }, caller: __method__.to_s) end - # sig { returns(T::Array[String]) } def list_configs @err_boundary.capture(task: lambda { @evaluator.list_configs }, caller: __method__.to_s) end - # sig { returns(T::Array[String]) } def list_experiments @err_boundary.capture(task: lambda { @evaluator.list_experiments }, caller: __method__.to_s) end - # sig { returns(T::Array[String]) } def list_autotunes @err_boundary.capture(task: lambda { @evaluator.list_autotunes }, caller: __method__.to_s) end - # sig { returns(T::Array[String]) } def list_layers @err_boundary.capture(task: lambda { @evaluator.list_layers @@ -307,7 +286,6 @@ def run_with_diagnostics(task:, caller:) return res end - # sig { params(user: StatsigUser, config_name: String, variable_name: String).returns(StatsigUser) } def verify_inputs(user, config_name, variable_name) validate_user(user) if !config_name.is_a?(String) || config_name.empty? @@ -319,14 +297,6 @@ def verify_inputs(user, config_name, variable_name) normalize_user(user) end - # sig do - # params( - # user: StatsigUser, - # config_name: String, - # disable_log_exposure: T::Boolean, - # user_persisted_values: T.nilable(Statsig::UserPersistedValues) - # ).returns(DynamicConfig) - # end def get_config_impl(user, config_name, disable_log_exposure, user_persisted_values: nil) res = @evaluator.get_config(user, config_name, user_persisted_values: user_persisted_values) if res.nil? diff --git a/lib/statsig_options.rb b/lib/statsig_options.rb index 9497ba1..58f67fa 100644 --- a/lib/statsig_options.rb +++ b/lib/statsig_options.rb @@ -1,142 +1,92 @@ - - -# require 'sorbet-runtime' require_relative 'interfaces/data_store' require_relative 'interfaces/user_persistent_storage' ## # Configuration options for the Statsig SDK. class StatsigOptions - # extend T::Sig - # sig { returns(T.any(T::Hash[String, String], NilClass)) } # Hash you can use to set environment variables that apply to all of your users in # the same session and will be used for targeting purposes. # eg. { "tier" => "development" } attr_accessor :environment - # sig { returns(String) } # The base url used to make network calls to Statsig. # default: https://statsigapi.net/v1 attr_accessor :api_url_base # The base url used specifically to call download_config_specs. # Takes precedence over api_url_base - # sig { returns(String) } attr_accessor :api_url_download_config_specs - # sig { returns(T.any(Float, Integer)) } # The interval (in seconds) to poll for changes to your Statsig configuration # default: 10s attr_accessor :rulesets_sync_interval - # sig { returns(T.any(Float, Integer)) } # The interval (in seconds) to poll for changes to your id lists # default: 60s attr_accessor :idlists_sync_interval # Disable background syncing for rulesets - # sig { returns(T::Boolean) } attr_accessor :disable_rulesets_sync # Disable background syncing for id lists - # sig { returns(T::Boolean) } attr_accessor :disable_idlists_sync - # sig { returns(T.any(Float, Integer)) } # How often to flush logs to Statsig # default: 60s attr_accessor :logging_interval_seconds - # sig { returns(Integer) } # The maximum number of events to batch before flushing logs to the server # default: 1000 attr_accessor :logging_max_buffer_size - # sig { returns(T::Boolean) } # Restricts the SDK to not issue any network requests and only respond with default values (or local overrides) # default: false attr_accessor :local_mode - # sig { returns(T.any(String, NilClass)) } # A string that represents all rules for all feature gates, dynamic configs and experiments. # It can be provided to bootstrap the Statsig server SDK at initialization in case your server runs # into network issue or Statsig is down temporarily. attr_accessor :bootstrap_values - # sig { returns(T.any(Method, Proc, NilClass)) } # A callback function that will be called anytime the rulesets are updated. attr_accessor :rules_updated_callback - # sig { returns(T.any(Statsig::Interfaces::IDataStore, NilClass)) } # A class that extends IDataStore. Can be used to provide values from a # common data store (like Redis) to initialize the Statsig SDK. attr_accessor :data_store - # sig { returns(Integer) } # The number of threads allocated to syncing IDLists. # default: 3 attr_accessor :idlist_threadpool_size - # sig { returns(Integer) } # The number of threads allocated to posting event logs. # default: 3 attr_accessor :logger_threadpool_size - # sig { returns(T::Boolean) } # Should diagnostics be logged. These include performance metrics for initialize. # default: false attr_accessor :disable_diagnostics_logging - # sig { returns(T::Boolean) } # Statsig utilizes Sorbet (https://sorbet.org) to ensure type safety of the SDK. This includes logging # to console when errors are detected. You can disable this logging by setting this flag to true. # default: false attr_accessor :disable_sorbet_logging_handlers - # sig { returns(T.any(Integer, NilClass)) } # Number of seconds before a network call is timed out attr_accessor :network_timeout - # sig { returns(Integer) } # Number of times to retry sending a batch of failed log events attr_accessor :post_logs_retry_limit - # sig { returns(T.any(Method, Proc, Integer, NilClass)) } # The number of seconds, or a function that returns the number of seconds based on the number of retries remaining # which overrides the default backoff time between retries attr_accessor :post_logs_retry_backoff - # sig { returns(T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass)) } # A storage adapter for persisted values. Can be used for sticky bucketing users in experiments. # Implements Statsig::Interfaces::IUserPersistentStorage. attr_accessor :user_persistent_storage - # sig do - # params( - # environment: T.any(T::Hash[String, String], NilClass), - # api_url_base: T.nilable(String), - # api_url_download_config_specs: T.any(String, NilClass), - # rulesets_sync_interval: T.any(Float, Integer), - # idlists_sync_interval: T.any(Float, Integer), - # disable_rulesets_sync: T::Boolean, - # disable_idlists_sync: T::Boolean, - # logging_interval_seconds: T.any(Float, Integer), - # logging_max_buffer_size: Integer, - # local_mode: T::Boolean, - # bootstrap_values: T.any(String, NilClass), - # rules_updated_callback: T.any(Method, Proc, NilClass), - # data_store: T.any(Statsig::Interfaces::IDataStore, NilClass), - # idlist_threadpool_size: Integer, - # logger_threadpool_size: Integer, - # disable_diagnostics_logging: T::Boolean, - # disable_sorbet_logging_handlers: T::Boolean, - # network_timeout: T.any(Integer, NilClass), - # post_logs_retry_limit: Integer, - # post_logs_retry_backoff: T.any(Method, Proc, Integer, NilClass), - # user_persistent_storage: T.any(Statsig::Interfaces::IUserPersistentStorage, NilClass) - # ).void - # end def initialize( environment = nil, api_url_base = nil, diff --git a/lib/statsig_user.rb b/lib/statsig_user.rb index f3b71d0..b600210 100644 --- a/lib/statsig_user.rb +++ b/lib/statsig_user.rb @@ -1,65 +1,48 @@ - - -# require 'sorbet-runtime' require 'json' ## # The user object to be evaluated against your Statsig configurations (gates/experiments/dynamic configs). class StatsigUser - # extend T::Sig - # sig { returns(T.any(String, NilClass)) } # An identifier for this user. Evaluated against the User ID criteria. (https://docs.statsig.com/feature-gates/conditions#userid) attr_accessor :user_id - # sig { returns(T.any(String, NilClass)) } # An identifier for this user. Evaluated against the Email criteria. (https://docs.statsig.com/feature-gates/conditions#email) attr_accessor :email - # sig { returns(T.any(String, NilClass)) } # An IP address associated with this user. Evaluated against the IP Address criteria. (https://docs.statsig.com/feature-gates/conditions#ip) attr_accessor :ip - # sig { returns(T.any(String, NilClass)) } # A user agent string associated with this user. Evaluated against Browser Version and Name (https://docs.statsig.com/feature-gates/conditions#browser-version) attr_accessor :user_agent - # sig { returns(T.any(String, NilClass)) } # The country code associated with this user (e.g New Zealand => NZ). Evaluated against the Country criteria. (https://docs.statsig.com/feature-gates/conditions#country) attr_accessor :country - # sig { returns(T.any(String, NilClass)) } # An locale for this user. attr_accessor :locale - # sig { returns(T.any(String, NilClass)) } # The current app version the user is interacting with. Evaluated against the App Version criteria. (https://docs.statsig.com/feature-gates/conditions#app-version) attr_accessor :app_version - # sig { returns(T.any(T::Hash[String, String], NilClass)) } # A Hash you can use to set environment variables that apply to this user. e.g. { "tier" => "development" } attr_accessor :statsig_environment - # sig { returns(T.any(T::Hash[String, String], NilClass)) } # Any Custom IDs to associated with the user. (See https://docs.statsig.com/guides/experiment-on-custom-id-types) attr_accessor :custom_ids - # sig { returns(T.any(T::Hash[String, String], NilClass)) } # Any value you wish to use in evaluation, but do not want logged with events, can be stored in this field. attr_accessor :private_attributes - # sig { returns(T.any(T::Hash[String, T.untyped], NilClass)) } def custom @custom end - # sig { params(value: T.any(T::Hash[String, T.untyped], NilClass)).void } # Any custom fields for this user. Evaluated against the Custom criteria. (https://docs.statsig.com/feature-gates/conditions#custom) def custom=(value) @custom = value.is_a?(Hash) ? value : Hash.new end - # sig { params(user_hash: T.any(T::Hash[T.any(String, Symbol), T.untyped], NilClass)).void } def initialize(user_hash) the_hash = user_hash begin @@ -101,7 +84,7 @@ def serialize(for_logging) hash.compact end - def to_hash_without_stable_id() + def to_hash_without_stable_id hash = {} if @user_id != nil hash[:userID] = @user_id @@ -155,12 +138,6 @@ def get_unit_id(id_type) private - # sig { - # params(user_hash: T.any(T::Hash[T.any(String, Symbol), T.untyped], NilClass), - # keys: T::Array[Symbol], - # type: T.untyped) - # .returns(T.untyped) - # } # Pulls fields from the user hash via Symbols and Strings def from_hash(user_hash, keys, type) if user_hash.nil? diff --git a/lib/uri_helper.rb b/lib/uri_helper.rb index 0b14aae..8e77632 100644 --- a/lib/uri_helper.rb +++ b/lib/uri_helper.rb @@ -1,20 +1,12 @@ - - -# require 'sorbet-runtime' - class URIHelper class URIBuilder - # extend T::Sig - # sig { returns(StatsigOptions) } attr_accessor :options - # sig { params(options: StatsigOptions).void } def initialize(options) @options = options end - # sig { params(endpoint: String).returns(String) } def build_url(endpoint) api = @options.api_url_base if endpoint.include?('download_config_specs') diff --git a/lib/user_persistent_storage_utils.rb b/lib/user_persistent_storage_utils.rb index c8f268f..26fe86c 100644 --- a/lib/user_persistent_storage_utils.rb +++ b/lib/user_persistent_storage_utils.rb @@ -1,27 +1,17 @@ - - -# require 'sorbet-runtime' require 'statsig_options' module Statsig - # UserPersistedValues = T.type_alias { T::Hash[String, Hash] } - class UserPersistentStorageUtils - # extend T::Sig - # sig { returns(T::Hash[String, UserPersistedValues]) } attr_accessor :cache - # sig { returns(T.nilable(Interfaces::IUserPersistentStorage)) } attr_accessor :storage - # sig { params(options: StatsigOptions).void } def initialize(options) @storage = options.user_persistent_storage @cache = {} end - # sig { params(user: StatsigUser, id_type: String).returns(T.nilable(UserPersistedValues)) } def get_user_persisted_values(user, id_type) key = self.class.get_storage_key(user, id_type) return @cache[key] unless @cache[key].nil? @@ -29,7 +19,6 @@ def get_user_persisted_values(user, id_type) return load_from_storage(key) end - # sig { params(key: String).returns(T.nilable(UserPersistedValues)) } def load_from_storage(key) return if @storage.nil? @@ -50,7 +39,6 @@ def load_from_storage(key) return nil end - # sig { params(user: StatsigUser, id_type: String, user_persisted_values: UserPersistedValues).void } def save_to_storage(user, id_type, user_persisted_values) return if @storage.nil? @@ -65,7 +53,6 @@ def save_to_storage(user, id_type, user_persisted_values) end end - # sig { params(user: StatsigUser, id_type: String, config_name: String).void } def remove_experiment_from_storage(user, id_type, config_name) persisted_values = get_user_persisted_values(user, id_type) unless persisted_values.nil? @@ -74,7 +61,6 @@ def remove_experiment_from_storage(user, id_type, config_name) end end - # sig { params(user_persisted_values: T.nilable(UserPersistedValues), config_name: String, evaluation: ConfigResult).void } def add_evaluation_to_user_persisted_values(user_persisted_values, config_name, evaluation) if user_persisted_values.nil? user_persisted_values = {} @@ -84,21 +70,18 @@ def add_evaluation_to_user_persisted_values(user_persisted_values, config_name, private - # sig { params(values_string: String).returns(T.nilable(UserPersistedValues)) } def self.parse(values_string) return JSON.parse(values_string) rescue JSON::ParserError return nil end - # sig { params(values_object: UserPersistedValues).returns(T.nilable(String)) } def self.stringify(values_object) return JSON.generate(values_object) rescue StandardError return nil end - # sig { params(user: StatsigUser, id_type: String).returns(String) } def self.get_storage_key(user, id_type) "#{user.get_unit_id(id_type)}:#{id_type}" end diff --git a/test/data_adapter_test.rb b/test/data_adapter_test.rb index df67dc1..de9eed9 100644 --- a/test/data_adapter_test.rb +++ b/test/data_adapter_test.rb @@ -1,5 +1,3 @@ - - require_relative 'test_helper' require_relative './dummy_data_adapter' diff --git a/test/statsig_e2e_test.rb b/test/statsig_e2e_test.rb index df33b9f..25adff7 100644 --- a/test/statsig_e2e_test.rb +++ b/test/statsig_e2e_test.rb @@ -1,5 +1,3 @@ - - require_relative 'test_helper' require 'json' require 'minitest' diff --git a/test/test_helper.rb b/test/test_helper.rb index 97af938..6339d43 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,5 +1,3 @@ - - require 'simplecov' require 'simplecov-lcov' require 'simplecov-cobertura' From 2d49ec90035686900f765c3b930035c0fb39e8a6 Mon Sep 17 00:00:00 2001 From: Daniel Loomb Date: Mon, 22 Jan 2024 11:50:04 -0800 Subject: [PATCH 08/16] Enable GH Actions for Perf branch --- .github/workflows/build-and-test.yml | 4 ++-- .github/workflows/kong.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 98aaef6..4464caa 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -2,9 +2,9 @@ name: build-and-test on: workflow_dispatch: push: - branches: [main] + branches: [main, performance-improvements] pull_request: - branches: [main] + branches: [main, performance-improvements] env: COVERAGE: true diff --git a/.github/workflows/kong.yml b/.github/workflows/kong.yml index 90fdfcf..b843be8 100644 --- a/.github/workflows/kong.yml +++ b/.github/workflows/kong.yml @@ -3,9 +3,9 @@ name: KONG on: workflow_dispatch: pull_request: - branches: [main] + branches: [main, performance-improvements] push: - branches: [main] + branches: [main, performance-improvements] env: test_api_key: ${{ secrets.KONG_SERVER_SDK_KEY }} From 9c22980abec088f83d7653f685dfaae0a2a8eb4c Mon Sep 17 00:00:00 2001 From: Daniel Loomb Date: Mon, 22 Jan 2024 13:50:48 -0800 Subject: [PATCH 09/16] Fix Tests, revert breaking change --- lib/network.rb | 2 +- lib/statsig.rb | 26 +++++++++++------------ lib/statsig_driver.rb | 12 +++++------ test/local_overrides_test.rb | 19 ++++++++--------- test/test_statsig_error_boundary_usage.rb | 14 ++++++++---- test/test_user_fields.rb | 5 ++--- 6 files changed, 41 insertions(+), 37 deletions(-) diff --git a/lib/network.rb b/lib/network.rb index 66d8353..bfd931c 100644 --- a/lib/network.rb +++ b/lib/network.rb @@ -106,7 +106,7 @@ def request(method, endpoint, body, retries = 0, backoff = 1) end def post_logs(events) - json_body = JSON.generate({ :events => events, :statsigMetadata => Statsig.get_statsig_metadata }) + json_body = JSON.generate({ events: events, statsigMetadata: Statsig.get_statsig_metadata }) post('log_event', json_body, @post_logs_retry_limit) rescue StandardError diff --git a/lib/statsig.rb b/lib/statsig.rb index e1f7331..07fc032 100644 --- a/lib/statsig.rb +++ b/lib/statsig.rb @@ -38,7 +38,7 @@ def initialize(disable_log_exposure: false, skip_evaluation: false) # @return [FeatureGate] def self.get_gate(user, gate_name, options) ensure_initialized - @shared_instance&.get_gate(user, gate_name, options: options) + @shared_instance&.get_gate(user, gate_name, options) end class CheckGateOptions @@ -56,9 +56,9 @@ def initialize(disable_log_exposure: false) # @param [String] gate_name The name of the gate being checked # @param [CheckGateOptions] options Additional options for evaluating the gate # @return [Boolean] - def self.check_gate(user, gate_name, options: nil) + def self.check_gate(user, gate_name, options = nil) ensure_initialized - @shared_instance&.check_gate(user, gate_name, options: options) + @shared_instance&.check_gate(user, gate_name, options) end ## @@ -68,7 +68,7 @@ def self.check_gate(user, gate_name, options: nil) # @param gate_name The name of the gate being checked def self.check_gate_with_exposure_logging_disabled(user, gate_name) ensure_initialized - @shared_instance&.check_gate(user, gate_name, options: CheckGateOptions.new(disable_log_exposure: true)) + @shared_instance&.check_gate(user, gate_name, CheckGateOptions.new(disable_log_exposure: true)) end ## @@ -96,9 +96,9 @@ def initialize(disable_log_exposure: false) # @param [String] dynamic_config_name The name of the dynamic config # @param [GetConfigOptions] options Additional options for evaluating the config # @return [DynamicConfig] - def self.get_config(user, dynamic_config_name, options: nil) + def self.get_config(user, dynamic_config_name, options = nil) ensure_initialized - @shared_instance&.get_config(user, dynamic_config_name, options: options) + @shared_instance&.get_config(user, dynamic_config_name, options) end ## @@ -109,7 +109,7 @@ def self.get_config(user, dynamic_config_name, options: nil) # @return [DynamicConfig] def self.get_config_with_exposure_logging_disabled(user, dynamic_config_name) ensure_initialized - @shared_instance&.get_config(user, dynamic_config_name, options: GetConfigOptions.new(disable_log_exposure: true)) + @shared_instance&.get_config(user, dynamic_config_name, GetConfigOptions.new(disable_log_exposure: true)) end ## @@ -137,9 +137,9 @@ def initialize(disable_log_exposure: false, user_persisted_values: nil) # @param [StatsigUser] user A StatsigUser object used for the evaluation # @param [String] experiment_name The name of the experiment # @param [GetExperimentOptions] options Additional options for evaluating the experiment - def self.get_experiment(user, experiment_name, options: nil) + def self.get_experiment(user, experiment_name, options = nil) ensure_initialized - @shared_instance&.get_experiment(user, experiment_name, options: options) + @shared_instance&.get_experiment(user, experiment_name, options) end ## @@ -149,7 +149,7 @@ def self.get_experiment(user, experiment_name, options: nil) # @param [String] experiment_name The name of the experiment def self.get_experiment_with_exposure_logging_disabled(user, experiment_name) ensure_initialized - @shared_instance&.get_experiment(user, experiment_name, options: GetExperimentOptions.new(disable_log_exposure: true)) + @shared_instance&.get_experiment(user, experiment_name, GetExperimentOptions.new(disable_log_exposure: true)) end ## @@ -182,9 +182,9 @@ def initialize(disable_log_exposure: false) # @param [StatsigUser] user A StatsigUser object used for the evaluation # @param [String] layer_name The name of the layer # @param [GetLayerOptions] options Configuration of how this method call should behave - def self.get_layer(user, layer_name, options: nil) + def self.get_layer(user, layer_name, options = nil) ensure_initialized - @shared_instance&.get_layer(user, layer_name, options: options) + @shared_instance&.get_layer(user, layer_name, options) end ## @@ -194,7 +194,7 @@ def self.get_layer(user, layer_name, options: nil) # @param layer_name The name of the layer def self.get_layer_with_exposure_logging_disabled(user, layer_name) ensure_initialized - @shared_instance&.get_layer(user, layer_name, options: GetLayerOptions.new(disable_log_exposure: true)) + @shared_instance&.get_layer(user, layer_name, GetLayerOptions.new(disable_log_exposure: true)) end ## diff --git a/lib/statsig_driver.rb b/lib/statsig_driver.rb index 534ba6a..7dff707 100644 --- a/lib/statsig_driver.rb +++ b/lib/statsig_driver.rb @@ -64,7 +64,7 @@ def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: FeatureGate.from_config_result(res) end - def get_gate(user, gate_name, options: nil) + def get_gate(user, gate_name, options = nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { get_gate_impl(user, gate_name, @@ -75,7 +75,7 @@ def get_gate(user, gate_name, options: nil) }, recover: -> { false }, caller: __method__.to_s) end - def check_gate(user, gate_name, options: nil) + def check_gate(user, gate_name, options = nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { get_gate_impl(user, gate_name, disable_log_exposure: options&.disable_log_exposure == true).value @@ -91,7 +91,7 @@ def manually_log_gate_exposure(user, gate_name) }) end - def get_config(user, dynamic_config_name, options: nil) + def get_config(user, dynamic_config_name, options = nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { user = verify_inputs(user, dynamic_config_name, "dynamic_config_name") @@ -100,7 +100,7 @@ def get_config(user, dynamic_config_name, options: nil) }, recover: -> { DynamicConfig.new(dynamic_config_name) }, caller: __method__.to_s) end - def get_experiment(user, experiment_name, options: nil) + def get_experiment(user, experiment_name, options = nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { user = verify_inputs(user, experiment_name, "experiment_name") @@ -126,7 +126,7 @@ def get_user_persisted_values(user, id_type) }, caller: __method__.to_s) end - def get_layer(user, layer_name, options: nil) + def get_layer(user, layer_name, options = nil) @err_boundary.capture(task: lambda { run_with_diagnostics(task: lambda { user = verify_inputs(user, layer_name, "layer_name") @@ -136,7 +136,7 @@ def get_layer(user, layer_name, options: nil) res = Statsig::ConfigResult.new(layer_name) end - exposures_disabled = options&.disable_log_exposure != true + exposures_disabled = options&.disable_log_exposure == true exposure_log_func = !exposures_disabled ? lambda { |layer, parameter_name| @logger.log_layer_exposure(user, layer, parameter_name, res) } : nil diff --git a/test/local_overrides_test.rb b/test/local_overrides_test.rb index 1acd891..671fbc4 100644 --- a/test/local_overrides_test.rb +++ b/test/local_overrides_test.rb @@ -1,5 +1,3 @@ - - require_relative 'test_helper' require 'minitest' require 'minitest/autorun' @@ -8,6 +6,7 @@ class StatsigLocalOverridesTest < BaseTest suite :StatsigLocalOverridesTest + def setup super options = StatsigOptions.new() @@ -26,38 +25,38 @@ def teardown end def test_gates - val = Statsig.check_gate(StatsigUser.new({'userID' => 'some_user_id'}), "override_me") + val = Statsig.check_gate(StatsigUser.new({ 'userID' => 'some_user_id' }), "override_me") assert(val == false) Statsig.override_gate("override_me", true) - val = Statsig.check_gate(StatsigUser.new({'userID' => 'some_user_id'}), "override_me") + val = Statsig.check_gate(StatsigUser.new({ 'userID' => 'some_user_id' }), "override_me") assert(val == true) - val = Statsig.check_gate(StatsigUser.new({'userID' => '123'}), "override_me") + val = Statsig.check_gate(StatsigUser.new({ 'userID' => '123' }), "override_me") assert(val == true) Statsig.override_gate("override_me", false) - val = Statsig.check_gate(StatsigUser.new({'userID' => '123'}), "override_me") + val = Statsig.check_gate(StatsigUser.new({ 'userID' => '123' }), "override_me") assert(val == false) end def test_configs - val = Statsig.get_config(StatsigUser.new({'userID' => 'some_user_id'}), "override_me") + val = Statsig.get_config(StatsigUser.new({ 'userID' => 'some_user_id' }), "override_me") assert(val.group_name.nil?) assert(val.value == {}) Statsig.override_config("override_me", { "hello" => "its me" }) - val = Statsig.get_config(StatsigUser.new({'userID' => 'some_user_id'}), "override_me") + val = Statsig.get_config(StatsigUser.new({ 'userID' => 'some_user_id' }), "override_me") assert(val.group_name.nil?) assert(val.value == { "hello" => "its me" }) Statsig.override_config("override_me", { "hello" => "its no longer me" }) - val = Statsig.get_config(StatsigUser.new({'userID' => '123'}), "override_me") + val = Statsig.get_config(StatsigUser.new({ 'userID' => '123' }), "override_me") assert(val.group_name.nil?) assert(val.value == { "hello" => "its no longer me" }) Statsig.override_config("override_me", {}) - val = Statsig.get_config(StatsigUser.new({'userID' => '123'}), "override_me") + val = Statsig.get_config(StatsigUser.new({ 'userID' => '123' }), "override_me") assert(val.group_name.nil?) assert(val.value == {}) end diff --git a/test/test_statsig_error_boundary_usage.rb b/test/test_statsig_error_boundary_usage.rb index 6bdc3ef..e715801 100644 --- a/test/test_statsig_error_boundary_usage.rb +++ b/test/test_statsig_error_boundary_usage.rb @@ -103,12 +103,18 @@ def test_errors_with_idlist_sync def test_errors_with_initialize opts = MiniTest::Mock.new - (0..1).each { + 2.times do opts.expect(:is_a?, true, [StatsigOptions]) - } - (0..3).each { + end + 4.times do opts.expect(:nil?, false) - } + end + + opts.expect(:local_mode, false, []) + opts.expect(:network_timeout, nil, []) + opts.expect(:post_logs_retry_backoff, nil, []) + opts.expect(:post_logs_retry_limit, nil, []) + opts.expect(:logger_threadpool_size, nil, []) opts.expect(:instance_of?, true, [StatsigOptions]) diff --git a/test/test_user_fields.rb b/test/test_user_fields.rb index 7c4f570..fa8b138 100644 --- a/test/test_user_fields.rb +++ b/test/test_user_fields.rb @@ -1,5 +1,3 @@ - - require_relative 'test_helper' require 'minitest' require 'minitest/autorun' @@ -9,6 +7,7 @@ class UserFieldsTest < BaseTest suite :UserFieldsTest + def test_nil_init a = nil user = StatsigUser.new(a) @@ -146,7 +145,7 @@ def test_various_primitives_from_hash } }) - custom = T.must(user.custom) + custom = user.custom assert_equal("a_string_value", custom["a_string"]) assert_equal(true, custom["a_bool"]) From 70ba51a7c36b189055f1823a357e006ebd452282 Mon Sep 17 00:00:00 2001 From: Daniel Loomb Date: Mon, 22 Jan 2024 15:01:57 -0800 Subject: [PATCH 10/16] Fix gcir --- lib/client_initialize_helpers.rb | 21 ++++++++++++++------- lib/evaluator.rb | 12 ++++++------ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index fe1b1e2..4e64b85 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -4,9 +4,16 @@ module Statsig class ResponseFormatter def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) - entities - .map { |name, spec| to_response(name, spec, evaluator, user, client_sdk_key, hash_algo) } - .delete_if { |v| v.nil? }.to_h + result = {} + + entities.each do |name, spec| + hashed_name, value = to_response(name, spec, evaluator, user, client_sdk_key, hash_algo) + if hashed_name != nil && value != nil + result[hashed_name] = value + end + end + + result end def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash_algo) @@ -32,11 +39,11 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, case category - when :feature_gate + when 'feature_gate' result[:value] = eval_result.gate_value result[:group_name] = eval_result.group_name result[:id_type] = eval_result.id_type - when :dynamic_config + when 'dynamic_config' id_type = config_spec[:idType] result[:value] = eval_result.json_value result[:group] = eval_result.rule_id @@ -118,10 +125,10 @@ def self.hash_name(name, hash_algo) case hash_algo when 'none' return name - when 'sha256' - return Statsig::HashUtils.sha256(name) when 'djb2' return Statsig::HashUtils.djb2(name) + else + return Statsig::HashUtils.sha256(name) end end end diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 5690885..c9590e5 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -141,7 +141,7 @@ def list_layers @spec_store.layers.map { |name, _| name } end - def get_client_initialize_response(user, hash, client_sdk_key) + def get_client_initialize_response(user, hash_algo, client_sdk_key) if @spec_store.is_ready_for_checks == false return nil end @@ -156,16 +156,16 @@ def get_client_initialize_response(user, hash, client_sdk_key) end { - feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, hash, client_sdk_key), - dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, hash, client_sdk_key), - layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, hash, client_sdk_key), + feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, client_sdk_key, hash_algo), + dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, client_sdk_key, hash_algo), + layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, client_sdk_key, hash_algo), sdkParams: {}, has_updates: true, generator: 'statsig-ruby-sdk', evaluated_keys: evaluated_keys, time: 0, - hash_used: hash, - user_hash: user.to_hash_without_stable_id() + hash_used: hash_algo, + user_hash: user.to_hash_without_stable_id } end From 2aee3bf0a50dd521b03acbe500cedf83e5205555 Mon Sep 17 00:00:00 2001 From: Daniel <95646168+daniel-statsig@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:12:50 -0800 Subject: [PATCH 11/16] Remove inline strings v2 (#278) Co-authored-by: tore-statsig <74584483+tore-statsig@users.noreply.github.com> --- lib/client_initialize_helpers.rb | 18 ++++---- lib/constants.rb | 44 +++++++++++++++++++ lib/evaluator.rb | 72 ++++++++++++++------------------ lib/statsig_user.rb | 4 +- 4 files changed, 89 insertions(+), 49 deletions(-) create mode 100644 lib/constants.rb diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index 4e64b85..2a4174e 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -1,5 +1,7 @@ require_relative 'hash_utils' +require 'constants' + module Statsig class ResponseFormatter @@ -26,7 +28,7 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, category = config_spec[:type] entity_type = config_spec[:entity] - if entity_type == 'segment' || entity_type == 'holdout' + if entity_type == Statsig::Const::SEGMENT || entity_type == Statsig::Const::HOLDOUT return nil end @@ -39,26 +41,26 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, case category - when 'feature_gate' + when Statsig::Const::FEATURE_GATE result[:value] = eval_result.gate_value result[:group_name] = eval_result.group_name result[:id_type] = eval_result.id_type - when 'dynamic_config' + when Statsig::Const::DYNAMIC_CONFIG id_type = config_spec[:idType] result[:value] = eval_result.json_value result[:group] = eval_result.rule_id result[:group_name] = eval_result.group_name result[:id_type] = eval_result.id_type - result[:is_device_based] = id_type.is_a?(String) && id_type.downcase == 'stableid' + result[:is_device_based] = id_type.is_a?(String) && id_type.downcase == Statsig::Const::STABLEID else return nil end - if entity_type == 'experiment' + if entity_type == Statsig::Const::EXPERIMENT populate_experiment_fields(config_name, config_spec, eval_result, result, evaluator) end - if entity_type == 'layer' + if entity_type == Statsig::Const::LAYER populate_layer_fields(config_spec, eval_result, result, evaluator, user, hash_algo) result.delete(:id_type) # not exposed for layer configs in /initialize end @@ -123,9 +125,9 @@ def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user def self.hash_name(name, hash_algo) case hash_algo - when 'none' + when Statsig::Const::NONE return name - when 'djb2' + when Statsig::Const::DJB2 return Statsig::HashUtils.djb2(name) else return Statsig::HashUtils.sha256(name) diff --git a/lib/constants.rb b/lib/constants.rb new file mode 100644 index 0000000..984040a --- /dev/null +++ b/lib/constants.rb @@ -0,0 +1,44 @@ +module Statsig + + module Const + EMPTY_STR = ''.freeze + + APP_VERSION = 'app_version'.freeze + APPVERSION = 'appversion'.freeze + AUTOTUNE = 'autotune'.freeze + BROWSER_NAME = 'browser_name'.freeze + BROWSER_VERSION = 'browser_version'.freeze + BROWSERNAME = 'browsername'.freeze + BROWSERVERSION = 'browserversion'.freeze + CML_SHA_256 = 'sha256'.freeze + CML_USER_ID = "userID".freeze + COUNTRY = 'country'.freeze + DEFAULT = 'default'.freeze + DISABLED = 'disabled'.freeze + DJB2 = 'djb2'.freeze + DYNAMIC_CONFIG = 'dynamic_config'.freeze + EMAIL = 'email'.freeze + EXPERIMENT = 'experiment'.freeze + FALSE = 'false'.freeze + FEATURE_GATE = 'feature_gate'.freeze + HOLDOUT = 'holdout'.freeze + IP = 'ip'.freeze + LAYER = 'layer'.freeze + LOCALE = 'locale'.freeze + NONE = 'none'.freeze + OS_NAME = 'os_name'.freeze + OS_VERSION = 'os_version'.freeze + OSNAME = 'osname'.freeze + OSVERSION = 'osversion'.freeze + OVERRIDE = 'override'.freeze + Q_RIGHT_CHEVRON = 'Q>'.freeze + SEGMENT = 'segment'.freeze + STABLEID = 'stableid'.freeze + STATSIG_RUBY_SDK = 'statsig-ruby-sdk'.freeze + TRUE = 'true'.freeze + USER_AGENT = 'user_agent'.freeze + USER_ID = 'user_id'.freeze + USERAGENT = 'useragent'.freeze + USERID = 'userid'.freeze + end +end \ No newline at end of file diff --git a/lib/evaluator.rb b/lib/evaluator.rb index c9590e5..0cf9390 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -9,8 +9,10 @@ require 'evaluation_details' require 'user_agent_parser/operating_system' require 'user_persistent_storage_utils' +require 'constants' module Statsig + class Evaluator UNSUPPORTED_EVALUATION = :unsupported_eval @@ -42,7 +44,7 @@ def check_gate(user, gate_name) gate_name, @gate_overrides[gate_name], @gate_overrides[gate_name], - 'override', + Const::OVERRIDE, [], evaluation_details: EvaluationDetails.local_override(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) end @@ -59,12 +61,12 @@ def check_gate(user, gate_name) def get_config(user, config_name, user_persisted_values: nil) if @config_overrides.key?(config_name) - id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)[:idType] : '' + id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)[:idType] : Const::EMPTY_STR return Statsig::ConfigResult.new( config_name, false, @config_overrides[config_name], - 'override', + Const::OVERRIDE, [], evaluation_details: EvaluationDetails.local_override( @spec_store.last_config_sync_time, @@ -126,15 +128,15 @@ def list_gates end def list_configs - @spec_store.configs.map { |name, config| name if config[:entity] == 'dynamic_config' }.compact + @spec_store.configs.map { |name, config| name if config[:entity] == Const::DYNAMIC_CONFIG }.compact end def list_experiments - @spec_store.configs.map { |name, config| name if config[:entity] == 'experiment' }.compact + @spec_store.configs.map { |name, config| name if config[:entity] == Const::EXPERIMENT }.compact end def list_autotunes - @spec_store.configs.map { |name, config| name if config[:entity] == 'autotune' }.compact + @spec_store.configs.map { |name, config| name if config[:entity] == Const::AUTOTUNE }.compact end def list_layers @@ -161,7 +163,7 @@ def get_client_initialize_response(user, hash_algo, client_sdk_key) layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, client_sdk_key, hash_algo), sdkParams: {}, has_updates: true, - generator: 'statsig-ruby-sdk', + generator: Const::STATSIG_RUBY_SDK, evaluated_keys: evaluated_keys, time: 0, hash_used: hash_algo, @@ -181,16 +183,6 @@ def get_all_evaluations(user) } end - def clean_exposures(exposures) - seen = {} - exposures.reject do |exposure| - key = "#{exposure["gate"]}|#{exposure["gateValue"]}|#{exposure["ruleID"]}}" - should_reject = seen[key] - seen[key] = true - should_reject == true - end - end - def shutdown @spec_store.shutdown end @@ -204,7 +196,7 @@ def override_config(config, value) end def eval_spec(user, config) - default_rule_id = 'default' + default_rule_id = Const::DEFAULT exposures = [] if config[:enabled] i = 0 @@ -215,7 +207,7 @@ def eval_spec(user, config) config[:name], false, config[:defaultValue], - '', + Const::EMPTY_STR, exposures, evaluation_details: EvaluationDetails.new( @spec_store.last_config_sync_time, @@ -255,7 +247,7 @@ def eval_spec(user, config) i += 1 end else - default_rule_id = 'disabled' + default_rule_id = Const::DISABLED end Statsig::ConfigResult.new( @@ -297,7 +289,7 @@ def eval_rule(user, rule) end Statsig::ConfigResult.new( - '', + Const::EMPTY_STR, pass, rule[:returnValue], rule[:id], @@ -347,7 +339,7 @@ def eval_condition(user, condition) gate_value = other_gate_result&.gate_value == true new_exposure = { gate: target, - gateValue: gate_value ? 'true' : 'false', + gateValue: gate_value ? Const::TRUE : Const::FALSE, ruleID: other_gate_result&.rule_id } exposures = other_gate_result&.secondary_exposures&.append(new_exposure) @@ -368,7 +360,7 @@ def eval_condition(user, condition) when :user_bucket begin salt = additional_values[:salt] - unit_id = user.get_unit_id(id_type) || '' + unit_id = user.get_unit_id(id_type) || Const::EMPTY_STR # there are only 1000 user buckets as opposed to 10k for gate pass % value = compute_user_hash("#{salt}.#{unit_id}") % 1000 rescue @@ -465,19 +457,19 @@ def eval_condition(user, condition) def get_value_from_user(user, field) value = case field.downcase - when 'userid', 'user_id' + when Const::USERID, Const::USER_ID user.user_id - when 'email' + when Const::EMAIL user.email - when 'ip' + when Const::IP user.ip - when 'useragent', 'user_agent' + when Const::USERAGENT, Const::USER_AGENT user.user_agent - when 'country' + when Const::COUNTRY user.country - when 'locale' + when Const::LOCALE user.locale - when 'appversion', 'app_version' + when Const::APPVERSION, Const::APP_VERSION user.app_version else nil @@ -500,28 +492,28 @@ def get_value_from_environment(user, field) end def get_value_from_ip(user, field) - return nil unless field == 'country' - ip = get_value_from_user(user, 'ip') + return nil unless field == Const::COUNTRY + ip = get_value_from_user(user, Const::IP) return nil unless ip.is_a?(String) CountryLookup.lookup_ip_string(ip) end def get_value_from_ua(user, field) - ua = get_value_from_user(user, 'user_agent') + ua = get_value_from_user(user, Const::USER_AGENT) return nil unless ua.is_a?(String) case field.downcase - when 'os_name', 'osname' + when Const::OSNAME, Const::OS_NAME os = UAParser.parse_os(ua) return os&.family - when 'os_version', 'osversion' + when Const::OS_VERSION, Const::OSVERSION os = UAParser.parse_os(ua) return os&.version unless os&.version.nil? - when 'browser_name', 'browsername' + when Const::BROWSERNAME, Const::BROWSER_NAME parsed = UAParser.parse_ua(ua) return parsed.family - when 'browser_version', 'browserversion' + when Const::BROWSERVERSION, Const::BROWSER_VERSION parsed = UAParser.parse_ua(ua) return parsed.version.to_s else @@ -532,8 +524,8 @@ def get_value_from_ua(user, field) def eval_pass_percent(user, rule, config_salt) return false unless config_salt.is_a?(String) && !rule[:passPercentage].nil? begin - unit_id = user.get_unit_id(rule[:idType]) || '' - rule_salt = rule[:salt] || rule[:id] || '' + unit_id = user.get_unit_id(rule[:idType]) || Const::EMPTY_STR + rule_salt = rule[:salt] || rule[:id] || Const::EMPTY_STR hash = compute_user_hash("#{config_salt}.#{rule_salt}.#{unit_id}") return (hash % 10000) < (rule[:passPercentage].to_f * 100) rescue @@ -542,7 +534,7 @@ def eval_pass_percent(user, rule, config_salt) end def compute_user_hash(user_hash) - Digest::SHA256.digest(user_hash).unpack('Q>')[0] + Digest::SHA256.digest(user_hash).unpack(Const::Q_RIGHT_CHEVRON)[0] end end end diff --git a/lib/statsig_user.rb b/lib/statsig_user.rb index b600210..d3f62e7 100644 --- a/lib/statsig_user.rb +++ b/lib/statsig_user.rb @@ -1,4 +1,5 @@ require 'json' +require 'constants' ## # The user object to be evaluated against your Statsig configurations (gates/experiments/dynamic configs). @@ -86,6 +87,7 @@ def serialize(for_logging) def to_hash_without_stable_id hash = {} + if @user_id != nil hash[:userID] = @user_id end @@ -128,7 +130,7 @@ def to_hash_without_stable_id end def get_unit_id(id_type) - if id_type.is_a?(String) && id_type != 'userID' + if id_type.is_a?(String) && id_type != Statsig::Const::CML_USER_ID return nil unless @custom_ids.is_a? Hash return @custom_ids[id_type] || @custom_ids[id_type.downcase] From 206148b062583966d8cb57e9e0d79949b06e7b71 Mon Sep 17 00:00:00 2001 From: tore-statsig <74584483+tore-statsig@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:07:56 -0800 Subject: [PATCH 12/16] Pass evaluation result by reference through evaluator (#282) Co-authored-by: Daniel Loomb --- lib/client_initialize_helpers.rb | 13 +-- lib/evaluator.rb | 173 +++++++++++-------------------- 2 files changed, 68 insertions(+), 118 deletions(-) diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index 2a4174e..66d0581 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -32,10 +32,8 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, return nil end - eval_result = evaluator.eval_spec(user, config_spec) - if eval_result.nil? - return nil - end + eval_result = ConfigResult.new(config_spec[:name]) + evaluator.eval_spec(user, config_spec, eval_result) result = {} @@ -61,7 +59,7 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, end if entity_type == Statsig::Const::LAYER - populate_layer_fields(config_spec, eval_result, result, evaluator, user, hash_algo) + populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo) result.delete(:id_type) # not exposed for layer configs in /initialize end @@ -106,16 +104,15 @@ def self.populate_experiment_fields(config_name, config_spec, eval_result, resul result[:value] = layer[:defaultValue].merge(result[:value]) end - def self.populate_layer_fields(config_spec, eval_result, result, evaluator, user, hash_algo) + def self.populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo) delegate = eval_result.config_delegate result[:explicit_parameters] = config_spec[:explicitParameters] || [] if delegate.nil? == false && delegate.empty? == false delegate_spec = evaluator.spec_store.configs[delegate] - delegate_result = evaluator.eval_spec(user, delegate_spec) result[:allocated_experiment_name] = hash_name(delegate, hash_algo) - result[:is_user_in_experiment] = delegate_result.is_experiment_group + result[:is_user_in_experiment] = eval_result.is_experiment_group result[:is_experiment_active] = delegate_spec[:isActive] == true result[:explicit_parameters] = delegate_spec[:explicitParameters] || [] end diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 0cf9390..80766da 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -56,7 +56,9 @@ def check_gate(user, gate_name) unless @spec_store.has_gate?(gate_name) return Statsig::ConfigResult.new(gate_name, evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) end - eval_spec(user, @spec_store.get_gate(gate_name)) + result = Statsig::ConfigResult.new(gate_name) + eval_spec(user, @spec_store.get_gate(gate_name), result) + result end def get_config(user, config_name, user_persisted_values: nil) @@ -98,17 +100,19 @@ def get_config(user, config_name, user_persisted_values: nil) return sticky_result unless sticky_result.nil? # If it doesn't exist, then save to persisted storage if the user was assigned to an experiment group. - evaluation = eval_spec(user, config) - if evaluation.is_experiment_group - @persistent_storage_utils.add_evaluation_to_user_persisted_values(user_persisted_values, config_name, evaluation) + result = Statsig::ConfigResult.new(config_name) + eval_spec(user, config, result) + if result.is_experiment_group + @persistent_storage_utils.add_evaluation_to_user_persisted_values(user_persisted_values, config_name, result) @persistent_storage_utils.save_to_storage(user, config[:idType], user_persisted_values) end # Otherwise, remove from persisted storage else @persistent_storage_utils.remove_experiment_from_storage(user, config[:idType], config_name) - evaluation = eval_spec(user, config) + result = Statsig::ConfigResult.new(config_name) + eval_spec(user, config, result) end - evaluation + result end def get_layer(user, layer_name) @@ -120,7 +124,9 @@ def get_layer(user, layer_name) return Statsig::ConfigResult.new(layer_name, evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) end - eval_spec(user, @spec_store.get_layer(layer_name)) + result = Statsig::ConfigResult.new(layer_name) + eval_spec(user, @spec_store.get_layer(layer_name), result) + result end def list_gates @@ -195,53 +201,33 @@ def override_config(config, value) @config_overrides[config] = value end - def eval_spec(user, config) + def eval_spec(user, config, end_result) + end_result.id_type = config[:idType] + end_result.target_app_ids = config[:targetAppIDs] + end_result.evaluation_details = EvaluationDetails.new( + @spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time, + @spec_store.init_reason + ) default_rule_id = Const::DEFAULT - exposures = [] if config[:enabled] i = 0 until i >= config[:rules].length do rule = config[:rules][i] - result = eval_rule(user, rule) - return Statsig::ConfigResult.new( - config[:name], - false, - config[:defaultValue], - Const::EMPTY_STR, - exposures, - evaluation_details: EvaluationDetails.new( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time, - EvaluationReason::UNSUPPORTED, - ), - group_name: nil, - id_type: config[:idType], - target_app_ids: config[:targetAppIDs] - ) if result == UNSUPPORTED_EVALUATION - exposures = exposures + result.secondary_exposures - if result.gate_value - - if (delegated_result = eval_delegate(config[:name], user, rule, exposures)) - return delegated_result + eval_rule(user, rule, end_result) + + if end_result.gate_value + if eval_delegate(config[:name], user, rule, end_result) + return end pass = eval_pass_percent(user, rule, config[:salt]) - return Statsig::ConfigResult.new( - config[:name], - pass, - pass ? result.json_value : config[:defaultValue], - result.rule_id, - exposures, - evaluation_details: EvaluationDetails.new( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time, - @spec_store.init_reason - ), - is_experiment_group: result.is_experiment_group, - group_name: result.group_name, - id_type: config[:idType], - target_app_ids: config[:targetAppIDs] - ) + end_result.gate_value = pass + end_result.json_value = pass ? rule[:returnValue] : config[:defaultValue] + end_result.rule_id = rule[:id] + end_result.group_name = rule[:groupName] + end_result.is_experiment_group = rule[:isExperimentGroup] == true + return end i += 1 @@ -250,76 +236,47 @@ def eval_spec(user, config) default_rule_id = Const::DISABLED end - Statsig::ConfigResult.new( - config[:name], - false, - config[:defaultValue], - default_rule_id, - exposures, - evaluation_details: EvaluationDetails.new( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time, - @spec_store.init_reason - ), - group_name: nil, - id_type: config[:idType], - target_app_ids: config[:targetAppIDs] + end_result.rule_id = default_rule_id + end_result.gate_value = false + end_result.json_value = config[:defaultValue] + end_result.evaluation_details = EvaluationDetails.new( + @spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time, + @spec_store.init_reason ) + end_result.group_name = nil end private - def eval_rule(user, rule) - exposures = [] + def eval_rule(user, rule, end_result) pass = true i = 0 until i >= rule[:conditions].length do - result = eval_condition(user, rule[:conditions][i]) - if result == UNSUPPORTED_EVALUATION - return UNSUPPORTED_EVALUATION - end + result = eval_condition(user, rule[:conditions][i], end_result) - if result.is_a?(Hash) - exposures = exposures + result[:exposures] - pass = false if result[:value] == false - elsif result == false - pass = false - end + pass = false if result == false i += 1 end - Statsig::ConfigResult.new( - Const::EMPTY_STR, - pass, - rule[:returnValue], - rule[:id], - exposures, - evaluation_details: EvaluationDetails.new( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time, - @spec_store.init_reason - ), - is_experiment_group: rule[:isExperimentGroup] == true, - group_name: rule[:groupName] - ) + end_result.gate_value = pass end - def eval_delegate(name, user, rule, exposures) - return nil unless (delegate = rule[:configDelegate]) - return nil unless (config = @spec_store.get_config(delegate)) + def eval_delegate(name, user, rule, end_result) + return false unless (delegate = rule[:configDelegate]) + return false unless (config = @spec_store.get_config(delegate)) - delegated_result = self.eval_spec(user, config) - return UNSUPPORTED_EVALUATION if delegated_result == UNSUPPORTED_EVALUATION + end_result.undelegated_sec_exps = end_result.secondary_exposures.dup + self.eval_spec(user, config, end_result) - delegated_result.name = name - delegated_result.config_delegate = delegate - delegated_result.secondary_exposures = exposures + delegated_result.secondary_exposures - delegated_result.undelegated_sec_exps = exposures - delegated_result.explicit_parameters = config[:explicitParameters] - delegated_result + end_result.name = name + end_result.config_delegate = delegate + end_result.explicit_parameters = config[:explicitParameters] + + true end - def eval_condition(user, condition) + def eval_condition(user, condition, end_result) value = nil field = condition[:field] target = condition[:targetValue] @@ -334,19 +291,18 @@ def eval_condition(user, condition) return true when :fail_gate, :pass_gate other_gate_result = check_gate(user, target) - return UNSUPPORTED_EVALUATION if other_gate_result == UNSUPPORTED_EVALUATION - gate_value = other_gate_result&.gate_value == true + gate_value = other_gate_result.gate_value new_exposure = { gate: target, gateValue: gate_value ? Const::TRUE : Const::FALSE, - ruleID: other_gate_result&.rule_id - } - exposures = other_gate_result&.secondary_exposures&.append(new_exposure) - return { - value: type == :pass_gate ? gate_value : !gate_value, - exposures: exposures + ruleID: other_gate_result.rule_id } + if other_gate_result.secondary_exposures.length > 0 + end_result.secondary_exposures.concat(other_gate_result.secondary_exposures) + end + end_result.secondary_exposures.append(new_exposure) + return type == :pass_gate ? gate_value : !gate_value when :ip_based value = get_value_from_user(user, field) || get_value_from_ip(user, field) when :ua_based @@ -368,8 +324,6 @@ def eval_condition(user, condition) end when :unit_id value = user.get_unit_id(id_type) - else - return UNSUPPORTED_EVALUATION end case operator @@ -450,9 +404,8 @@ def eval_condition(user, condition) rescue return false end - else - return UNSUPPORTED_EVALUATION end + return false end def get_value_from_user(user, field) From c9229cbf91f816260802c5932823b51ee8834520 Mon Sep 17 00:00:00 2001 From: tore-statsig <74584483+tore-statsig@users.noreply.github.com> Date: Tue, 23 Jan 2024 11:18:07 -0800 Subject: [PATCH 13/16] Classes not hashes (#275) --- lib/api_config.rb | 105 +++++++++++++++++ lib/client_initialize_helpers.rb | 39 +++---- lib/constants.rb | 13 +-- lib/evaluator.rb | 195 ++++++++++++++++++------------- lib/spec_store.rb | 80 +++++-------- lib/statsig_driver.rb | 2 +- test/statsig_e2e_test.rb | 79 ++++++++----- 7 files changed, 324 insertions(+), 189 deletions(-) create mode 100644 lib/api_config.rb diff --git a/lib/api_config.rb b/lib/api_config.rb new file mode 100644 index 0000000..ca50e54 --- /dev/null +++ b/lib/api_config.rb @@ -0,0 +1,105 @@ +class APIConfig + attr_accessor :name, :type, :is_active, :salt, :default_value, :enabled, + :rules, :id_type, :entity, :explicit_parameters, :has_shared_params, :target_app_ids + + def initialize(name:, type:, is_active:, salt:, default_value:, enabled:, rules:, id_type:, entity:, + explicit_parameters: nil, has_shared_params: nil, target_app_ids: nil) + @name = name + @type = type.to_sym unless entity.nil? + @is_active = is_active + @salt = salt + @default_value = default_value + @enabled = enabled + @rules = rules + @id_type = id_type + @entity = entity.to_sym unless entity.nil? + @explicit_parameters = explicit_parameters + @has_shared_params = has_shared_params + @target_app_ids = target_app_ids + end + + def self.from_json(json) + new( + name: json[:name], + type: json[:type], + is_active: json[:isActive], + salt: json[:salt], + default_value: json[:defaultValue], + enabled: json[:enabled], + rules: json[:rules]&.map do |rule| + APIRule.from_json(rule) + end, + id_type: json[:idType], + entity: json[:entity], + explicit_parameters: json[:explicitParameters], + has_shared_params: json[:hasSharedParams], + target_app_ids: json[:targetAppIDs] + ) + end +end + +class APIRule + attr_accessor :name, :pass_percentage, :return_value, :id, :salt, + :conditions, :id_type, :group_name, :config_delegate, :is_experiment_group + + def initialize(name:, pass_percentage:, return_value:, id:, salt:, conditions:, id_type:, + group_name: nil, config_delegate: nil, is_experiment_group: nil) + @name = name + @pass_percentage = pass_percentage.to_f + @return_value = return_value + @id = id + @salt = salt + @conditions = conditions + @id_type = id_type + @group_name = group_name + @config_delegate = config_delegate + @is_experiment_group = is_experiment_group + end + + def self.from_json(json) + new( + name: json[:name], + pass_percentage: json[:passPercentage], + return_value: json[:returnValue], + id: json[:id], + salt: json[:salt], + conditions: json[:conditions]&.map do |condition| + APICondition.from_json(condition) + end, + id_type: json[:idType], + group_name: json[:groupName], + config_delegate: json[:configDelegate], + is_experiment_group: json[:isExperimentGroup] + ) + end +end + +class APICondition + attr_accessor :type, :target_value, :operator, :field, :additional_values, :id_type + + def initialize(type:, target_value:, operator:, field:, additional_values:, id_type:) + @type = type.to_sym unless type.nil? + @target_value = target_value + @operator = operator.to_sym unless operator.nil? + @field = field + @additional_values = additional_values || {} + @id_type = id_type + end + + def self.from_json(json) + new( + type: json[:type], + target_value: process_target_value(json[:targetValue], json[:operator], json[:type]), + operator: json[:operator], + field: json[:field], + additional_values: json[:additionalValues], + id_type: json[:idType] + ) + end + + def self.process_target_value(target_value, _operator, _type) + return target_value unless target_value.is_a?(Array) + + target_value.to_set + end +end diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index 66d0581..008ab1f 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -4,13 +4,12 @@ module Statsig class ResponseFormatter - def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) result = {} entities.each do |name, spec| hashed_name, value = to_response(name, spec, evaluator, user, client_sdk_key, hash_algo) - if hashed_name != nil && value != nil + if !hashed_name.nil? && !value.nil? result[hashed_name] = value end end @@ -20,31 +19,31 @@ def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash_algo) target_app_id = evaluator.spec_store.get_app_id_for_sdk_key(client_sdk_key) - config_target_apps = config_spec[:targetAppIDs] + config_target_apps = config_spec.target_app_ids unless target_app_id.nil? || (!config_target_apps.nil? && config_target_apps.include?(target_app_id)) return nil end - category = config_spec[:type] - entity_type = config_spec[:entity] - if entity_type == Statsig::Const::SEGMENT || entity_type == Statsig::Const::HOLDOUT + category = config_spec.type + entity_type = config_spec.entity + if entity_type == :segment || entity_type == :holdout return nil end - eval_result = ConfigResult.new(config_spec[:name]) + eval_result = ConfigResult.new(config_name) evaluator.eval_spec(user, config_spec, eval_result) result = {} case category - when Statsig::Const::FEATURE_GATE + when :feature_gate result[:value] = eval_result.gate_value result[:group_name] = eval_result.group_name result[:id_type] = eval_result.id_type - when Statsig::Const::DYNAMIC_CONFIG - id_type = config_spec[:idType] + when :dynamic_config + id_type = config_spec.id_type result[:value] = eval_result.json_value result[:group] = eval_result.rule_id result[:group_name] = eval_result.group_name @@ -54,11 +53,11 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, return nil end - if entity_type == Statsig::Const::EXPERIMENT - populate_experiment_fields(config_name, config_spec, eval_result, result, evaluator) + if entity_type == :experiment + populate_experiment_fields(name, config_spec, eval_result, result, evaluator) end - if entity_type == Statsig::Const::LAYER + if entity_type == :layer populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo) result.delete(:id_type) # not exposed for layer configs in /initialize end @@ -72,8 +71,6 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, [hashed_name, result] end - private - def self.clean_exposures(exposures) seen = {} exposures.reject do |exposure| @@ -86,14 +83,14 @@ def self.clean_exposures(exposures) def self.populate_experiment_fields(config_name, config_spec, eval_result, result, evaluator) result[:is_user_in_experiment] = eval_result.is_experiment_group - result[:is_experiment_active] = config_spec[:isActive] == true + result[:is_experiment_active] = config_spec.is_active == true - if config_spec[:hasSharedParams] != true + if config_spec.has_shared_params != true return end result[:is_in_layer] = true - result[:explicit_parameters] = config_spec[:explicitParameters] || [] + result[:explicit_parameters] = config_spec.explicit_parameters || [] layer_name = evaluator.spec_store.experiment_to_layer[config_name] if layer_name.nil? || evaluator.spec_store.layers[layer_name].nil? @@ -106,15 +103,15 @@ def self.populate_experiment_fields(config_name, config_spec, eval_result, resul def self.populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo) delegate = eval_result.config_delegate - result[:explicit_parameters] = config_spec[:explicitParameters] || [] + result[:explicit_parameters] = config_spec.explicit_parameters || [] if delegate.nil? == false && delegate.empty? == false delegate_spec = evaluator.spec_store.configs[delegate] result[:allocated_experiment_name] = hash_name(delegate, hash_algo) result[:is_user_in_experiment] = eval_result.is_experiment_group - result[:is_experiment_active] = delegate_spec[:isActive] == true - result[:explicit_parameters] = delegate_spec[:explicitParameters] || [] + result[:is_experiment_active] = delegate_spec.is_active == true + result[:explicit_parameters] = delegate_spec.explicit_parameters || [] end result[:undelegated_secondary_exposures] = clean_exposures(eval_result.undelegated_sec_exps || []) diff --git a/lib/constants.rb b/lib/constants.rb index 984040a..2ece25d 100644 --- a/lib/constants.rb +++ b/lib/constants.rb @@ -1,29 +1,23 @@ module Statsig - module Const EMPTY_STR = ''.freeze APP_VERSION = 'app_version'.freeze APPVERSION = 'appversion'.freeze - AUTOTUNE = 'autotune'.freeze BROWSER_NAME = 'browser_name'.freeze BROWSER_VERSION = 'browser_version'.freeze BROWSERNAME = 'browsername'.freeze BROWSERVERSION = 'browserversion'.freeze CML_SHA_256 = 'sha256'.freeze - CML_USER_ID = "userID".freeze + CML_USER_ID = 'userID'.freeze COUNTRY = 'country'.freeze DEFAULT = 'default'.freeze DISABLED = 'disabled'.freeze DJB2 = 'djb2'.freeze - DYNAMIC_CONFIG = 'dynamic_config'.freeze EMAIL = 'email'.freeze - EXPERIMENT = 'experiment'.freeze FALSE = 'false'.freeze - FEATURE_GATE = 'feature_gate'.freeze - HOLDOUT = 'holdout'.freeze IP = 'ip'.freeze - LAYER = 'layer'.freeze + LAYER = :layer LOCALE = 'locale'.freeze NONE = 'none'.freeze OS_NAME = 'os_name'.freeze @@ -32,7 +26,6 @@ module Const OSVERSION = 'osversion'.freeze OVERRIDE = 'override'.freeze Q_RIGHT_CHEVRON = 'Q>'.freeze - SEGMENT = 'segment'.freeze STABLEID = 'stableid'.freeze STATSIG_RUBY_SDK = 'statsig-ruby-sdk'.freeze TRUE = 'true'.freeze @@ -41,4 +34,4 @@ module Const USERAGENT = 'useragent'.freeze USERID = 'userid'.freeze end -end \ No newline at end of file +end diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 80766da..1a8d7db 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -12,9 +12,7 @@ require 'constants' module Statsig - class Evaluator - UNSUPPORTED_EVALUATION = :unsupported_eval attr_accessor :spec_store @@ -46,7 +44,9 @@ def check_gate(user, gate_name) @gate_overrides[gate_name], Const::OVERRIDE, [], - evaluation_details: EvaluationDetails.local_override(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) + evaluation_details: EvaluationDetails.local_override(@spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time) + ) end if @spec_store.init_reason == EvaluationReason::UNINITIALIZED @@ -54,8 +54,11 @@ def check_gate(user, gate_name) end unless @spec_store.has_gate?(gate_name) - return Statsig::ConfigResult.new(gate_name, evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) + return Statsig::ConfigResult.new(gate_name, + evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time)) end + result = Statsig::ConfigResult.new(gate_name) eval_spec(user, @spec_store.get_gate(gate_name), result) result @@ -63,7 +66,7 @@ def check_gate(user, gate_name) def get_config(user, config_name, user_persisted_values: nil) if @config_overrides.key?(config_name) - id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name)[:idType] : Const::EMPTY_STR + id_type = @spec_store.has_config?(config_name) ? @spec_store.get_config(config_name).id_type : Const::EMPTY_STR return Statsig::ConfigResult.new( config_name, false, @@ -95,7 +98,7 @@ def get_config(user, config_name, user_persisted_values: nil) config = @spec_store.get_config(config_name) # If persisted values is provided and the experiment is active, return sticky values if exists. - if !user_persisted_values.nil? && config[:isActive] == true + if !user_persisted_values.nil? && config.is_active == true sticky_result = Statsig::ConfigResult.from_user_persisted_values(config_name, user_persisted_values) return sticky_result unless sticky_result.nil? @@ -104,11 +107,11 @@ def get_config(user, config_name, user_persisted_values: nil) eval_spec(user, config, result) if result.is_experiment_group @persistent_storage_utils.add_evaluation_to_user_persisted_values(user_persisted_values, config_name, result) - @persistent_storage_utils.save_to_storage(user, config[:idType], user_persisted_values) + @persistent_storage_utils.save_to_storage(user, config.id_type, user_persisted_values) end # Otherwise, remove from persisted storage else - @persistent_storage_utils.remove_experiment_from_storage(user, config[:idType], config_name) + @persistent_storage_utils.remove_experiment_from_storage(user, config.id_type, config_name) result = Statsig::ConfigResult.new(config_name) eval_spec(user, config, result) end @@ -121,7 +124,9 @@ def get_layer(user, layer_name) end unless @spec_store.has_layer?(layer_name) - return Statsig::ConfigResult.new(layer_name, evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, @spec_store.initial_config_sync_time)) + return Statsig::ConfigResult.new(layer_name, + evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time)) end result = Statsig::ConfigResult.new(layer_name) @@ -134,15 +139,15 @@ def list_gates end def list_configs - @spec_store.configs.map { |name, config| name if config[:entity] == Const::DYNAMIC_CONFIG }.compact + @spec_store.configs.map { |name, config| name if config.entity == :dynamic_config }.compact end def list_experiments - @spec_store.configs.map { |name, config| name if config[:entity] == Const::EXPERIMENT }.compact + @spec_store.configs.map { |name, config| name if config.entity == :experiment }.compact end def list_autotunes - @spec_store.configs.map { |name, config| name if config[:entity] == Const::AUTOTUNE }.compact + @spec_store.configs.map { |name, config| name if config.entity == :autotune }.compact end def list_layers @@ -164,9 +169,12 @@ def get_client_initialize_response(user, hash_algo, client_sdk_key) end { - feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, client_sdk_key, hash_algo), - dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, client_sdk_key, hash_algo), - layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, client_sdk_key, hash_algo), + feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, client_sdk_key, + hash_algo), + dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, client_sdk_key, + hash_algo), + layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, client_sdk_key, + hash_algo), sdkParams: {}, has_updates: true, generator: Const::STATSIG_RUBY_SDK, @@ -185,7 +193,7 @@ def get_all_evaluations(user) { feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, nil, 'none'), dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, nil, 'none'), - layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, nil, 'none'), + layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, nil, 'none') } end @@ -202,31 +210,31 @@ def override_config(config, value) end def eval_spec(user, config, end_result) - end_result.id_type = config[:idType] - end_result.target_app_ids = config[:targetAppIDs] + end_result.id_type = config.id_type + end_result.target_app_ids = config.target_app_ids end_result.evaluation_details = EvaluationDetails.new( @spec_store.last_config_sync_time, @spec_store.initial_config_sync_time, @spec_store.init_reason ) default_rule_id = Const::DEFAULT - if config[:enabled] + if config.enabled i = 0 - until i >= config[:rules].length do - rule = config[:rules][i] + until i >= config.rules.length + rule = config.rules[i] eval_rule(user, rule, end_result) if end_result.gate_value - if eval_delegate(config[:name], user, rule, end_result) + if eval_delegate(config.name, user, rule, end_result) return end - pass = eval_pass_percent(user, rule, config[:salt]) + pass = eval_pass_percent(user, rule, config.salt) end_result.gate_value = pass - end_result.json_value = pass ? rule[:returnValue] : config[:defaultValue] - end_result.rule_id = rule[:id] - end_result.group_name = rule[:groupName] - end_result.is_experiment_group = rule[:isExperimentGroup] == true + end_result.json_value = pass ? rule.return_value : config.default_value + end_result.rule_id = rule.id + end_result.group_name = rule.group_name + end_result.is_experiment_group = rule.is_experiment_group == true return end @@ -238,7 +246,7 @@ def eval_spec(user, config, end_result) end_result.rule_id = default_rule_id end_result.gate_value = false - end_result.json_value = config[:defaultValue] + end_result.json_value = config.default_value end_result.evaluation_details = EvaluationDetails.new( @spec_store.last_config_sync_time, @spec_store.initial_config_sync_time, @@ -252,8 +260,8 @@ def eval_spec(user, config, end_result) def eval_rule(user, rule, end_result) pass = true i = 0 - until i >= rule[:conditions].length do - result = eval_condition(user, rule[:conditions][i], end_result) + until i >= rule.conditions.length + result = eval_condition(user, rule.conditions[i], end_result) pass = false if result == false i += 1 @@ -263,28 +271,27 @@ def eval_rule(user, rule, end_result) end def eval_delegate(name, user, rule, end_result) - return false unless (delegate = rule[:configDelegate]) + return false unless (delegate = rule.config_delegate) return false unless (config = @spec_store.get_config(delegate)) end_result.undelegated_sec_exps = end_result.secondary_exposures.dup - self.eval_spec(user, config, end_result) + eval_spec(user, config, end_result) end_result.name = name end_result.config_delegate = delegate - end_result.explicit_parameters = config[:explicitParameters] + end_result.explicit_parameters = config.explicit_parameters true end def eval_condition(user, condition, end_result) value = nil - field = condition[:field] - target = condition[:targetValue] - type = condition[:type] - operator = condition[:operator] - additional_values = condition[:additionalValues] - additional_values = Hash.new unless additional_values.is_a? Hash - id_type = condition[:idType] + field = condition.field + target = condition.target_value + type = condition.type + operator = condition.operator + additional_values = condition.additional_values + id_type = condition.id_type case type when :public @@ -319,7 +326,7 @@ def eval_condition(user, condition, end_result) unit_id = user.get_unit_id(id_type) || Const::EMPTY_STR # there are only 1000 user buckets as opposed to 10k for gate pass % value = compute_user_hash("#{salt}.#{unit_id}") % 1000 - rescue + rescue StandardError return false end when :unit_id @@ -329,56 +336,90 @@ def eval_condition(user, condition, end_result) case operator # numerical comparison when :gt - return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a > b }) + return EvaluationHelpers.compare_numbers(value, target, ->(a, b) { a > b }) when :gte - return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a >= b }) + return EvaluationHelpers.compare_numbers(value, target, ->(a, b) { a >= b }) when :lt - return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a < b }) + return EvaluationHelpers.compare_numbers(value, target, ->(a, b) { a < b }) when :lte - return EvaluationHelpers::compare_numbers(value, target, ->(a, b) { a <= b }) + return EvaluationHelpers.compare_numbers(value, target, ->(a, b) { a <= b }) # version comparison # need to check for nil or empty value because Version takes them as valid values when :version_gt return false if value.to_s.empty? - return (Gem::Version.new(value) > Gem::Version.new(target) rescue false) + + return begin + Gem::Version.new(value) > Gem::Version.new(target) + rescue StandardError + false + end when :version_gte return false if value.to_s.empty? - return (Gem::Version.new(value) >= Gem::Version.new(target) rescue false) + + return begin + Gem::Version.new(value) >= Gem::Version.new(target) + rescue StandardError + false + end when :version_lt return false if value.to_s.empty? - return (Gem::Version.new(value) < Gem::Version.new(target) rescue false) + + return begin + Gem::Version.new(value) < Gem::Version.new(target) + rescue StandardError + false + end when :version_lte return false if value.to_s.empty? - return (Gem::Version.new(value) <= Gem::Version.new(target) rescue false) + + return begin + Gem::Version.new(value) <= Gem::Version.new(target) + rescue StandardError + false + end when :version_eq return false if value.to_s.empty? - return (Gem::Version.new(value) == Gem::Version.new(target) rescue false) + + return begin + Gem::Version.new(value) == Gem::Version.new(target) + rescue StandardError + false + end when :version_neq return false if value.to_s.empty? - return (Gem::Version.new(value) != Gem::Version.new(target) rescue false) + + return begin + Gem::Version.new(value) != Gem::Version.new(target) + rescue StandardError + false + end # array operations when :any - return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a == b }) + return EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a == b }) when :none - return !EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a == b }) + return !EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a == b }) when :any_case_sensitive - return EvaluationHelpers::match_string_in_array(target, value, false, ->(a, b) { a == b }) + return EvaluationHelpers.match_string_in_array(target, value, false, ->(a, b) { a == b }) when :none_case_sensitive - return !EvaluationHelpers::match_string_in_array(target, value, false, ->(a, b) { a == b }) + return !EvaluationHelpers.match_string_in_array(target, value, false, ->(a, b) { a == b }) # string when :str_starts_with_any - return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.start_with?(b) }) + return EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a.start_with?(b) }) when :str_ends_with_any - return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.end_with?(b) }) + return EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a.end_with?(b) }) when :str_contains_any - return EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) + return EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) when :str_contains_none - return !EvaluationHelpers::match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) + return !EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) when :str_matches - return (value.is_a?(String) && !(value =~ Regexp.new(target)).nil? rescue false) + return begin + value.is_a?(String) && !(value =~ Regexp.new(target)).nil? + rescue StandardError + false + end when :eq return value == target when :neq @@ -386,11 +427,13 @@ def eval_condition(user, condition, end_result) # dates when :before - return EvaluationHelpers::compare_times(value, target, ->(a, b) { a < b }) + return EvaluationHelpers.compare_times(value, target, ->(a, b) { a < b }) when :after - return EvaluationHelpers::compare_times(value, target, ->(a, b) { a > b }) + return EvaluationHelpers.compare_times(value, target, ->(a, b) { a > b }) when :on - return EvaluationHelpers::compare_times(value, target, ->(a, b) { a.year == b.year && a.month == b.month && a.day == b.day }) + return EvaluationHelpers.compare_times(value, target, lambda { |a, b| + a.year == b.year && a.month == b.month && a.day == b.day + }) when :in_segment_list, :not_in_segment_list begin is_in_list = false @@ -400,8 +443,9 @@ def eval_condition(user, condition, end_result) is_in_list = id_list.ids.include?(hashed_id) end return is_in_list if operator == :in_segment_list + return !is_in_list - rescue + rescue StandardError return false end end @@ -424,8 +468,6 @@ def get_value_from_user(user, field) user.locale when Const::APPVERSION, Const::APP_VERSION user.app_version - else - nil end if value.nil? value = user.custom[field] if user.custom.is_a?(Hash) @@ -438,6 +480,7 @@ def get_value_from_user(user, field) def get_value_from_environment(user, field) return nil unless user.statsig_environment.is_a? Hash + user.statsig_environment.each do |key, value| return value if key.to_s.downcase == (field) end @@ -446,6 +489,7 @@ def get_value_from_environment(user, field) def get_value_from_ip(user, field) return nil unless field == Const::COUNTRY + ip = get_value_from_user(user, Const::IP) return nil unless ip.is_a?(String) @@ -469,25 +513,20 @@ def get_value_from_ua(user, field) when Const::BROWSERVERSION, Const::BROWSER_VERSION parsed = UAParser.parse_ua(ua) return parsed.version.to_s - else - nil end end def eval_pass_percent(user, rule, config_salt) - return false unless config_salt.is_a?(String) && !rule[:passPercentage].nil? - begin - unit_id = user.get_unit_id(rule[:idType]) || Const::EMPTY_STR - rule_salt = rule[:salt] || rule[:id] || Const::EMPTY_STR - hash = compute_user_hash("#{config_salt}.#{rule_salt}.#{unit_id}") - return (hash % 10000) < (rule[:passPercentage].to_f * 100) - rescue - return false - end + unit_id = user.get_unit_id(rule.id_type) || Const::EMPTY_STR + rule_salt = rule.salt || rule.id || Const::EMPTY_STR + hash = compute_user_hash("#{config_salt}.#{rule_salt}.#{unit_id}") + return (hash % 10_000) < (rule.pass_percentage * 100) + rescue StandardError + return false end def compute_user_hash(user_hash) - Digest::SHA256.digest(user_hash).unpack(Const::Q_RIGHT_CHEVRON)[0] + Digest::SHA256.digest(user_hash).unpack1(Const::Q_RIGHT_CHEVRON) end end end diff --git a/lib/spec_store.rb b/lib/spec_store.rb index 1309222..11eaad1 100644 --- a/lib/spec_store.rb +++ b/lib/spec_store.rb @@ -1,14 +1,13 @@ - require 'net/http' require 'uri' require 'evaluation_details' require 'id_list' require 'concurrent-ruby' require 'hash_utils' +require 'api_config' module Statsig class SpecStore - attr_accessor :last_config_sync_time attr_accessor :initial_config_sync_time attr_accessor :init_reason @@ -46,7 +45,7 @@ def initialize(network, options, error_callback, diagnostics, error_boundary, lo options.idlist_threadpool_size, name: 'statsig-idlist', max_queue: 100, - fallback_policy: :discard, + fallback_policy: :discard ) unless @options.bootstrap_values.nil? @@ -58,7 +57,7 @@ def initialize(network, options, error_callback, diagnostics, error_boundary, lo if process_specs(options.bootstrap_values) @init_reason = EvaluationReason::BOOTSTRAP end - rescue + rescue StandardError puts 'the provided bootstrapValues is not a valid JSON string' ensure tracker.end(success: @init_reason == EvaluationReason::BOOTSTRAP) @@ -114,16 +113,19 @@ def has_layer?(layer_name) def get_gate(gate_name) return nil unless has_gate?(gate_name) + @gates[gate_name] end def get_config(config_name) return nil unless has_config?(config_name) + @configs[config_name] end def get_layer(layer_name) return nil unless has_layer?(layer_name) + @layers[layer_name] end @@ -143,12 +145,15 @@ def get_app_id_for_sdk_key(sdk_key) if sdk_key.nil? return nil end + hashed_sdk_key = Statsig::HashUtils.djb2(sdk_key).to_sym if has_hashed_sdk_key?(hashed_sdk_key) return @hashed_sdk_keys_to_app_ids[hashed_sdk_key] end + key = sdk_key.to_sym return nil unless has_sdk_key?(key) + @sdk_keys_to_app_ids[key] end @@ -203,6 +208,7 @@ def save_config_specs_to_storage_adapter(specs_string) if @options.data_store.nil? return end + @options.data_store.set(Interfaces::IDataStore::CONFIG_SPECS_KEY, specs_string) end @@ -256,7 +262,10 @@ def download_config_specs end tracker.end(success: @init_reason == EvaluationReason::NETWORK) - @rules_updated_callback.call(response.body.to_s, @last_config_sync_time) unless response.body.nil? or @rules_updated_callback.nil? + unless response.body.nil? or @rules_updated_callback.nil? + @rules_updated_callback.call(response.body.to_s, + @last_config_sync_time) + end end nil @@ -275,7 +284,7 @@ def process_specs(specs_string, from_adapter: false) return false end - specs_json = JSON.parse(specs_string, {:symbolize_names => true}) + specs_json = JSON.parse(specs_string, { symbolize_names: true }) return false unless specs_json.is_a? Hash hashed_sdk_key_used = specs_json[:hashed_sdk_key_used] @@ -286,10 +295,9 @@ def process_specs(specs_string, from_adapter: false) @last_config_sync_time = specs_json[:time] || @last_config_sync_time return false unless specs_json[:has_updates] == true && - !specs_json[:feature_gates].nil? && - !specs_json[:dynamic_configs].nil? && - !specs_json[:layer_configs].nil? - + !specs_json[:feature_gates].nil? && + !specs_json[:dynamic_configs].nil? && + !specs_json[:layer_configs].nil? new_gates = process_configs(specs_json[:feature_gates]) new_configs = process_configs(specs_json[:dynamic_configs]) @@ -299,9 +307,9 @@ def process_specs(specs_string, from_adapter: false) specs_json[:diagnostics]&.each { |key, value| @diagnostics.sample_rates[key.to_s] = value } if specs_json[:layers].is_a?(Hash) - specs_json[:layers].each { |layer_name, experiments| + specs_json[:layers].each do |layer_name, experiments| experiments.each { |experiment_name| new_exp_to_layer[experiment_name] = layer_name } - } + end end @gates = new_gates @@ -319,35 +327,7 @@ def process_specs(specs_string, from_adapter: false) def process_configs(configs) configs.each_with_object({}) do |config, new_configs| - new_configs[config[:name]] = process_config(config) - end - end - - def process_config(config) - config[:rules] = process_rules(config[:rules]) if config.key?(:rules) - config - end - - def process_rules(rules) - rules.map do |rule| - rule[:conditions] = process_conditions(rule[:conditions]) if rule.key?(:conditions) - rule - end - end - - def process_conditions(conditions) - conditions.map do |condition| - # try symbols for perf - condition[:operator] = condition[:operator].downcase.to_sym unless condition[:operator].nil? - condition[:type] = condition[:type].downcase.to_sym unless condition[:type].nil? - - if condition[:targetValue].is_a?(Array) - # target values are really sets, which will be more performant for evaluation - # for now, create the set - condition[:targetValue] = condition[:targetValue].to_set - end - - condition + new_configs[config[:name]] = APIConfig.from_json(config) end end @@ -369,6 +349,7 @@ def save_id_lists_to_adapter(id_lists_raw_json) if @options.data_store.nil? return end + @options.data_store.set(Interfaces::IDataStore::ID_LISTS_KEY, id_lists_raw_json) end @@ -381,7 +362,7 @@ def get_id_lists_from_network end success = e.nil? && !response.nil? tracker.end(statusCode: code, success: success, sdkRegion: response&.headers&.[]('X-Statsig-Region')) - if !success + unless success return end @@ -389,7 +370,7 @@ def get_id_lists_from_network server_id_lists = JSON.parse(response) process_id_lists(server_id_lists) save_id_lists_to_adapter(response.body.to_s) - rescue + rescue StandardError # Ignored, will try again end end @@ -399,6 +380,7 @@ def process_id_lists(new_id_lists, from_adapter: false) if !new_id_lists.is_a?(Hash) || !local_id_lists.is_a?(Hash) return end + tasks = [] tracker = @diagnostics.track( @@ -413,7 +395,7 @@ def process_id_lists(new_id_lists, from_adapter: false) end delete_lists = [] - local_id_lists.each do |list_name, list| + local_id_lists.each do |list_name, _list| unless new_id_lists.key? list_name delete_lists.push list_name end @@ -449,7 +431,7 @@ def process_id_lists(new_id_lists, from_adapter: false) next end - tasks << Concurrent::Promise.execute(:executor => @id_list_thread_pool) do + tasks << Concurrent::Promise.execute(executor: @id_list_thread_pool) do if from_adapter get_single_id_list_from_adapter(local_list) else @@ -492,7 +474,7 @@ def download_single_id_list(list) content = res.body.to_s success = process_single_id_list(list, content, content_length) save_single_id_list_to_adapter(list.name, content) unless success.nil? || !success - rescue + rescue StandardError tracker.end(success: false) nil end @@ -512,6 +494,7 @@ def process_single_id_list(list, content, content_length = nil, from_adapter: fa lines.each do |li| line = li.strip next if line.length <= 1 + op = line[0] id = line[1..line.length] if op == '+' @@ -528,11 +511,10 @@ def process_single_id_list(list, content, content_length = nil, from_adapter: fa end tracker.end(success: true) return true - rescue + rescue StandardError tracker.end(success: false) return false end end - end -end \ No newline at end of file +end diff --git a/lib/statsig_driver.rb b/lib/statsig_driver.rb index 7dff707..c06d448 100644 --- a/lib/statsig_driver.rb +++ b/lib/statsig_driver.rb @@ -47,7 +47,7 @@ def get_gate_impl(user, gate_name, disable_log_exposure: false, skip_evaluation: if skip_evaluation gate = @store.get_gate(gate_name) return FeatureGate.new(gate_name) if gate.nil? - return FeatureGate.new(gate[:name], target_app_ids: gate[:targetAppIDs]) + return FeatureGate.new(gate.name, target_app_ids: gate.target_app_ids) end user = verify_inputs(user, gate_name, 'gate_name') diff --git a/test/statsig_e2e_test.rb b/test/statsig_e2e_test.rb index 25adff7..e91aaec 100644 --- a/test/statsig_e2e_test.rb +++ b/test/statsig_e2e_test.rb @@ -15,7 +15,7 @@ # - failing (default) returns {number: 4, string: "default", boolean: true} # sample_experiment is a 50/50 experiment with a single parameter, experiment_param # - ("test" or "control" depending on the user's group) -$expected_sync_time = 1631638014811 +$expected_sync_time = 1_631_638_014_811 class StatsigE2ETest < BaseTest suite :StatsigE2ETest @@ -47,12 +47,13 @@ def test_get_feature_gate driver = StatsigDriver.new( SDK_KEY, @options, - lambda { |e| + lambda { |_e| # error callback should not be called on successful initialize assert(false) } ) - gate_without_evaluation = driver.get_gate(@statsig_user, 'always_on_gate', Statsig::GetGateOptions.new(skip_evaluation: true)) + gate_without_evaluation = driver.get_gate(@statsig_user, 'always_on_gate', + Statsig::GetGateOptions.new(skip_evaluation: true)) gate_with_evaluation = driver.get_gate(@statsig_user, 'always_on_gate') assert_equal('always_on_gate', gate_without_evaluation.name) assert_equal(false, gate_without_evaluation.value) @@ -63,7 +64,7 @@ def test_check_feature_gate driver = StatsigDriver.new( SDK_KEY, @options, - lambda { |e| + lambda { |_e| # error callback should not be called on successful initialize assert(false) } @@ -77,7 +78,7 @@ def test_check_feature_gate assert_requested( :post, 'https://statsigapi.net/v1/log_event', - :body => hash_including( + body: hash_including( 'events' => [ hash_including( 'eventName' => 'statsig::gate_exposure', @@ -89,21 +90,24 @@ def test_check_feature_gate 'gate' => 'always_on_gate', 'gateValue' => 'true', 'ruleID' => '6N6Z8ODekNYZ7F8gFdoLP5' - )), + ) + ), hash_including( 'eventName' => 'statsig::gate_exposure', 'metadata' => hash_including( 'gate' => 'on_for_statsig_email', 'gateValue' => 'true', 'ruleID' => '7w9rbTSffLT89pxqpyhuqK' - )), + ) + ), hash_including( 'eventName' => 'statsig::gate_exposure', 'metadata' => hash_including( 'gate' => 'email_not_null', 'gateValue' => 'true', 'ruleID' => '7w9rbTSffLT89pxqpyhuqK' - )), + ) + ), hash_including( 'eventName' => 'statsig::gate_exposure', 'user' => { @@ -113,19 +117,22 @@ def test_check_feature_gate 'gate' => 'on_for_statsig_email', 'gateValue' => 'false', 'ruleID' => 'default' - )), + ) + ), hash_including( 'eventName' => 'statsig::gate_exposure', 'metadata' => hash_including( 'gate' => 'email_not_null', 'gateValue' => 'false', 'ruleID' => 'default' - )), + ) + ) ], 'statsigMetadata' => Statsig.get_statsig_metadata ), - :times => 1) + times: 1 + ) end def test_dynamic_config @@ -148,28 +155,34 @@ def test_dynamic_config assert_requested( :post, 'https://statsigapi.net/v1/log_event', - :body => hash_including( + body: hash_including( 'events' => [ hash_including( 'eventName' => 'statsig::config_exposure', 'metadata' => hash_including( 'config' => 'test_config', 'ruleID' => '1kNmlB23wylPFZi1M0Divl' - )), + ) + ), hash_including( 'eventName' => 'statsig::config_exposure', 'metadata' => hash_including( 'config' => 'test_config', 'ruleID' => 'default' - )), - ]), - :times => 1) + ) + ) + ] + ), + times: 1 + ) end def test_experiment driver = StatsigDriver.new(SDK_KEY, @options) experiment = driver.get_experiment(@random_user, 'sample_experiment') assert(experiment.get('experiment_param', '') == 'control') + puts(experiment.group_name) + puts(experiment.rule_id) assert(experiment.group_name == 'Control') assert(experiment.id_type == 'userID') @@ -183,33 +196,38 @@ def test_experiment assert_requested( :post, 'https://statsigapi.net/v1/log_event', - :body => hash_including( + body: hash_including( 'events' => [ hash_including( 'eventName' => 'statsig::config_exposure', 'metadata' => hash_including( 'config' => 'sample_experiment', 'ruleID' => '2RamGsERWbWMIMnSfOlQuX' - )), + ) + ), hash_including( 'eventName' => 'statsig::config_exposure', 'metadata' => hash_including( 'config' => 'sample_experiment', 'ruleID' => '2RamGujUou6h2bVNQWhtNZ' - )), - ]), - :times => 1) + ) + ) + ] + ), + times: 1 + ) end def test_log_event driver = StatsigDriver.new(SDK_KEY, @options) - driver.log_event(@random_user, 'add_to_cart', 'SKU_12345', { 'price' => '9.99', 'item_name' => 'diet_coke_48_pack' }) + driver.log_event(@random_user, 'add_to_cart', 'SKU_12345', + { 'price' => '9.99', 'item_name' => 'diet_coke_48_pack' }) driver.shutdown assert_requested( :post, 'https://statsigapi.net/v1/log_event', - :body => hash_including( + body: hash_including( 'events' => [ hash_including( 'eventName' => 'add_to_cart', @@ -219,11 +237,13 @@ def test_log_event 'item_name' => 'diet_coke_48_pack' }, 'user' => hash_including( - 'userID' => "random" + 'userID' => 'random' ) - ), - ]), - :times => 1) + ) + ] + ), + times: 1 + ) end def test_bootstrap_option @@ -235,7 +255,7 @@ def test_bootstrap_option # with network, rules_updated_callback gets called when there are updated rulesets coming back from server callback_validated = false options = StatsigOptions.new(rulesets_sync_interval: 0.1, rules_updated_callback: lambda { |rules, time| - if rules == @@mock_response && time == 1631638014811 + if rules == @@mock_response && time == 1_631_638_014_811 callback_validated = true end }) @@ -244,5 +264,4 @@ def test_bootstrap_option assert_equal(true, callback_validated) driver.shutdown end - -end \ No newline at end of file +end From 711f91ca9c9cee89d71e6ef6d1eaa33f4b9decb6 Mon Sep 17 00:00:00 2001 From: tore-statsig <74584483+tore-statsig@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:13:39 -0800 Subject: [PATCH 14/16] Find unsupported configs up front (#286) --- lib/api_config.rb | 211 ++++++++++++++++++++++---------------- lib/constants.rb | 12 +++ lib/evaluation_details.rb | 4 + lib/evaluator.rb | 36 ++++--- lib/spec_store.rb | 10 +- 5 files changed, 167 insertions(+), 106 deletions(-) diff --git a/lib/api_config.rb b/lib/api_config.rb index ca50e54..55ca7f6 100644 --- a/lib/api_config.rb +++ b/lib/api_config.rb @@ -1,105 +1,134 @@ -class APIConfig - attr_accessor :name, :type, :is_active, :salt, :default_value, :enabled, - :rules, :id_type, :entity, :explicit_parameters, :has_shared_params, :target_app_ids - - def initialize(name:, type:, is_active:, salt:, default_value:, enabled:, rules:, id_type:, entity:, - explicit_parameters: nil, has_shared_params: nil, target_app_ids: nil) - @name = name - @type = type.to_sym unless entity.nil? - @is_active = is_active - @salt = salt - @default_value = default_value - @enabled = enabled - @rules = rules - @id_type = id_type - @entity = entity.to_sym unless entity.nil? - @explicit_parameters = explicit_parameters - @has_shared_params = has_shared_params - @target_app_ids = target_app_ids - end +require 'constants' - def self.from_json(json) - new( - name: json[:name], - type: json[:type], - is_active: json[:isActive], - salt: json[:salt], - default_value: json[:defaultValue], - enabled: json[:enabled], - rules: json[:rules]&.map do |rule| - APIRule.from_json(rule) - end, - id_type: json[:idType], - entity: json[:entity], - explicit_parameters: json[:explicitParameters], - has_shared_params: json[:hasSharedParams], - target_app_ids: json[:targetAppIDs] - ) - end +class UnsupportedConfigException < StandardError end -class APIRule - attr_accessor :name, :pass_percentage, :return_value, :id, :salt, - :conditions, :id_type, :group_name, :config_delegate, :is_experiment_group - - def initialize(name:, pass_percentage:, return_value:, id:, salt:, conditions:, id_type:, - group_name: nil, config_delegate: nil, is_experiment_group: nil) - @name = name - @pass_percentage = pass_percentage.to_f - @return_value = return_value - @id = id - @salt = salt - @conditions = conditions - @id_type = id_type - @group_name = group_name - @config_delegate = config_delegate - @is_experiment_group = is_experiment_group - end +module Statsig + class APIConfig + attr_accessor :name, :type, :is_active, :salt, :default_value, :enabled, + :rules, :id_type, :entity, :explicit_parameters, :has_shared_params, :target_app_ids + + def initialize(name:, type:, is_active:, salt:, default_value:, enabled:, rules:, id_type:, entity:, + explicit_parameters: nil, has_shared_params: nil, target_app_ids: nil) + @name = name + @type = type.to_sym unless entity.nil? + @is_active = is_active + @salt = salt + @default_value = default_value + @enabled = enabled + @rules = rules + @id_type = id_type + @entity = entity.to_sym unless entity.nil? + @explicit_parameters = explicit_parameters + @has_shared_params = has_shared_params + @target_app_ids = target_app_ids + end - def self.from_json(json) - new( - name: json[:name], - pass_percentage: json[:passPercentage], - return_value: json[:returnValue], - id: json[:id], - salt: json[:salt], - conditions: json[:conditions]&.map do |condition| - APICondition.from_json(condition) - end, - id_type: json[:idType], - group_name: json[:groupName], - config_delegate: json[:configDelegate], - is_experiment_group: json[:isExperimentGroup] - ) + def self.from_json(json) + new( + name: json[:name], + type: json[:type], + is_active: json[:isActive], + salt: json[:salt], + default_value: json[:defaultValue], + enabled: json[:enabled], + rules: json[:rules]&.map do |rule| + APIRule.from_json(rule) + end, + id_type: json[:idType], + entity: json[:entity], + explicit_parameters: json[:explicitParameters], + has_shared_params: json[:hasSharedParams], + target_app_ids: json[:targetAppIDs] + ) + end end end -class APICondition - attr_accessor :type, :target_value, :operator, :field, :additional_values, :id_type +module Statsig + class APIRule - def initialize(type:, target_value:, operator:, field:, additional_values:, id_type:) - @type = type.to_sym unless type.nil? - @target_value = target_value - @operator = operator.to_sym unless operator.nil? - @field = field - @additional_values = additional_values || {} - @id_type = id_type - end + attr_accessor :name, :pass_percentage, :return_value, :id, :salt, + :conditions, :id_type, :group_name, :config_delegate, :is_experiment_group + + def initialize(name:, pass_percentage:, return_value:, id:, salt:, conditions:, id_type:, + group_name: nil, config_delegate: nil, is_experiment_group: nil) + @name = name + @pass_percentage = pass_percentage.to_f + @return_value = return_value + @id = id + @salt = salt + @conditions = conditions + @id_type = id_type + @group_name = group_name + @config_delegate = config_delegate + @is_experiment_group = is_experiment_group + end - def self.from_json(json) - new( - type: json[:type], - target_value: process_target_value(json[:targetValue], json[:operator], json[:type]), - operator: json[:operator], - field: json[:field], - additional_values: json[:additionalValues], - id_type: json[:idType] - ) + def self.from_json(json) + new( + name: json[:name], + pass_percentage: json[:passPercentage], + return_value: json[:returnValue], + id: json[:id], + salt: json[:salt], + conditions: json[:conditions]&.map do |condition| + APICondition.from_json(condition) + end, + id_type: json[:idType], + group_name: json[:groupName], + config_delegate: json[:configDelegate], + is_experiment_group: json[:isExperimentGroup] + ) + end end +end + +module Statsig + class APICondition + + attr_accessor :type, :target_value, :operator, :field, :additional_values, :id_type + + def initialize(type:, target_value:, operator:, field:, additional_values:, id_type:) + @type = type.to_sym unless type.nil? + @target_value = target_value + @operator = operator.to_sym unless operator.nil? + @field = field + @additional_values = additional_values || {} + @id_type = id_type + end + + def self.from_json(json) + operator = json[:operator] + unless operator.nil? + operator = operator&.downcase&.to_sym + unless Const::SUPPORTED_OPERATORS.include?(operator) + raise UnsupportedConfigException + end + end + + type = json[:type] + unless type.nil? + type = type&.downcase&.to_sym + unless Const::SUPPORTED_CONDITION_TYPES.include?(type) + raise UnsupportedConfigException + end + end + + new( + type: json[:type], + target_value: process_target_value(json[:targetValue], json[:operator], json[:type]), + operator: json[:operator], + field: json[:field], + additional_values: json[:additionalValues], + id_type: json[:idType] + ) + end - def self.process_target_value(target_value, _operator, _type) - return target_value unless target_value.is_a?(Array) + def self.process_target_value(target_value, _operator, _type) + return target_value unless target_value.is_a?(Array) - target_value.to_set + target_value.to_set + end end end diff --git a/lib/constants.rb b/lib/constants.rb index 2ece25d..0d5a9f5 100644 --- a/lib/constants.rb +++ b/lib/constants.rb @@ -2,6 +2,18 @@ module Statsig module Const EMPTY_STR = ''.freeze + SUPPORTED_CONDITION_TYPES = Set.new(%i[ + public fail_gate pass_gate ip_based ua_based user_field + environment_field current_time user_bucket unit_id + ]).freeze + + SUPPORTED_OPERATORS = Set.new(%i[ + gt gte lt lte version_gt version_gte version_lt version_lte + version_eq version_neq any none any_case_sensitive none_case_sensitive + str_starts_with_any str_ends_with_any str_contains_any str_contains_none + str_matches eq neq before after on in_segment_list not_in_segment_list + ]).freeze + APP_VERSION = 'app_version'.freeze APPVERSION = 'appversion'.freeze BROWSER_NAME = 'browser_name'.freeze diff --git a/lib/evaluation_details.rb b/lib/evaluation_details.rb index 187daa6..c6a1580 100644 --- a/lib/evaluation_details.rb +++ b/lib/evaluation_details.rb @@ -24,6 +24,10 @@ def initialize(config_sync_time, init_time, reason) @server_time = (Time.now.to_i * 1000).to_s end + def self.unsupported(config_sync_time, init_time) + EvaluationDetails.new(config_sync_time, init_time, EvaluationReason::UNSUPPORTED) + end + def self.unrecognized(config_sync_time, init_time) EvaluationDetails.new(config_sync_time, init_time, EvaluationReason::UNRECOGNIZED) end diff --git a/lib/evaluator.rb b/lib/evaluator.rb index 1a8d7db..dfa8419 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -13,7 +13,6 @@ module Statsig class Evaluator - UNSUPPORTED_EVALUATION = :unsupported_eval attr_accessor :spec_store @@ -54,9 +53,7 @@ def check_gate(user, gate_name) end unless @spec_store.has_gate?(gate_name) - return Statsig::ConfigResult.new(gate_name, - evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time)) + return unsupported_or_unrecognized(gate_name) end result = Statsig::ConfigResult.new(gate_name) @@ -86,13 +83,7 @@ def get_config(user, config_name, user_persisted_values: nil) end unless @spec_store.has_config?(config_name) - return Statsig::ConfigResult.new( - config_name, - evaluation_details: EvaluationDetails.unrecognized( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time - ) - ) + return unsupported_or_unrecognized(config_name) end config = @spec_store.get_config(config_name) @@ -124,9 +115,7 @@ def get_layer(user, layer_name) end unless @spec_store.has_layer?(layer_name) - return Statsig::ConfigResult.new(layer_name, - evaluation_details: EvaluationDetails.unrecognized(@spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time)) + return unsupported_or_unrecognized(layer_name) end result = Statsig::ConfigResult.new(layer_name) @@ -201,6 +190,25 @@ def shutdown @spec_store.shutdown end + def unsupported_or_unrecognized(config_name) + if @spec_store.unsupported_configs.include?(config_name) + return Statsig::ConfigResult.new( + config_name, + evaluation_details: EvaluationDetails.unsupported( + @spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time + ) + ) + end + return Statsig::ConfigResult.new( + config_name, + evaluation_details: EvaluationDetails.unrecognized( + @spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time + ) + ) + end + def override_gate(gate, value) @gate_overrides[gate] = value end diff --git a/lib/spec_store.rb b/lib/spec_store.rb index 11eaad1..ec6a6f5 100644 --- a/lib/spec_store.rb +++ b/lib/spec_store.rb @@ -18,6 +18,7 @@ class SpecStore attr_accessor :experiment_to_layer attr_accessor :sdk_keys_to_app_ids attr_accessor :hashed_sdk_keys_to_app_ids + attr_accessor :unsupported_configs def initialize(network, options, error_callback, diagnostics, error_boundary, logger, secret_key) @init_reason = EvaluationReason::UNINITIALIZED @@ -40,6 +41,7 @@ def initialize(network, options, error_callback, diagnostics, error_boundary, lo @error_boundary = error_boundary @logger = logger @secret_key = secret_key + @unsupported_configs = Set.new @id_list_thread_pool = Concurrent::FixedThreadPool.new( options.idlist_threadpool_size, @@ -299,6 +301,7 @@ def process_specs(specs_string, from_adapter: false) !specs_json[:dynamic_configs].nil? && !specs_json[:layer_configs].nil? + @unsupported_configs.clear() new_gates = process_configs(specs_json[:feature_gates]) new_configs = process_configs(specs_json[:dynamic_configs]) new_layers = process_configs(specs_json[:layer_configs]) @@ -327,7 +330,12 @@ def process_specs(specs_string, from_adapter: false) def process_configs(configs) configs.each_with_object({}) do |config, new_configs| - new_configs[config[:name]] = APIConfig.from_json(config) + begin + new_configs[config[:name]] = APIConfig.from_json(config) + rescue UnsupportedConfigException => e + @unsupported_configs.add(config[:name]) + nil + end end end From bd32404771e0c191f3b7676433c3eed13c984e37 Mon Sep 17 00:00:00 2001 From: Daniel <95646168+daniel-statsig@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:19:21 -0800 Subject: [PATCH 15/16] Rm eval details 4 (#290) --- lib/api_config.rb | 8 +- lib/client_initialize_helpers.rb | 21 +++-- lib/config_result.rb | 5 +- lib/evaluation_helpers.rb | 37 +++++++- lib/evaluator.rb | 151 +++++++++++++++++-------------- 5 files changed, 134 insertions(+), 88 deletions(-) diff --git a/lib/api_config.rb b/lib/api_config.rb index 55ca7f6..3ce1f9e 100644 --- a/lib/api_config.rb +++ b/lib/api_config.rb @@ -117,18 +117,12 @@ def self.from_json(json) new( type: json[:type], - target_value: process_target_value(json[:targetValue], json[:operator], json[:type]), + target_value: json[:targetValue], operator: json[:operator], field: json[:field], additional_values: json[:additionalValues], id_type: json[:idType] ) end - - def self.process_target_value(target_value, _operator, _type) - return target_value unless target_value.is_a?(Array) - - target_value.to_set - end end end diff --git a/lib/client_initialize_helpers.rb b/lib/client_initialize_helpers.rb index 008ab1f..e9d242a 100644 --- a/lib/client_initialize_helpers.rb +++ b/lib/client_initialize_helpers.rb @@ -4,11 +4,11 @@ module Statsig class ResponseFormatter - def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) + def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo, include_exposures: true) result = {} entities.each do |name, spec| - hashed_name, value = to_response(name, spec, evaluator, user, client_sdk_key, hash_algo) + hashed_name, value = to_response(name, spec, evaluator, user, client_sdk_key, hash_algo, include_exposures) if !hashed_name.nil? && !value.nil? result[hashed_name] = value end @@ -17,7 +17,7 @@ def self.get_responses(entities, evaluator, user, client_sdk_key, hash_algo) result end - def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash_algo) + def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, hash_algo, include_exposures) target_app_id = evaluator.spec_store.get_app_id_for_sdk_key(client_sdk_key) config_target_apps = config_spec.target_app_ids @@ -31,7 +31,7 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, return nil end - eval_result = ConfigResult.new(config_name) + eval_result = ConfigResult.new(config_name, disable_evaluation_details: true) evaluator.eval_spec(user, config_spec, eval_result) result = {} @@ -58,7 +58,7 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, end if entity_type == :layer - populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo) + populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo, include_exposures) result.delete(:id_type) # not exposed for layer configs in /initialize end @@ -66,7 +66,10 @@ def self.to_response(config_name, config_spec, evaluator, user, client_sdk_key, result[:name] = hashed_name result[:rule_id] = eval_result.rule_id - result[:secondary_exposures] = clean_exposures(eval_result.secondary_exposures) + + if include_exposures + result[:secondary_exposures] = clean_exposures(eval_result.secondary_exposures) + end [hashed_name, result] end @@ -101,7 +104,7 @@ def self.populate_experiment_fields(config_name, config_spec, eval_result, resul result[:value] = layer[:defaultValue].merge(result[:value]) end - def self.populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo) + def self.populate_layer_fields(config_spec, eval_result, result, evaluator, hash_algo, include_exposures) delegate = eval_result.config_delegate result[:explicit_parameters] = config_spec.explicit_parameters || [] @@ -114,7 +117,9 @@ def self.populate_layer_fields(config_spec, eval_result, result, evaluator, hash result[:explicit_parameters] = delegate_spec.explicit_parameters || [] end - result[:undelegated_secondary_exposures] = clean_exposures(eval_result.undelegated_sec_exps || []) + if include_exposures + result[:undelegated_secondary_exposures] = clean_exposures(eval_result.undelegated_sec_exps || []) + end end def self.hash_name(name, hash_algo) diff --git a/lib/config_result.rb b/lib/config_result.rb index e027e75..cccfdde 100644 --- a/lib/config_result.rb +++ b/lib/config_result.rb @@ -14,6 +14,7 @@ class ConfigResult attr_accessor :group_name attr_accessor :id_type attr_accessor :target_app_ids + attr_accessor :disable_evaluation_details def initialize( name, @@ -27,7 +28,8 @@ def initialize( evaluation_details: nil, group_name: nil, id_type: '', - target_app_ids: nil) + target_app_ids: nil, + disable_evaluation_details: false) @name = name @gate_value = gate_value @json_value = json_value @@ -41,6 +43,7 @@ def initialize( @group_name = group_name @id_type = id_type @target_app_ids = target_app_ids + @disable_evaluation_details = disable_evaluation_details end def self.from_user_persisted_values(config_name, user_persisted_values) diff --git a/lib/evaluation_helpers.rb b/lib/evaluation_helpers.rb index cdcf1e6..2a41015 100644 --- a/lib/evaluation_helpers.rb +++ b/lib/evaluation_helpers.rb @@ -1,4 +1,3 @@ - require 'time' module EvaluationHelpers @@ -10,7 +9,40 @@ def self.compare_numbers(a, b, func) # returns true if array has any element that evaluates to true with value using func lambda, ignoring case def self.match_string_in_array(array, value, ignore_case, func) str_value = value.to_s - array.any?{ |s| !s.nil? && ((ignore_case && func.call(str_value.downcase, s.to_s.downcase)) || func.call(str_value, s.to_s)) } rescue false + str_value_downcased = nil + + return false if array.nil? + + return array.any? do |item| + next false if item.nil? + item_str = item.to_s + + return true if func.call(str_value, item_str) + next false unless ignore_case + + str_value_downcased ||= str_value.downcase + func.call(str_value_downcased, item_str.downcase) + end + end + + def self.equal_string_in_array(array, value, ignore_case) + str_value = value.to_s + str_value_downcased = nil + + return false if array.nil? + + return array.any? do |item| + next false if item.nil? + item_str = item.to_s + + next false unless item_str.length == str_value.length + + return true if item_str == str_value + next false unless ignore_case + + str_value_downcased ||= str_value.downcase + item_str.downcase == str_value_downcased + end end def self.compare_times(a, b, func) @@ -26,6 +58,7 @@ def self.compare_times(a, b, func) private def self.is_numeric(v) + return true if v.is_a?(Numeric) !(v.to_s =~ /\A[-+]?\d*\.?\d+\z/).nil? end diff --git a/lib/evaluator.rb b/lib/evaluator.rb index dfa8419..e27a529 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -158,12 +158,12 @@ def get_client_initialize_response(user, hash_algo, client_sdk_key) end { - feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, client_sdk_key, - hash_algo), - dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, client_sdk_key, - hash_algo), - layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, client_sdk_key, - hash_algo), + feature_gates: Statsig::ResponseFormatter + .get_responses(@spec_store.gates, self, user, client_sdk_key, hash_algo), + dynamic_configs: Statsig::ResponseFormatter + .get_responses(@spec_store.configs, self, user, client_sdk_key, hash_algo), + layer_configs: Statsig::ResponseFormatter + .get_responses(@spec_store.layers, self, user, client_sdk_key, hash_algo), sdkParams: {}, has_updates: true, generator: Const::STATSIG_RUBY_SDK, @@ -180,9 +180,12 @@ def get_all_evaluations(user) end { - feature_gates: Statsig::ResponseFormatter.get_responses(@spec_store.gates, self, user, nil, 'none'), - dynamic_configs: Statsig::ResponseFormatter.get_responses(@spec_store.configs, self, user, nil, 'none'), - layer_configs: Statsig::ResponseFormatter.get_responses(@spec_store.layers, self, user, nil, 'none') + feature_gates: Statsig::ResponseFormatter + .get_responses(@spec_store.gates, self, user, nil, 'none', include_exposures: false), + dynamic_configs: Statsig::ResponseFormatter + .get_responses(@spec_store.configs, self, user, nil, 'none', include_exposures: false), + layer_configs: Statsig::ResponseFormatter + .get_responses(@spec_store.layers, self, user, nil, 'none', include_exposures: false) } end @@ -220,11 +223,15 @@ def override_config(config, value) def eval_spec(user, config, end_result) end_result.id_type = config.id_type end_result.target_app_ids = config.target_app_ids - end_result.evaluation_details = EvaluationDetails.new( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time, - @spec_store.init_reason - ) + + if end_result.disable_evaluation_details != true + end_result.evaluation_details = EvaluationDetails.new( + @spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time, + @spec_store.init_reason + ) + end + default_rule_id = Const::DEFAULT if config.enabled i = 0 @@ -255,11 +262,6 @@ def eval_spec(user, config, end_result) end_result.rule_id = default_rule_id end_result.gate_value = false end_result.json_value = config.default_value - end_result.evaluation_details = EvaluationDetails.new( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time, - @spec_store.init_reason - ) end_result.group_name = nil end @@ -271,7 +273,7 @@ def eval_rule(user, rule, end_result) until i >= rule.conditions.length result = eval_condition(user, rule.conditions[i], end_result) - pass = false if result == false + pass = false if result != true i += 1 end @@ -358,60 +360,60 @@ def eval_condition(user, condition, end_result) return false if value.to_s.empty? return begin - Gem::Version.new(value) > Gem::Version.new(target) - rescue StandardError - false - end + Gem::Version.new(value) > Gem::Version.new(target) + rescue StandardError + false + end when :version_gte return false if value.to_s.empty? return begin - Gem::Version.new(value) >= Gem::Version.new(target) - rescue StandardError - false - end + Gem::Version.new(value) >= Gem::Version.new(target) + rescue StandardError + false + end when :version_lt return false if value.to_s.empty? return begin - Gem::Version.new(value) < Gem::Version.new(target) - rescue StandardError - false - end + Gem::Version.new(value) < Gem::Version.new(target) + rescue StandardError + false + end when :version_lte return false if value.to_s.empty? return begin - Gem::Version.new(value) <= Gem::Version.new(target) - rescue StandardError - false - end + Gem::Version.new(value) <= Gem::Version.new(target) + rescue StandardError + false + end when :version_eq return false if value.to_s.empty? return begin - Gem::Version.new(value) == Gem::Version.new(target) - rescue StandardError - false - end + Gem::Version.new(value) == Gem::Version.new(target) + rescue StandardError + false + end when :version_neq return false if value.to_s.empty? return begin - Gem::Version.new(value) != Gem::Version.new(target) - rescue StandardError - false - end + Gem::Version.new(value) != Gem::Version.new(target) + rescue StandardError + false + end # array operations when :any - return EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a == b }) + return EvaluationHelpers::equal_string_in_array(target, value, true) when :none - return !EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a == b }) + return !EvaluationHelpers::equal_string_in_array(target, value, true) when :any_case_sensitive - return EvaluationHelpers.match_string_in_array(target, value, false, ->(a, b) { a == b }) + return EvaluationHelpers::equal_string_in_array(target, value, false) when :none_case_sensitive - return !EvaluationHelpers.match_string_in_array(target, value, false, ->(a, b) { a == b }) + return !EvaluationHelpers::equal_string_in_array(target, value, false) # string when :str_starts_with_any @@ -424,10 +426,10 @@ def eval_condition(user, condition, end_result) return !EvaluationHelpers.match_string_in_array(target, value, true, ->(a, b) { a.include?(b) }) when :str_matches return begin - value.is_a?(String) && !(value =~ Regexp.new(target)).nil? - rescue StandardError - false - end + value&.is_a?(String) && !(value =~ Regexp.new(target)).nil? + rescue StandardError + false + end when :eq return value == target when :neq @@ -440,8 +442,8 @@ def eval_condition(user, condition, end_result) return EvaluationHelpers.compare_times(value, target, ->(a, b) { a > b }) when :on return EvaluationHelpers.compare_times(value, target, lambda { |a, b| - a.year == b.year && a.month == b.month && a.day == b.day - }) + a.year == b.year && a.month == b.month && a.day == b.day + }) when :in_segment_list, :not_in_segment_list begin is_in_list = false @@ -461,22 +463,9 @@ def eval_condition(user, condition, end_result) end def get_value_from_user(user, field) - value = case field.downcase - when Const::USERID, Const::USER_ID - user.user_id - when Const::EMAIL - user.email - when Const::IP - user.ip - when Const::USERAGENT, Const::USER_AGENT - user.user_agent - when Const::COUNTRY - user.country - when Const::LOCALE - user.locale - when Const::APPVERSION, Const::APP_VERSION - user.app_version - end + value = get_value_from_user_field(user, field) + value ||= get_value_from_user_field(user, field.downcase) + if value.nil? value = user.custom[field] if user.custom.is_a?(Hash) value = user.custom[field.to_sym] if value.nil? && user.custom.is_a?(Hash) @@ -486,6 +475,27 @@ def get_value_from_user(user, field) value end + def get_value_from_user_field(user, field) + case field + when Const::USERID, Const::USER_ID + user.user_id + when Const::EMAIL + user.email + when Const::IP + user.ip + when Const::USERAGENT, Const::USER_AGENT + user.user_agent + when Const::COUNTRY + user.country + when Const::LOCALE + user.locale + when Const::APPVERSION, Const::APP_VERSION + user.app_version + else + nil + end + end + def get_value_from_environment(user, field) return nil unless user.statsig_environment.is_a? Hash @@ -536,5 +546,6 @@ def eval_pass_percent(user, rule, config_salt) def compute_user_hash(user_hash) Digest::SHA256.digest(user_hash).unpack1(Const::Q_RIGHT_CHEVRON) end + end end From e5c1cb6992847c6bf9816ec83d6a260a4f0da81b Mon Sep 17 00:00:00 2001 From: tore-statsig <74584483+tore-statsig@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:31:35 -0800 Subject: [PATCH 16/16] Add eval_gate helper for nested gate checks (#289) --- lib/evaluator.rb | 68 +++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/lib/evaluator.rb b/lib/evaluator.rb index e27a529..97ed02e 100644 --- a/lib/evaluator.rb +++ b/lib/evaluator.rb @@ -36,29 +36,31 @@ def maybe_restart_background_threads end def check_gate(user, gate_name) - if @gate_overrides.has_key?(gate_name) - return Statsig::ConfigResult.new( - gate_name, - @gate_overrides[gate_name], - @gate_overrides[gate_name], - Const::OVERRIDE, - [], - evaluation_details: EvaluationDetails.local_override(@spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time) - ) + result = Statsig::ConfigResult.new(gate_name) + eval_gate(user, gate_name, result) + result + end + + def eval_gate(user, gate_name, end_result) + if @gate_overrides.key?(gate_name) + end_result.gate_value = @gate_overrides[gate_name] + end_result.rule_id = Const::OVERRIDE + end_result.evaluation_details = EvaluationDetails.local_override(@spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time) + return end if @spec_store.init_reason == EvaluationReason::UNINITIALIZED - return Statsig::ConfigResult.new(gate_name, evaluation_details: EvaluationDetails.uninitialized) + end_result.evaluation_details = EvaluationDetails.uninitialized + return end unless @spec_store.has_gate?(gate_name) - return unsupported_or_unrecognized(gate_name) + unsupported_or_unrecognized(gate_name, end_result) + return end - result = Statsig::ConfigResult.new(gate_name) - eval_spec(user, @spec_store.get_gate(gate_name), result) - result + eval_spec(user, @spec_store.get_gate(gate_name), end_result) end def get_config(user, config_name, user_persisted_values: nil) @@ -83,7 +85,9 @@ def get_config(user, config_name, user_persisted_values: nil) end unless @spec_store.has_config?(config_name) - return unsupported_or_unrecognized(config_name) + result = Statsig::ConfigResult.new(config_name) + unsupported_or_unrecognized(config_name, result) + return result end config = @spec_store.get_config(config_name) @@ -115,7 +119,9 @@ def get_layer(user, layer_name) end unless @spec_store.has_layer?(layer_name) - return unsupported_or_unrecognized(layer_name) + result = Statsig::ConfigResult.new(layer_name) + unsupported_or_unrecognized(layer_name, result) + return result end result = Statsig::ConfigResult.new(layer_name) @@ -193,22 +199,17 @@ def shutdown @spec_store.shutdown end - def unsupported_or_unrecognized(config_name) + def unsupported_or_unrecognized(config_name, end_result) if @spec_store.unsupported_configs.include?(config_name) - return Statsig::ConfigResult.new( - config_name, - evaluation_details: EvaluationDetails.unsupported( - @spec_store.last_config_sync_time, - @spec_store.initial_config_sync_time - ) - ) - end - return Statsig::ConfigResult.new( - config_name, - evaluation_details: EvaluationDetails.unrecognized( + end_result.evaluation_details = EvaluationDetails.unsupported( @spec_store.last_config_sync_time, @spec_store.initial_config_sync_time ) + return + end + end_result.evaluation_details = EvaluationDetails.unrecognized( + @spec_store.last_config_sync_time, + @spec_store.initial_config_sync_time ) end @@ -307,17 +308,14 @@ def eval_condition(user, condition, end_result) when :public return true when :fail_gate, :pass_gate - other_gate_result = check_gate(user, target) + eval_gate(user, target, end_result) - gate_value = other_gate_result.gate_value + gate_value = end_result.gate_value new_exposure = { gate: target, gateValue: gate_value ? Const::TRUE : Const::FALSE, - ruleID: other_gate_result.rule_id + ruleID: end_result.rule_id } - if other_gate_result.secondary_exposures.length > 0 - end_result.secondary_exposures.concat(other_gate_result.secondary_exposures) - end end_result.secondary_exposures.append(new_exposure) return type == :pass_gate ? gate_value : !gate_value when :ip_based