finitio 0.12.1 → 0.12.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98a5d335829b36e4723c0cd55955fdd9a17125fe86d74e671b87fb3c965ce78e
4
- data.tar.gz: 3c32527c4dddb343f218420943f748b7126f26b3676c7860371feb9d32136efe
3
+ metadata.gz: df61ed2ea8ba9643bab08463287bd7f78141b0ded15b11564715254c28eb134d
4
+ data.tar.gz: 4cf9ab37fe2ba85ba9d86036475f67925a075d049a8d00eb6e91f3d80bbf38aa
5
5
  SHA512:
6
- metadata.gz: dd1a8adf0cc87610d51397fee2a6c735f1e42ee58d1cb107da7372b1b1eaa158bc6499bfa01a0870c9721431adc59b28c1efc969258e4c3c89ba6bf6b3957474
7
- data.tar.gz: 8cd34bae14c768d99408191b7484cd6620f99e87b1f7e03e4b1df75914da76c9df50f854e564056aaf5c8ed41d556a2634215f43d102da7006cc0b4d0edc265a
6
+ metadata.gz: 821411d259e45809c9e1da9ee22dafb36917b0f8c42a1dd87de66ff0951f063d49127b14dafab2c23e2c4ec4c9689204519b8152a4d218fb5279ccdba52777f1
7
+ data.tar.gz: 94bc8e8b9f0444872cc964e56baf46c325e0f742940c9e2f081bf31e187cdb9d45165b13426f122d6020a0cd8395365d83e5a38ee8b0ab271f71669bc7edb28f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 0.12.3 - 2025/09/01
2
+
3
+ * Add Heading#project and (Multi)TupleType#project, to remove some attributes.
4
+
5
+ * Add attribute description (taken from metadata) when generating JsonSchema
6
+ from a HashBasedType.
7
+
8
+ * Add support for a hard stop when generating JsonSchema, via a jsonSchemaType
9
+ metadata.
10
+
11
+ ## 0.12.2 - 2025/03/22
12
+
13
+ * Add Heading#allbut and (Multi)TupleType#allbut, to remove some attributes.
14
+
15
+ This actually starts the support for an algebra on types...
16
+
17
+ * Don't generate anyOf with duplicate types in JsonSchema geneation.
18
+
1
19
  ## 0.12.1 - 2025/03/20
2
20
 
3
21
  * Allow Hash as bulttin type recognized by JsonSchema generation.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- finitio (0.12.1)
4
+ finitio (0.12.3)
5
5
  citrus (>= 3.0, < 4.0)
6
6
 
7
7
  GEM
@@ -13,7 +13,7 @@ GEM
13
13
  minitest (>= 5.1)
14
14
  tzinfo (~> 2.0)
15
15
  awesome_print (1.9.2)
16
- bigdecimal (3.1.9)
16
+ bigdecimal (3.2.2)
17
17
  builder (3.3.0)
18
18
  citrus (3.0.2)
19
19
  concurrent-ruby (1.3.5)
@@ -56,13 +56,14 @@ GEM
56
56
  cucumber-messages (~> 12.2, >= 12.2.0)
57
57
  diff-lcs (1.3)
58
58
  docile (1.4.1)
59
- ffi (1.17.1-x86_64-linux-gnu)
59
+ ffi (1.17.2-x86_64-linux-gnu)
60
60
  i18n (1.14.7)
61
61
  concurrent-ruby (~> 1.0)
62
- json (2.10.2)
62
+ json (2.13.2)
63
+ memoist3 (1.0.0)
63
64
  middleware (0.1.0)
64
65
  minitest (5.25.5)
65
- multi_json (1.15.0)
66
+ multi_json (1.17.0)
66
67
  multi_test (0.1.2)
67
68
  path (2.1.0)
68
69
  protobuf-cucumber (3.10.8)
@@ -70,33 +71,34 @@ GEM
70
71
  middleware
