cel 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +20 -5
- data/lib/cel/ast/elements.rb +12 -0
- data/lib/cel/ast/types.rb +42 -1
- data/lib/cel/checker.rb +3 -3
- data/lib/cel/program.rb +7 -5
- data/lib/cel/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54879dbe064eebebe6597acd098c6b10b8376f7b2333d2f822ca02c24a0815bb
|
4
|
+
data.tar.gz: 95e2fed808711b64aedc8ed6aff2f8bc8eb9e5f9562907c0d794df186a35f035
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59349c9633015f0a63c297573e30e33d459de63f1af8ff032f808b045c069716c19142e2208f653864bd4a2363009dd7cb54c8feed3160e6c792c260853cc79f
|
7
|
+
data.tar.gz: 2070807c5f7a01217117d96373372e111697727069b915a665acfc6fd2a58c6ff4adfb4fd747522585d7b03733cfb77ee2b7b726b6c36edb3f6d828a93ffed10
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.1] - 2023-07-26
|
4
|
+
|
5
|
+
|
6
|
+
### Improvements
|
7
|
+
|
8
|
+
Collection type declarations are now better supported, i.e. declaring "an array of strings" is now possible:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
Cel::Types[:list, :string] # array of strings
|
12
|
+
Cel::Environment.new(
|
13
|
+
names: Cel::Types[:list, :string],
|
14
|
+
owned_by: Cel::Types[:map, :string] # hash map of string keys
|
15
|
+
)
|
16
|
+
```
|
17
|
+
|
18
|
+
### Bugfixes
|
19
|
+
|
20
|
+
Collections passed as variables of an expression are now correctly cast to Cel types:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
env.evaluate("a", { a: [1, 2, 3] }) #=> now returns a Cel::List
|
24
|
+
```
|
25
|
+
|
26
|
+
Conversely, custom functions now expose ruby types in the blocks, instead of its Cel counterparts:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
func = Cel::Function(:list, :list, return_type: :list) do |a, b|
|
30
|
+
# a is now a ruby array, b as well
|
31
|
+
a & b
|
32
|
+
# function returns a ruby array, will be converted to a Cel::List for use in the expression
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
3
36
|
## [0.2.0] - 2023-01-17
|
4
37
|
|
5
38
|
### Features
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Cel::Ruby
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/cel.svg)](http://rubygems.org/gems/cel)
|
4
|
-
[![pipeline status](https://gitlab.com/
|
5
|
-
[![coverage report](https://gitlab.com/
|
4
|
+
[![pipeline status](https://gitlab.com/os85/cel-ruby/badges/master/pipeline.svg)](https://gitlab.com/os85/cel-ruby/pipelines?page=1&scope=all&ref=master)
|
5
|
+
[![coverage report](https://gitlab.com/os85/cel-ruby/badges/master/coverage.svg?job=coverage)](https://os85.gitlab.io/cel-ruby/coverage/#_AllFiles)
|
6
6
|
|
7
7
|
Pure Ruby implementation of Google Common Expression Language, https://opensource.google/projects/cel.
|
8
8
|
|
@@ -45,19 +45,20 @@ end
|
|
45
45
|
prg = env.program(ast)
|
46
46
|
# 1.3 evaluate
|
47
47
|
return_value = prg.evaluate(name: Cel::String.new("/groups/acme.co/documents/secret-stuff"),
|
48
|
-
group: Cel::String.new("acme.co"))
|
48
|
+
group: Cel::String.new("acme.co"))
|
49
49
|
|
50
50
|
# 2.1 parse and check
|
51
51
|
prg = env.program('name.startsWith("/groups/" + group)')
|
52
52
|
# 2.2 then evaluate
|
53
53
|
return_value = prg.evaluate(name: Cel::String.new("/groups/acme.co/documents/secret-stuff"),
|
54
|
-
group: Cel::String.new("acme.co"))
|
54
|
+
group: Cel::String.new("acme.co"))
|
55
55
|
|
56
56
|
# 3. or parse, check and evaluate
|
57
57
|
begin
|
58
58
|
return_value = env.evaluate(ast,
|
59
59
|
name: Cel::String.new("/groups/acme.co/documents/secret-stuff"),
|
60
|
-
group: Cel::String.new("acme.co")
|
60
|
+
group: Cel::String.new("acme.co")
|
61
|
+
)
|
61
62
|
rescue Cel::Error => e
|
62
63
|
STDERR.puts("evaluation error: #{e.message}")
|
63
64
|
raise e
|
@@ -66,6 +67,20 @@ end
|
|
66
67
|
puts return_value #=> true
|
67
68
|
```
|
68
69
|
|
70
|
+
### types
|
71
|
+
|
72
|
+
`cel-ruby` supports declaring the types of variables in the environment, which allows for expression checking:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
env = Cel::Environment.new(
|
76
|
+
first_name: :string, # shortcut for Cel::Types[:string]
|
77
|
+
middle_names: Cel::Types[:list, :string], # list of strings
|
78
|
+
last_name: :string
|
79
|
+
)
|
80
|
+
|
81
|
+
# you can use Cel::Types to access any type of primitive type, i.e. Cel::Types[:bytes]
|
82
|
+
```
|
83
|
+
|
69
84
|
### protobuf
|
70
85
|
|
71
86
|
If `google/protobuf` is available in the environment, `cel-ruby` will also be able to integrate with protobuf declarations in CEL expressions.
|
data/lib/cel/ast/elements.rb
CHANGED
@@ -176,6 +176,10 @@ module Cel
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
def to_ruby_type
|
180
|
+
@value
|
181
|
+
end
|
182
|
+
|
179
183
|
private
|
180
184
|
|
181
185
|
def check; end
|
@@ -296,6 +300,10 @@ module Cel
|
|
296
300
|
def to_ary
|
297
301
|
[self]
|
298
302
|
end
|
303
|
+
|
304
|
+
def to_ruby_type
|
305
|
+
value.map(&:to_ruby_type)
|
306
|
+
end
|
299
307
|
end
|
300
308
|
|
301
309
|
class Map < Literal
|
@@ -318,6 +326,10 @@ module Cel
|
|
318
326
|
[self]
|
319
327
|
end
|
320
328
|
|
329
|
+
def to_ruby_type
|
330
|
+
value.to_h { |*args| args.map(&:to_ruby_type) }
|
331
|
+
end
|
332
|
+
|
321
333
|
def respond_to_missing?(meth, *args)
|
322
334
|
super || (@value && @value.keys.any? { |k| k.to_s == meth.to_s })
|
323
335
|
end
|
data/lib/cel/ast/types.rb
CHANGED
@@ -58,6 +58,14 @@ module Cel
|
|
58
58
|
def get(idx)
|
59
59
|
@type_list[idx]
|
60
60
|
end
|
61
|
+
|
62
|
+
def ==(other)
|
63
|
+
other == :list || super
|
64
|
+
end
|
65
|
+
|
66
|
+
def cast(value)
|
67
|
+
List.new(value)
|
68
|
+
end
|
61
69
|
end
|
62
70
|
|
63
71
|
class MapType < Type
|
@@ -73,12 +81,45 @@ module Cel
|
|
73
81
|
_, value = @type_map.find { |k, _| k == attrib.to_s }
|
74
82
|
value
|
75
83
|
end
|
84
|
+
|
85
|
+
def ==(other)
|
86
|
+
other == :map || super
|
87
|
+
end
|
88
|
+
|
89
|
+
def cast(value)
|
90
|
+
Map.new(value)
|
91
|
+
end
|
76
92
|
end
|
77
93
|
|
78
94
|
# Primitive Cel Types
|
79
95
|
|
80
96
|
PRIMITIVE_TYPES = %i[int uint double bool string bytes list map timestamp duration null_type type].freeze
|
81
|
-
|
97
|
+
COLTYPES = %i[list map].freeze
|
98
|
+
TYPES = (PRIMITIVE_TYPES - COLTYPES).to_h { |typ| [typ, Type.new(typ)] }
|
82
99
|
TYPES[:type] = Type.new(:type)
|
83
100
|
TYPES[:any] = Type.new(:any)
|
101
|
+
|
102
|
+
module CollectionTypeFetch
|
103
|
+
def [](*args)
|
104
|
+
col_type, elem_type = args
|
105
|
+
|
106
|
+
return super unless COLTYPES.include?(col_type)
|
107
|
+
|
108
|
+
return super if args.size > 2
|
109
|
+
|
110
|
+
elem_type ||= :any
|
111
|
+
|
112
|
+
type = case col_type
|
113
|
+
when :list
|
114
|
+
ListType.new([])
|
115
|
+
when :map
|
116
|
+
MapType.new({})
|
117
|
+
end
|
118
|
+
|
119
|
+
type.element_type = super(*elem_type)
|
120
|
+
type
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
TYPES.singleton_class.prepend(CollectionTypeFetch)
|
84
125
|
end
|
data/lib/cel/checker.rb
CHANGED
@@ -148,7 +148,7 @@ module Cel
|
|
148
148
|
case func
|
149
149
|
when :[]
|
150
150
|
attribute = var_type.get(args)
|
151
|
-
|
151
|
+
return TYPES[:any] unless attribute
|
152
152
|
when :all, :exists, :exists_one
|
153
153
|
check_arity(funcall, args, 2)
|
154
154
|
identifier, predicate = args
|
@@ -162,7 +162,7 @@ module Cel
|
|
162
162
|
return TYPES[:bool]
|
163
163
|
else
|
164
164
|
attribute = var_type.get(func)
|
165
|
-
|
165
|
+
return TYPES[:any] unless attribute
|
166
166
|
end
|
167
167
|
|
168
168
|
call(attribute)
|
@@ -381,7 +381,7 @@ module Cel
|
|
381
381
|
end
|
382
382
|
end
|
383
383
|
|
384
|
-
TYPES[type]
|
384
|
+
type && types.is_a?(Type) ? types : TYPES[type]
|
385
385
|
end
|
386
386
|
|
387
387
|
def check_arity(func, args, arity)
|
data/lib/cel/program.rb
CHANGED
@@ -93,7 +93,7 @@ module Cel
|
|
93
93
|
when String
|
94
94
|
raise EvaluateError, "#{invoke} is not supported" unless String.method_defined?(func, false)
|
95
95
|
|
96
|
-
var.public_send(func, *args)
|
96
|
+
var.public_send(func, *args.map(&method(:call)))
|
97
97
|
when Message
|
98
98
|
# If e evaluates to a message and f is not declared in this message, the
|
99
99
|
# runtime error no_such_field is raised.
|
@@ -134,10 +134,12 @@ module Cel
|
|
134
134
|
|
135
135
|
val.class
|
136
136
|
# MACROS
|
137
|
-
when :has
|
138
|
-
Macro.__send__(func, *args)
|
137
|
+
when :has
|
138
|
+
Bool.new(Macro.__send__(func, *args))
|
139
|
+
when :size
|
140
|
+
Cel::Number.new(:int, Macro.__send__(func, *args))
|
139
141
|
when :matches
|
140
|
-
Macro.__send__(func, *args.map(&method(:call)))
|
142
|
+
Bool.new(Macro.__send__(func, *args.map(&method(:call))))
|
141
143
|
when :int, :uint, :string, :double, :bytes, :duration, :timestamp
|
142
144
|
type = TYPES[func]
|
143
145
|
type.cast(call(args.first))
|
@@ -153,7 +155,7 @@ module Cel
|
|
153
155
|
def evaluate_custom_func(func, funcall)
|
154
156
|
args = funcall.args
|
155
157
|
|
156
|
-
func.call(*args.map(&method(:call)))
|
158
|
+
func.call(*args.map(&method(:call)).map(&:to_ruby_type))
|
157
159
|
end
|
158
160
|
end
|
159
161
|
end
|
data/lib/cel/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
requirements: []
|
91
|
-
rubygems_version: 3.
|
91
|
+
rubygems_version: 3.4.10
|
92
92
|
signing_key:
|
93
93
|
specification_version: 4
|
94
94
|
summary: Pure Ruby implementation of Google Common Expression Language, https://opensource.google/projects/cel.
|