optify-config 1.15.2 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/optify_ruby/Cargo.toml +2 -2
- data/ext/optify_ruby/src/lib.rs +45 -56
- data/ext/optify_ruby/src/preferences.rs +60 -0
- data/lib/optify.rb +1 -1
- data/lib/optify_ruby/provider_module.rb +22 -20
- data/lib/optify_ruby/watcher_implementation.rb +1 -1
- data/rbi/optify.rbi +12 -0
- data/sig/optify.rbs +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61fd9d81e7b8808f374f13e8859da5f875ae2d57e6438ece70f905d92e370955
|
4
|
+
data.tar.gz: 4d3ccb53cea8d3c09519c7ec960735bb1fb49b03f2d6afbab2fc56f6d6ecb3e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5f9f06f4f98e1ecf052a39f608a09900631eaf9cd8338a3a1e58468e84c7e59858b673e74b9b944c20f89c9e575d8eebbb3e142778e6a95a4e13e6926fd7b44
|
7
|
+
data.tar.gz: dd9f9b8a273198cfb52a7a017fd607a49111e21611019112dcaeac919eaa5bc7fefdc9119191910f05ec7dcd54c7f6aa5fa0ae856570fa8547301c5457d93027
|
data/ext/optify_ruby/Cargo.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[package]
|
2
2
|
name = "optify_ruby"
|
3
|
-
version = "0.
|
3
|
+
version = "0.18.0"
|
4
4
|
edition = "2021"
|
5
5
|
|
6
6
|
description = "optify bindings for Ruby"
|
@@ -21,6 +21,6 @@ crate-type = ["cdylib"]
|
|
21
21
|
|
22
22
|
[dependencies]
|
23
23
|
magnus = "0.8.0"
|
24
|
-
optify = { path = "../../../../rust/optify", version = "0.
|
24
|
+
optify = { path = "../../../../rust/optify", version = "0.19.0" }
|
25
25
|
rb-sys = { version = "*", default-features = false, features = ["ruby-static"] }
|
26
26
|
serde_json = "1.0.143"
|
data/ext/optify_ruby/src/lib.rs
CHANGED
@@ -2,69 +2,16 @@ use magnus::{function, method, prelude::*, wrap, Object, Ruby};
|
|
2
2
|
use optify::builder::OptionsProviderBuilder;
|
3
3
|
use optify::builder::OptionsRegistryBuilder;
|
4
4
|
use optify::builder::OptionsWatcherBuilder;
|
5
|
-
use optify::provider::GetOptionsPreferences;
|
6
5
|
use optify::provider::OptionsProvider;
|
7
6
|
use optify::provider::OptionsRegistry;
|
8
7
|
use optify::provider::OptionsWatcher;
|
9
8
|
use optify::schema::metadata::OptionsMetadata;
|
10
9
|
use std::cell::RefCell;
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
) -> std::cell::Ref<'_, GetOptionsPreferences> {
|
15
|
-
preferences.0.borrow()
|
16
|
-
}
|
17
|
-
|
18
|
-
#[derive(Clone)]
|
19
|
-
#[wrap(class = "Optify::GetOptionsPreferences")]
|
20
|
-
struct MutGetOptionsPreferences(RefCell<GetOptionsPreferences>);
|
21
|
-
|
22
|
-
impl MutGetOptionsPreferences {
|
23
|
-
fn new() -> Self {
|
24
|
-
Self(RefCell::new(GetOptionsPreferences {
|
25
|
-
constraints: None,
|
26
|
-
overrides_json: None,
|
27
|
-
skip_feature_name_conversion: false,
|
28
|
-
}))
|
29
|
-
}
|
30
|
-
|
31
|
-
// Constraints Section
|
32
|
-
fn set_constraints_json(&self, constraints_json: Option<String>) {
|
33
|
-
self.0
|
34
|
-
.borrow_mut()
|
35
|
-
.set_constraints_json(constraints_json.as_deref());
|
36
|
-
}
|
37
|
-
|
38
|
-
fn get_constraints_json(&self) -> Option<String> {
|
39
|
-
self.0
|
40
|
-
.borrow()
|
41
|
-
.constraints
|
42
|
-
.as_ref()
|
43
|
-
.map(|c| serde_json::to_string(&c.constraints).unwrap())
|
44
|
-
}
|
45
|
-
|
46
|
-
// Overrides Section
|
47
|
-
fn has_overrides(&self) -> bool {
|
48
|
-
self.0.borrow().overrides_json.is_some()
|
49
|
-
}
|
50
|
-
|
51
|
-
fn set_overrides_json(&self, overrides: Option<String>) {
|
52
|
-
self.0.borrow_mut().overrides_json = overrides;
|
53
|
-
}
|
54
|
-
|
55
|
-
fn get_overrides_json(&self) -> Option<String> {
|
56
|
-
self.0.borrow().overrides_json.clone()
|
57
|
-
}
|
58
|
-
|
59
|
-
// Skip Feature Name Conversion Section
|
60
|
-
fn set_skip_feature_name_conversion(&self, value: bool) {
|
61
|
-
self.0.borrow_mut().skip_feature_name_conversion = value;
|
62
|
-
}
|
11
|
+
use crate::preferences::convert_preferences;
|
12
|
+
use crate::preferences::MutGetOptionsPreferences;
|
63
13
|
|
64
|
-
|
65
|
-
self.0.borrow().skip_feature_name_conversion
|
66
|
-
}
|
67
|
-
}
|
14
|
+
mod preferences;
|
68
15
|
|
69
16
|
#[wrap(class = "Optify::OptionsProvider")]
|
70
17
|
struct WrappedOptionsProvider(RefCell<OptionsProvider>);
|
@@ -180,6 +127,23 @@ impl WrappedOptionsProvider {
|
|
180
127
|
serde_json::to_string(&self.0.borrow().get_features_with_metadata()).unwrap()
|
181
128
|
}
|
182
129
|
|
130
|
+
fn get_filtered_features(
|
131
|
+
ruby: &Ruby,
|
132
|
+
rb_self: &Self,
|
133
|
+
feature_names: Vec<String>,
|
134
|
+
preferences: &MutGetOptionsPreferences,
|
135
|
+
) -> Result<Vec<String>, magnus::Error> {
|
136
|
+
let preferences = &convert_preferences(preferences);
|
137
|
+
match rb_self
|
138
|
+
.0
|
139
|
+
.borrow()
|
140
|
+
.get_filtered_feature_names(&feature_names, Some(preferences))
|
141
|
+
{
|
142
|
+
Ok(features) => Ok(features),
|
143
|
+
Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
183
147
|
// Return a string because it wasn't clear how to return a type defined in Rust despite looking at docs and trying a few examples.
|
184
148
|
fn get_options_json(
|
185
149
|
ruby: &Ruby,
|
@@ -352,6 +316,23 @@ impl WrappedOptionsWatcher {
|
|
352
316
|
serde_json::to_string(&self.0.borrow().get_features_with_metadata()).unwrap()
|
353
317
|
}
|
354
318
|
|
319
|
+
fn get_filtered_features(
|
320
|
+
ruby: &Ruby,
|
321
|
+
rb_self: &Self,
|
322
|
+
feature_names: Vec<String>,
|
323
|
+
preferences: &MutGetOptionsPreferences,
|
324
|
+
) -> Result<Vec<String>, magnus::Error> {
|
325
|
+
let preferences = &convert_preferences(preferences);
|
326
|
+
match rb_self
|
327
|
+
.0
|
328
|
+
.borrow()
|
329
|
+
.get_filtered_feature_names(&feature_names, Some(preferences))
|
330
|
+
{
|
331
|
+
Ok(features) => Ok(features),
|
332
|
+
Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
|
333
|
+
}
|
334
|
+
}
|
335
|
+
|
355
336
|
fn get_options_json(
|
356
337
|
ruby: &Ruby,
|
357
338
|
rb_self: &Self,
|
@@ -465,6 +446,10 @@ fn init(ruby: &Ruby) -> Result<(), magnus::Error> {
|
|
465
446
|
"get_canonical_feature_name",
|
466
447
|
method!(WrappedOptionsProvider::get_canonical_feature_name, 1),
|
467
448
|
)?;
|
449
|
+
provider_class.define_method(
|
450
|
+
"get_filtered_features",
|
451
|
+
method!(WrappedOptionsProvider::get_filtered_features, 2),
|
452
|
+
)?;
|
468
453
|
provider_class.define_method(
|
469
454
|
"get_options_json",
|
470
455
|
method!(WrappedOptionsProvider::get_options_json, 2),
|
@@ -565,6 +550,10 @@ fn init(ruby: &Ruby) -> Result<(), magnus::Error> {
|
|
565
550
|
"get_canonical_feature_name",
|
566
551
|
method!(WrappedOptionsWatcher::get_canonical_feature_name, 1),
|
567
552
|
)?;
|
553
|
+
watcher_class.define_method(
|
554
|
+
"get_filtered_features",
|
555
|
+
method!(WrappedOptionsWatcher::get_filtered_features, 2),
|
556
|
+
)?;
|
568
557
|
watcher_class.define_method(
|
569
558
|
"get_options_json",
|
570
559
|
method!(WrappedOptionsWatcher::get_options_json, 2),
|
@@ -0,0 +1,60 @@
|
|
1
|
+
use magnus::wrap;
|
2
|
+
use optify::provider::GetOptionsPreferences;
|
3
|
+
use std::cell::RefCell;
|
4
|
+
|
5
|
+
pub fn convert_preferences(
|
6
|
+
preferences: &MutGetOptionsPreferences,
|
7
|
+
) -> std::cell::Ref<'_, GetOptionsPreferences> {
|
8
|
+
preferences.0.borrow()
|
9
|
+
}
|
10
|
+
|
11
|
+
#[derive(Clone)]
|
12
|
+
#[wrap(class = "Optify::GetOptionsPreferences")]
|
13
|
+
pub struct MutGetOptionsPreferences(RefCell<GetOptionsPreferences>);
|
14
|
+
|
15
|
+
impl MutGetOptionsPreferences {
|
16
|
+
pub fn new() -> Self {
|
17
|
+
Self(RefCell::new(GetOptionsPreferences {
|
18
|
+
constraints: None,
|
19
|
+
overrides_json: None,
|
20
|
+
skip_feature_name_conversion: false,
|
21
|
+
}))
|
22
|
+
}
|
23
|
+
|
24
|
+
// Constraints Section
|
25
|
+
pub fn set_constraints_json(&self, constraints_json: Option<String>) {
|
26
|
+
self.0
|
27
|
+
.borrow_mut()
|
28
|
+
.set_constraints_json(constraints_json.as_deref());
|
29
|
+
}
|
30
|
+
|
31
|
+
pub fn get_constraints_json(&self) -> Option<String> {
|
32
|
+
self.0
|
33
|
+
.borrow()
|
34
|
+
.constraints
|
35
|
+
.as_ref()
|
36
|
+
.map(|c| serde_json::to_string(&c.constraints).unwrap())
|
37
|
+
}
|
38
|
+
|
39
|
+
// Overrides Section
|
40
|
+
pub fn has_overrides(&self) -> bool {
|
41
|
+
self.0.borrow().overrides_json.is_some()
|
42
|
+
}
|
43
|
+
|
44
|
+
pub fn set_overrides_json(&self, overrides: Option<String>) {
|
45
|
+
self.0.borrow_mut().overrides_json = overrides;
|
46
|
+
}
|
47
|
+
|
48
|
+
pub fn get_overrides_json(&self) -> Option<String> {
|
49
|
+
self.0.borrow().overrides_json.clone()
|
50
|
+
}
|
51
|
+
|
52
|
+
// Skip Feature Name Conversion Section
|
53
|
+
pub fn set_skip_feature_name_conversion(&self, value: bool) {
|
54
|
+
self.0.borrow_mut().skip_feature_name_conversion = value;
|
55
|
+
}
|
56
|
+
|
57
|
+
pub fn skip_feature_name_conversion(&self) -> bool {
|
58
|
+
self.0.borrow().skip_feature_name_conversion
|
59
|
+
}
|
60
|
+
}
|
data/lib/optify.rb
CHANGED
@@ -15,7 +15,7 @@ require_relative 'optify_ruby/watcher_implementation'
|
|
15
15
|
# but that doesn't work when building for multiple versions of Ruby.
|
16
16
|
# So we have to do this which is similar to something from 'https://github.com/matsadler/halton-rb/blob/main/lib/halton.rb'.
|
17
17
|
begin
|
18
|
-
ruby_version =
|
18
|
+
ruby_version = RUBY_VERSION.match(/\d+\.\d+/)&.[](0)
|
19
19
|
require_relative "optify_ruby/#{ruby_version}/optify_ruby"
|
20
20
|
rescue LoadError
|
21
21
|
begin
|
@@ -6,8 +6,6 @@ require 'sorbet-runtime'
|
|
6
6
|
module Optify
|
7
7
|
# @!visibility private
|
8
8
|
module ProviderModule
|
9
|
-
extend T::Sig
|
10
|
-
|
11
9
|
#: (Array[String] feature_names) -> Array[String]
|
12
10
|
def get_canonical_feature_names(feature_names)
|
13
11
|
# Try to optimize a typical case where there are just a few features.
|
@@ -40,7 +38,7 @@ module Optify
|
|
40
38
|
end
|
41
39
|
result.freeze
|
42
40
|
|
43
|
-
@features_with_metadata =
|
41
|
+
@features_with_metadata = result
|
44
42
|
result
|
45
43
|
end
|
46
44
|
|
@@ -71,13 +69,14 @@ module Optify
|
|
71
69
|
get_options_json(key, feature_names)
|
72
70
|
end
|
73
71
|
hash = JSON.parse(options_json)
|
74
|
-
|
72
|
+
config_class #: as untyped
|
73
|
+
.from_hash(hash)
|
75
74
|
end
|
76
75
|
|
77
76
|
#: -> void
|
78
77
|
def _init
|
79
|
-
@cache =
|
80
|
-
@features_with_metadata =
|
78
|
+
@cache = {} #: Hash[untyped, untyped]?
|
79
|
+
@features_with_metadata = nil #: Hash[String, OptionsMetadata]?
|
81
80
|
end
|
82
81
|
|
83
82
|
NOT_FOUND_IN_CACHE_SENTINEL = Object.new
|
@@ -93,28 +92,31 @@ module Optify
|
|
93
92
|
end
|
94
93
|
|
95
94
|
init unless @cache
|
96
|
-
feature_names = get_canonical_feature_names(feature_names) unless preferences&.skip_feature_name_conversion
|
97
95
|
|
98
|
-
|
99
|
-
|
96
|
+
if preferences.nil?
|
97
|
+
feature_names = get_filtered_features(feature_names, GetOptionsPreferences.new)
|
98
|
+
elsif !preferences.skip_feature_name_conversion || preferences.constraints_json
|
99
|
+
feature_names = get_filtered_features(feature_names, preferences)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Features are filtered, so we don't need the constraints in the cache key.
|
103
|
+
cache_key = [key, feature_names, config_class]
|
104
|
+
result = @cache #: as !nil
|
105
|
+
.fetch(cache_key, NOT_FOUND_IN_CACHE_SENTINEL)
|
100
106
|
return result unless result.equal?(NOT_FOUND_IN_CACHE_SENTINEL)
|
101
107
|
|
102
108
|
# Handle a cache miss.
|
103
109
|
|
104
|
-
# We can avoid converting the features names because they're already converted, if that was desired.
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
# Indeed the copying of preferences could be wasteful, but this only happens on a cache miss
|
110
|
-
# and when no custom preferences are provided.
|
111
|
-
preferences = preferences.dup
|
112
|
-
preferences.skip_feature_name_conversion = true
|
113
|
-
end
|
110
|
+
# We can avoid converting the features names because they're already converted from filtering above, if that was desired.
|
111
|
+
# We don't need the constraints because we filtered the features above.
|
112
|
+
# We already know there are no overrides because we checked above.
|
113
|
+
preferences = GetOptionsPreferences.new
|
114
|
+
preferences.skip_feature_name_conversion = true
|
114
115
|
|
115
116
|
result = get_options(key, feature_names, config_class, nil, preferences)
|
116
117
|
|
117
|
-
|
118
|
+
@cache #: as !nil
|
119
|
+
.[]= cache_key, result
|
118
120
|
end
|
119
121
|
end
|
120
122
|
end
|
data/rbi/optify.rbi
CHANGED
@@ -183,6 +183,18 @@ module Optify
|
|
183
183
|
sig { params(canonical_feature_name: String).returns(T.nilable(OptionsMetadata)) }
|
184
184
|
def get_feature_metadata(canonical_feature_name); end
|
185
185
|
|
186
|
+
# Filters `feature_names` based on the preferences,
|
187
|
+
# such as the `preferences`'s constraints.
|
188
|
+
# Also converts the feature names to canonical feature names if `preferences.skip_feature_name_conversion` is `false`.
|
189
|
+
sig do
|
190
|
+
params(
|
191
|
+
feature_names: T::Array[String],
|
192
|
+
preferences: GetOptionsPreferences
|
193
|
+
)
|
194
|
+
.returns(T::Array[String])
|
195
|
+
end
|
196
|
+
def get_filtered_features(feature_names, preferences); end
|
197
|
+
|
186
198
|
# Fetches options based on the provided key and feature names.
|
187
199
|
#
|
188
200
|
# @param key The key to fetch options for.
|
data/sig/optify.rbs
CHANGED
@@ -142,6 +142,8 @@ module Optify::ProviderModule
|
|
142
142
|
# @return The metadata for the feature.
|
143
143
|
def get_feature_metadata: (String canonical_feature_name) -> OptionsMetadata?
|
144
144
|
|
145
|
+
def get_filtered_features: (::Array[String] feature_names, GetOptionsPreferences preferences) -> ::Array[String]
|
146
|
+
|
145
147
|
def get_options: [Config] (String key, ::Array[String] feature_names, T::Class[Config] config_class, ?CacheOptions? cache_options, ?Optify::GetOptionsPreferences? preferences) -> Config
|
146
148
|
|
147
149
|
# Fetches options in JSON format based on the provided key and feature names.
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optify-config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin D. Harris
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-09-
|
10
|
+
date: 2025-09-05 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rb_sys
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- ext/optify_ruby/Cargo.toml
|
119
119
|
- ext/optify_ruby/extconf.rb
|
120
120
|
- ext/optify_ruby/src/lib.rs
|
121
|
+
- ext/optify_ruby/src/preferences.rs
|
121
122
|
- lib/optify.rb
|
122
123
|
- lib/optify_ruby/base_config.rb
|
123
124
|
- lib/optify_ruby/get_options_preferences.rb
|