71
72
  thor
72
73
  thread_safe
73
- rake (13.2.1)
74
- rspec (3.13.0)
74
+ rake (13.3.0)
75
+ rspec (3.13.1)
75
76
  rspec-core (~> 3.13.0)
76
77
  rspec-expectations (~> 3.13.0)
77
78
  rspec-mocks (~> 3.13.0)
78
- rspec-core (3.13.3)
79
+ rspec-core (3.13.5)
79
80
  rspec-support (~> 3.13.0)
80
- rspec-expectations (3.13.3)
81
+ rspec-expectations (3.13.5)
81
82
  diff-lcs (>= 1.2.0, < 2.0)
82
83
  rspec-support (~> 3.13.0)
83
- rspec-mocks (3.13.2)
84
+ rspec-mocks (3.13.5)
84
85
  diff-lcs (>= 1.2.0, < 2.0)
85
86
  rspec-support (~> 3.13.0)
86
- rspec-support (3.13.2)
87
+ rspec-support (3.13.5)
87
88
  simplecov (0.16.1)
88
89
  docile (~> 1.1)
89
90
  json (>= 1.8, < 3)
90
91
  simplecov-html (~> 0.10.0)
91
92
  simplecov-html (0.10.2)
92
93
  sync (0.5.0)
93
- sys-uname (1.3.1)
94
+ sys-uname (1.4.1)
94
95
  ffi (~> 1.1)
96
+ memoist3 (~> 1.0.0)
95
97
  term-ansicolor (1.11.2)
96
98
  tins (~> 1.0)
97
- thor (1.3.2)
99
+ thor (1.4.0)
98
100
  thread_safe (0.3.6)
99
- tins (1.38.0)
101
+ tins (1.42.0)
100
102
  bigdecimal
101
103
  sync
102
104
  tzinfo (2.0.6)
@@ -2,9 +2,14 @@ module Finitio
2
2
  class AdType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
- {
6
- anyOf: contracts.map{|c| c.infotype.to_json_schema(*args, &bl) }
7
- }
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
9
+ subtypes = contracts
10
+ .map{|c| c.infotype.to_json_schema(*args, &bl) }
11
+ .uniq
12
+ subtypes.size == 1 ? subtypes.first : { anyOf: subtypes }
8
13
  end
9
14
 
10
15
  end # class AdType
@@ -2,6 +2,10 @@ module Finitio
2
2
  class AliasType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  target.to_json_schema(*args, &bl)
6
10
  end
7
11
 
@@ -2,6 +2,10 @@ module Finitio
2
2
  class AnyType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  {}
6
10
  end
7
11
 
@@ -17,6 +17,10 @@ module Finitio
17
17
  class BuiltinType
18
18
 
19
19
  def to_json_schema(*args, &bl)
20
+ if type = metadata[:jsonSchemaType]
21
+ return { type: type }
22
+ end
23
+
20
24
  mapped = JsonSchema::BUILTIN_MAPPING[ruby_type]
21
25
  if mapped
22
26
  { type: mapped }
@@ -2,22 +2,27 @@ module Finitio
2
2
  module HashBasedType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  base = {
6
10
  type: "object"
7
11
  }
8
12
  unless heading.empty?
9
13
  base[:properties] = heading.inject({}){|ps,a|
10
- ps.merge(a.name => a.type.to_json_schema(*args, &bl))
14
+ ps.merge(a.name => a.to_json_schema(*args, &bl))
11
15
  }
12
16
  end
13
17
  unless (reqs = heading.select{|a| a.required? }).empty?
14
18
  base[:required] = reqs.map{|a| a.name }
15
19
  end
16
- base[:additionalProperties] = if heading.allow_extra?
20
+ additional = if heading.allow_extra?
17
21
  heading.allow_extra.to_json_schema(*args, &bl)
18
22
  else
19
23
  false
20
24
  end
25
+ base[:additionalProperties] = additional if additional
21
26
  base
22
27
  end
23
28
 
@@ -2,6 +2,10 @@ module Finitio
2
2
  class ProxyType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  # ProxyType is supposed to be used only for recursive types.
6
10
  # We don't have support for references yet, so let just
7
11
  # generate an object here in the mean time.
@@ -2,6 +2,10 @@ module Finitio
2
2
  module RelBasedType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  {
6
10
  type: "array",
7
11
  items: tuple_type.to_json_schema(*args, &bl),
@@ -2,6 +2,10 @@ module Finitio
2
2
  class SeqType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  {
6
10
  type: "array",
7
11
  items: elm_type.to_json_schema(*args, &bl)
@@ -2,6 +2,10 @@ module Finitio
2
2
  class SetType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  {
6
10
  type: "array",
7
11
  items: elm_type.to_json_schema(*args, &bl),
@@ -2,6 +2,10 @@ module Finitio
2
2
  class StructType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  {
6
10
  type: "array",
7
11
  items: component_types.map{|c| c.to_json_schema(*args, &bl) }
@@ -2,6 +2,10 @@ module Finitio
2
2
  class SubType
3
3
 
4
4
  def to_json_schema(*args, &bl)
5
+ if type = metadata[:jsonSchemaType]
6
+ return { type: type }
7
+ end
8
+
5
9
  # TODO: add support for constraints here...
6
10
  super_type.to_json_schema(*args, &bl)
7
11
  end
@@ -10,12 +10,18 @@ module Finitio
10
10
  BOOLEAN_TYPE = UnionType.new([TRUE_TYPE, FALSE_TYPE])
11
11
 
12
12
  def to_json_schema(*args, &bl)
13
+ if type = metadata[:jsonSchemaType]
14
+ return { type: type }
15
+ end
16
+
13
17
  cs = candidates.reject{|c| c == NIL_TYPE }
14
18
  return { type: 'boolean'} if self == BOOLEAN_TYPE
15
19
  return cs.first.to_json_schema(*args, &bl) if cs.size == 1
16
20
 
21
+ subtypes = cs.map{|c| c.to_json_schema(*args, &bl) }.uniq
22
+ return subtypes.first if subtypes.size == 1
17
23
  {
18
- anyOf: cs.map{|c| c.to_json_schema(*args, &bl) }
24
+ anyOf: subtypes
19
25
  }
20
26
  end
21
27
 
@@ -63,5 +63,15 @@ module Finitio
63
63
  Attribute.new(name, type.unconstrained, required, metadata)
64
64
  end
65
65
 
66
+ def to_json_schema(*args, &bl)
67
+ schema = if jstype = metadata[:jsonSchemaType]
68
+ { type: jstype }
69
+ else
70
+ type.to_json_schema(*args, &bl)
71
+ end
72
+ schema[:description] = metadata[:description]
73
+ schema.compact
74
+ end
75
+
66
76
  end # class Attribute
67
77
  end # module Finitio
@@ -114,6 +114,14 @@ module Finitio
114
114
  Heading.new(attributes.values.map{|a| a.unconstrained }, options)
115
115
  end
116
116
 
117
+ def project(attrs)
118
+ Heading.new(attributes.values.select{|a| attrs.include?(a.name) }.to_a, @options)
119
+ end
120
+
121
+ def allbut(attrs)
122
+ Heading.new(attributes.values.reject{|a| attrs.include?(a.name) }.to_a, @options)
123
+ end
124
+
117
125
  private
118
126
 
119
127
  def normalize_attributes(attrs)
@@ -61,6 +61,14 @@ module Finitio
61
61
  uped
62
62
  end
63
63
 
64
+ def project(attrs)
65
+ factor(heading.project(attrs))
66
+ end
67
+
68
+ def allbut(attrs)
69
+ factor(heading.allbut(attrs))
70
+ end
71
+
64
72
  protected
65
73
 
66
74
  def looks_a_tuple?(value)
@@ -29,5 +29,9 @@ module Finitio
29
29
  super(other, TupleType, MultiTupleType)
30
30
  end
31
31
 
32
+ def factor(heading)
33
+ MultiTupleType.new(heading)
34
+ end
35
+
32
36
  end # class MultiTupleType
33
37
  end # module Finitio
@@ -48,5 +48,9 @@ module Finitio
48
48
  super(other, TupleType, MultiTupleType)
49
49
  end
50
50
 
51
+ def factor(heading)
52
+ TupleType.new(heading)
53
+ end
54
+
51
55
  end # class TupleType
52
56
  end # module Finitio
@@ -3,7 +3,7 @@ module Finitio
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 12
6
- TINY = 1
6
+ TINY = 3
7
7
 
8
8
  def self.to_s
9
9
  [ MAJOR, MINOR, TINY ].join('.')
@@ -3,10 +3,10 @@ module Finitio
3
3
  describe "AdType" do
4
4
 
5
5
  let(:type) {
6
- type = AdType.new(Color, [rgb_contract, hex_contract])
6
+ type = AdType.new(Color, [rgb_contract, hex_contract, hex_contract])
7
7
  }
8
8
 
9
- it 'works as expected' do
9
+ it 'works as expected and removes duplicates' do
10
10
  expect(type.to_json_schema).to eql({
11
11
  anyOf: [
12
12
  { type: "integer" },
@@ -28,8 +28,7 @@ module Finitio
28
28
  },
29
29
  required: [
30
30
  :children
31
- ],
32
- additionalProperties: false
31
+ ]
33
32
  })
34
33
  end
35
34
 
@@ -18,8 +18,7 @@ module Finitio
18
18
  properties: {
19
19
  a: {}
20
20
  },
21
- required: [:a],
22
- additionalProperties: false
21
+ required: [:a]
23
22
  },
24
23
  uniqueItems: true
25
24
  })
@@ -3,7 +3,7 @@ module Finitio
3
3
  describe "TupleType" do
4
4
 
5
5
  let(:heading){
6
- Heading.new([Attribute.new(:a, anyType)])
6
+ Heading.new([Attribute.new(:a, stringType, true, description: 'Hello')])
7
7
  }
8
8
 
9
9
  let(:tuple_type) {
@@ -14,10 +14,9 @@ module Finitio
14
14
  expect(tuple_type.to_json_schema).to eql({
15
15
  type: "object",
16
16
  properties: {
17
- a: {}
17
+ a: {:type=>"string", :description => 'Hello'}
18
18
  },
19
- required: [:a],
20
- additionalProperties: false
19
+ required: [:a]
21
20
  })
22
21
  end
23
22
 
@@ -46,6 +46,18 @@ module Finitio
46
46
  end
47
47
  end
48
48
 
49
+ context 'when used with two yielding the same final type' do
50
+ let(:union_type) {
51
+ UnionType.new([string_type, string_type])
52
+ }
53
+
54
+ it 'works as expected' do
55
+ expect(union_type.to_json_schema).to eql({
56
+ :type => "string"
57
+ })
58
+ end
59
+ end
60
+
49
61
  context 'when used with a |Nil' do
50
62
  let(:union_type) {
51
63
  UnionType.new([string_type, int_type, nil_type])
@@ -23,6 +23,19 @@ module Finitio
23
23
  end
24
24
  end
25
25
 
26
+ context 'with metadata' do
27
+ let(:input){ "/- Hello a -/\na: .Integer" }
28
+
29
+ it 'compiles to an mandatory Attribute' do
30
+ expect(compiled).to be_a(Attribute)
31
+ expect(compiled.name).to eq(:a)
32
+ expect(compiled.type).to be_a(BuiltinType)
33
+ expect(compiled.type.ruby_type).to be(Integer)
34
+ expect(compiled.metadata).to eql(description: 'Hello a')
35
+ expect(compiled).to be_required
36
+ end
37
+ end
38
+
26
39
  context 'a :? .Integer' do
27
40
  let(:input){ 'a :? .Integer' }
28
41
 
@@ -29,6 +29,16 @@ module Finitio
29
29
  end
30
30
  end
31
31
 
32
+ context '{a: .Integer}' do
33
+ let(:input){ '{/- Hello a -/ a: .Integer}' }
34
+
35
+ it 'compiles to a TupleType' do
36
+ expect(compiled).to be_a(TupleType)
37
+ expect(compiled.heading.size).to eq(1)
38
+ expect(compiled.heading[:a].metadata).to eql(description: 'Hello a')
39
+ end
40
+ end
41
+
32
42
  context '{a: .Integer, b: .Float}' do
33
43
  let(:input){ '{a: .Integer, b: .Float}' }
34
44
 
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ module Finitio
3
+ describe TupleType, "allbut" do
4
+
5
+ let(:h1){ Heading.new([Attribute.new(:r, intType), Attribute.new(:b, intType)]) }
6
+ let(:h2){ Heading.new([Attribute.new(:b, intType)]) }
7
+
8
+ let(:t1) { TupleType.new(h1) }
9
+ let(:t2) { TupleType.new(h2) }
10
+
11
+ it 'removes unwanted atributes' do
12
+ expect(t1.allbut([:r])).to eql(t2)
13
+ end
14
+
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ module Finitio
3
+ describe TupleType, "project" do
4
+
5
+ let(:h1){ Heading.new([Attribute.new(:r, intType), Attribute.new(:b, intType)]) }
6
+ let(:h2){ Heading.new([Attribute.new(:b, intType)]) }
7
+
8
+ let(:t1) { TupleType.new(h1) }
9
+ let(:t2) { TupleType.new(h2) }
10
+
11
+ it 'removes unwanted atributes' do
12
+ expect(t1.project([:b])).to eql(t2)
13
+ end
14
+
15
+
16
+ end
17
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finitio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-20 00:00:00.000000000 Z
11
+ date: 2025-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: citrus
@@ -446,12 +446,14 @@ files:
446
446
  - spec/type/sub_type/test_name.rb
447
447
  - spec/type/test_suppremum.rb
448
448
  - spec/type/test_unconstrained.rb
449
+ - spec/type/tuple_type/test_allbut.rb
449
450
  - spec/type/tuple_type/test_default_name.rb
450
451
  - spec/type/tuple_type/test_dress.rb
451
452
  - spec/type/tuple_type/test_equality.rb
452
453
  - spec/type/tuple_type/test_include.rb
453
454
  - spec/type/tuple_type/test_initialize.rb
454
455
  - spec/type/tuple_type/test_name.rb
456
+ - spec/type/tuple_type/test_project.rb
455
457
  - spec/type/tuple_type/test_suppremum.rb
456
458
  - spec/type/union_type/test_default_name.rb
457
459
  - spec/type/union_type/test_dress.rb
@@ -661,12 +663,14 @@ test_files:
661
663
  - spec/type/sub_type/test_name.rb
662
664
  - spec/type/test_suppremum.rb
663
665
  - spec/type/test_unconstrained.rb
666
+ - spec/type/tuple_type/test_allbut.rb
664
667
  - spec/type/tuple_type/test_default_name.rb
665
668
  - spec/type/tuple_type/test_dress.rb
666
669
  - spec/type/tuple_type/test_equality.rb
667
670
  - spec/type/tuple_type/test_include.rb
668
671
  - spec/type/tuple_type/test_initialize.rb
669
672
  - spec/type/tuple_type/test_name.rb
673
+ - spec/type/tuple_type/test_project.rb
670
674
  - spec/type/tuple_type/test_suppremum.rb
671
675
  - spec/type/union_type/test_default_name.rb
672
676
  - spec/type/union_type/test_dress.rb