yes 0.0.1 → 1.3.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 +7 -0
- data/CHANGELOG.md +64 -0
- data/LICENSE.txt +21 -0
- data/README.md +2256 -0
- data/lib/yes/version.rb +5 -0
- data/lib/yes.rb +7 -35
- metadata +93 -98
- data/.ruby +0 -41
- data/.yardopts +0 -8
- data/HISTORY.rdoc +0 -31
- data/LICENSE.rdoc +0 -35
- data/QED.rdoc +0 -1036
- data/README.rdoc +0 -144
- data/THANKS.rdoc +0 -10
- data/bin/yes-lint +0 -4
- data/data/yes/yes.yes +0 -21
- data/lib/yes/cli.rb +0 -20
- data/lib/yes/constraints/abstract_constraint.rb +0 -121
- data/lib/yes/constraints/choice.rb +0 -39
- data/lib/yes/constraints/count.rb +0 -38
- data/lib/yes/constraints/exclusive.rb +0 -48
- data/lib/yes/constraints/fnmatch.rb +0 -42
- data/lib/yes/constraints/inclusive.rb +0 -50
- data/lib/yes/constraints/key.rb +0 -55
- data/lib/yes/constraints/kind.rb +0 -34
- data/lib/yes/constraints/length.rb +0 -46
- data/lib/yes/constraints/node_constraint.rb +0 -55
- data/lib/yes/constraints/range.rb +0 -43
- data/lib/yes/constraints/regexp.rb +0 -52
- data/lib/yes/constraints/required.rb +0 -45
- data/lib/yes/constraints/requires.rb +0 -57
- data/lib/yes/constraints/tag.rb +0 -55
- data/lib/yes/constraints/tree_constraint.rb +0 -14
- data/lib/yes/constraints/type.rb +0 -91
- data/lib/yes/constraints/value.rb +0 -62
- data/lib/yes/genclass.rb +0 -2
- data/lib/yes/lint.rb +0 -101
- data/lib/yes/logical_and.rb +0 -13
data/README.rdoc
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
= YES - YAML Easy Schema
|
|
2
|
-
|
|
3
|
-
Author:: Thomas Sawyer
|
|
4
|
-
License:: BSD-2-Clause
|
|
5
|
-
Copyright:: (c) 2011 Thomas Sawyer, Rubyworks
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
== SALES PITCH
|
|
9
|
-
|
|
10
|
-
It doesn't get any easier than this!
|
|
11
|
-
|
|
12
|
-
YES is a schema system for YAML that is intuitive and extremely powerful.
|
|
13
|
-
|
|
14
|
-
YES Schemas are also YAML documents, so they eat there own dog food.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
== HOW IT WORKS
|
|
18
|
-
|
|
19
|
-
The design of YeS is as simple as it is powerful. A YeS schema is composed
|
|
20
|
-
of YPath selectors mapped to document constraints. YPath is a syntax
|
|
21
|
-
for selecting *nodes* from a YAML document.
|
|
22
|
-
|
|
23
|
-
When validating a YAML document against a YeS schema a "lint" program
|
|
24
|
-
simply collects all matching nodes with their applicable constraints into
|
|
25
|
-
a collection of *unit-validations*. Then this collection is filtered of
|
|
26
|
-
all *passing* validations. All that is left are the failures. If the filtered
|
|
27
|
-
list is empty the document is completely valid. If not empty, the lint
|
|
28
|
-
program can provide a detailed *editorial* list of the failures.
|
|
29
|
-
|
|
30
|
-
Constraints are given as a mappings of validation type to validation
|
|
31
|
-
parameters.
|
|
32
|
-
|
|
33
|
-
Lets take an example:
|
|
34
|
-
|
|
35
|
-
people/*/name:
|
|
36
|
-
regexp: '[^/n]'
|
|
37
|
-
|
|
38
|
-
This simple schema selects all nodes under a `people` sequence of
|
|
39
|
-
mappings with a name key, the value of which cannot contain newlines.
|
|
40
|
-
In other words:
|
|
41
|
-
|
|
42
|
-
--
|
|
43
|
-
people:
|
|
44
|
-
- name: Charlie Adams
|
|
45
|
-
- name: Julie Ann Rose
|
|
46
|
-
|
|
47
|
-
Would satisfy the schema. But,
|
|
48
|
-
|
|
49
|
-
--
|
|
50
|
-
people:
|
|
51
|
-
- name: |
|
|
52
|
-
Charlie
|
|
53
|
-
Adams
|
|
54
|
-
|
|
55
|
-
Would not.
|
|
56
|
-
|
|
57
|
-
TODO: Better Examples!!!
|
|
58
|
-
|
|
59
|
-
Sometimes multiple constraints of the same type need to be applied to
|
|
60
|
-
a set of nodes. This can be done by expressing the same YPath with
|
|
61
|
-
different constraints, for example:
|
|
62
|
-
|
|
63
|
-
people/*/name:
|
|
64
|
-
regexp: '[^/t]'
|
|
65
|
-
people/*/name:
|
|
66
|
-
regexp: '[^/n]'
|
|
67
|
-
|
|
68
|
-
But to make the intent more succinct a sequence of constraints can be give
|
|
69
|
-
along with the *logical-and* tag , `!!and`.
|
|
70
|
-
|
|
71
|
-
people/*/name: !!and
|
|
72
|
-
- regexp: '[^/t]'
|
|
73
|
-
- regexp: '[^/n]'
|
|
74
|
-
|
|
75
|
-
If the `!!and` tag is not given, then the default operator is used,
|
|
76
|
-
*logical-or*, which can also be explicitly stated as `!!or`:
|
|
77
|
-
|
|
78
|
-
people/*/name: !!or
|
|
79
|
-
- regexp: '[^/t]'
|
|
80
|
-
- regexp: '[^/n]'
|
|
81
|
-
|
|
82
|
-
In this way logical relationships of constraints can be created.
|
|
83
|
-
|
|
84
|
-
people/*/name: !!or
|
|
85
|
-
- !!and
|
|
86
|
-
- regexp: '[^/t]'
|
|
87
|
-
- regexp: '[^/n]'
|
|
88
|
-
- !!and
|
|
89
|
-
- regexp: '[^/t]'
|
|
90
|
-
- regexp: '[^/n]'
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
== COMMAND LINE
|
|
94
|
-
|
|
95
|
-
To use on the command line *lint* tool. Say we have a `schema.yes` file:
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
name:
|
|
99
|
-
type: str
|
|
100
|
-
regexp: '[^\n]'
|
|
101
|
-
required: true
|
|
102
|
-
age:
|
|
103
|
-
type: int
|
|
104
|
-
birth:
|
|
105
|
-
type: date
|
|
106
|
-
|
|
107
|
-
Try it on `sample.yaml`.
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
name: Thomas T. Thomas
|
|
111
|
-
age: 42
|
|
112
|
-
birth: 1976-07-04
|
|
113
|
-
|
|
114
|
-
Using the executable.
|
|
115
|
-
|
|
116
|
-
$ yes-lint schema.yes sample.yaml
|
|
117
|
-
|
|
118
|
-
In code that is:
|
|
119
|
-
|
|
120
|
-
require 'yes'
|
|
121
|
-
|
|
122
|
-
lint = YES::Lint.new(File.new('schema.yes'))
|
|
123
|
-
|
|
124
|
-
lint.validate(File.new('sample.yaml'))
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
== CONTRIBUTE
|
|
128
|
-
|
|
129
|
-
Come on folks! Let's get YAML up to snuff. A good Schema could really
|
|
130
|
-
help YAML go the distance and penetrate some of those "Enterprisey" worlds.
|
|
131
|
-
|
|
132
|
-
* Please read, write and comment on issues[https://github.com/rubyworks/yes/issues].
|
|
133
|
-
* Please critique the code.
|
|
134
|
-
* Please fork and submit patches in topic branches.
|
|
135
|
-
|
|
136
|
-
And please contribute to {Rubyworks Ruby Development Fund}[http://rubyworks.github.org]
|
|
137
|
-
so us poor Ruby OSS developers can eat :)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
== COPYRIGHT
|
|
141
|
-
|
|
142
|
-
(BSD-2 license)
|
|
143
|
-
|
|
144
|
-
Copyright (c) 2011 Rubyworks, Thomas Sawyer
|
data/THANKS.rdoc
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
= SPECIAL THANKS
|
|
2
|
-
|
|
3
|
-
== Kwaify
|
|
4
|
-
|
|
5
|
-
Copyright:: (c) 2005-2010 Kuwata Lab. All rights reserved.
|
|
6
|
-
License:: MIT
|
|
7
|
-
Website:: http://www.kuwata-lab.com/kwalify
|
|
8
|
-
|
|
9
|
-
Although no Kwalify code was actually used to build YES, it provided
|
|
10
|
-
inspiration for some of the design choices.
|
data/bin/yes-lint
DELETED
data/data/yes/yes.yes
DELETED
data/lib/yes/cli.rb
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
require 'yes'
|
|
2
|
-
|
|
3
|
-
module YES
|
|
4
|
-
|
|
5
|
-
def self.cli(*argv)
|
|
6
|
-
schema_file = argv[0]
|
|
7
|
-
target_file = argv[1]
|
|
8
|
-
|
|
9
|
-
lint = Lint.new(File.new(schema_file))
|
|
10
|
-
edit = lint.validate(File.new(target_file))
|
|
11
|
-
|
|
12
|
-
if edit.size == 0
|
|
13
|
-
#$stderr.puts "valid: #{target_file}"
|
|
14
|
-
else
|
|
15
|
-
$stderr.puts edit.to_yaml
|
|
16
|
-
exit -1
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
end
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
def self.constraints
|
|
5
|
-
@constraints ||= []
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
module Constraints
|
|
10
|
-
|
|
11
|
-
# AbstractConstraint serves as the base class for
|
|
12
|
-
# all other constraints.
|
|
13
|
-
class AbstractConstraint
|
|
14
|
-
|
|
15
|
-
#
|
|
16
|
-
def self.inherited(base)
|
|
17
|
-
YES.constraints << base
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# noop
|
|
21
|
-
def self.checklist(spec, tree, nodes)
|
|
22
|
-
[]
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
#
|
|
26
|
-
def initialize(spec, tree, nodes)
|
|
27
|
-
@spec = spec
|
|
28
|
-
@tree = tree
|
|
29
|
-
@nodes = nodes
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
public
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
attr :nodes
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
attr :spec
|
|
39
|
-
|
|
40
|
-
#
|
|
41
|
-
attr :tree
|
|
42
|
-
|
|
43
|
-
# MUST OVERRIDE THIS METHOD IN SUBCLASSES
|
|
44
|
-
#
|
|
45
|
-
def validate(spec)
|
|
46
|
-
raise "undefined method -- `validate'"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# MUST OVERRIDE THIS METHOD IN SUBCLASSES
|
|
50
|
-
#
|
|
51
|
-
def self.applicable?(spec)
|
|
52
|
-
raise "undefined class method -- `applicable?'"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
#
|
|
56
|
-
def valid?
|
|
57
|
-
return true unless applicable?
|
|
58
|
-
recurse_valid?(spec)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
#
|
|
62
|
-
def applicable?
|
|
63
|
-
self.class.applicable?(spec)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
private
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
def recurse_valid?(spec=nil)
|
|
70
|
-
spec ||= self.spec
|
|
71
|
-
case spec
|
|
72
|
-
when Array # logical-or
|
|
73
|
-
spec.any?{ |sub_spec| recurse_valid?(sub_spec) }
|
|
74
|
-
else
|
|
75
|
-
validate(spec)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Range matching is used by a couple of validators.
|
|
80
|
-
#
|
|
81
|
-
# @param range [Array, String]
|
|
82
|
-
# The range representation.
|
|
83
|
-
#
|
|
84
|
-
# @example
|
|
85
|
-
# 1..1 =~ 1
|
|
86
|
-
# 1...2 =~ 1
|
|
87
|
-
# [1,1] =~ 1
|
|
88
|
-
# [1,2) =~ 1
|
|
89
|
-
# (1,2] =~ 2
|
|
90
|
-
# (1,3) =~ 2
|
|
91
|
-
#
|
|
92
|
-
def match_delta(range, value)
|
|
93
|
-
case range
|
|
94
|
-
when Array # array can do string comparisons
|
|
95
|
-
value > range.first && value < range.last
|
|
96
|
-
when /^(.*)\.\.\.(n|N)$/
|
|
97
|
-
value >= $1.to_f
|
|
98
|
-
when /^(.*)\.\.(n|N)$/
|
|
99
|
-
value >= $1.to_f
|
|
100
|
-
when /^(.*)\.\.\.(.*)$/
|
|
101
|
-
value >= $1.to_f && value < $2.to_f
|
|
102
|
-
when /^(.*)\.\.(.*)$/
|
|
103
|
-
value >= $1.to_f && value <= $2.to_f
|
|
104
|
-
when /^\[(.*)\,(.*)\]$/
|
|
105
|
-
value >= $1.to_f && value <= $2.to_f
|
|
106
|
-
when /^\[(.*)\,(.*)\)$/
|
|
107
|
-
value >= $1.to_f && value < $2.to_f
|
|
108
|
-
when /^\((.*)\,(.*)\]$/
|
|
109
|
-
value > $1.to_f && value <= $2.to_f
|
|
110
|
-
when /^\((.*)\,(.*)\)$/
|
|
111
|
-
value > $1.to_f && value < $2.to_f
|
|
112
|
-
else # assume range is just a number
|
|
113
|
-
range.to_f == value.to_f
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
end
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Validate from a selction of choices.
|
|
6
|
-
#
|
|
7
|
-
# choice: [M,F]
|
|
8
|
-
#
|
|
9
|
-
class Choice < NodeConstraint
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
# @return [Array<Constraint>]
|
|
13
|
-
def self.checklist(spec, tree, nodes)
|
|
14
|
-
return [] unless applicable?(spec)
|
|
15
|
-
nodes.map do |node|
|
|
16
|
-
new(spec, tree, node)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Only applicable if `choice` field is in spec.
|
|
21
|
-
def self.applicable?(spec)
|
|
22
|
-
spec['choice']
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Validate that a node's value is amoung a provided
|
|
26
|
-
# list of values.
|
|
27
|
-
#
|
|
28
|
-
# @return [Boolean] validity
|
|
29
|
-
def validate(spec)
|
|
30
|
-
choice = Array(spec['choice'])
|
|
31
|
-
choice.include?(node.transform)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Count validation ensures there are a limited number of matching
|
|
6
|
-
# nodes in a document.
|
|
7
|
-
#
|
|
8
|
-
# //gold:
|
|
9
|
-
# count: 1..4
|
|
10
|
-
#
|
|
11
|
-
# Would mean the `gold` mapping key could only appear 1 to 4 times
|
|
12
|
-
# in the entire document.
|
|
13
|
-
class Count < TreeConstraint
|
|
14
|
-
|
|
15
|
-
#
|
|
16
|
-
# @return [Array<Constraint>]
|
|
17
|
-
def self.checklist(spec, tree, nodes)
|
|
18
|
-
return [] unless applicable?(spec)
|
|
19
|
-
[new(spec, tree, nodes)]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Only applicable if `count` entry is in the spec.
|
|
23
|
-
def self.applicable?(spec)
|
|
24
|
-
spec['count']
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Validate count ensure there is a minimum and/or maximum
|
|
28
|
-
# number of matching nodes.
|
|
29
|
-
def validate(spec)
|
|
30
|
-
count = spec['count']
|
|
31
|
-
match_delta(count, nodes.size)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Exclusion - This can either be a boolean expression in
|
|
6
|
-
# which case it validates that there is no more than one matching
|
|
7
|
-
# node. Otherwise, the value is taken to be a ypath and validates
|
|
8
|
-
# that there are no matching paths if the main selection is present.
|
|
9
|
-
#--
|
|
10
|
-
# TODO: Provide $parent$ path substitution ?
|
|
11
|
-
#++
|
|
12
|
-
class Exclusive < TreeConstraint
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
# @return [Array<Constraint>]
|
|
16
|
-
def self.checklist(spec, tree, nodes)
|
|
17
|
-
return [] unless applicable?(spec)
|
|
18
|
-
[new(spec, tree, nodes)]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Only applicable if `exclusive` feild is in the spec.
|
|
22
|
-
def self.applicable?(spec)
|
|
23
|
-
spec['exclusive']
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Exclusion - This can either be a boolean expression in
|
|
27
|
-
# which case it validates that there is no more than one matching
|
|
28
|
-
# node. Otherwise, the value is taken to be a ypath and validates
|
|
29
|
-
# that there are no matching paths if the main selection is present.
|
|
30
|
-
#
|
|
31
|
-
# @return [Boolean] validity
|
|
32
|
-
def validate(spec)
|
|
33
|
-
exclusive = spec['exclusive']
|
|
34
|
-
|
|
35
|
-
case exclusive
|
|
36
|
-
when true, false
|
|
37
|
-
nodes.size <= 1
|
|
38
|
-
else
|
|
39
|
-
ex_nodes = tree.select(exclusive)
|
|
40
|
-
nodes.size == 0 or ex_nodes.size == 0
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Validate file glob match. This uess standard unix-style file matching,
|
|
6
|
-
# primarily '*` and `?`, to detrmine a mathing node value.
|
|
7
|
-
# All values are converted to strings (using #to_s) for comparison.
|
|
8
|
-
#--
|
|
9
|
-
# TODO: better name then `FNMatch`?
|
|
10
|
-
#++
|
|
11
|
-
class FNMatch < NodeConstraint
|
|
12
|
-
|
|
13
|
-
#
|
|
14
|
-
# @return [Array<Constraint>]
|
|
15
|
-
def self.checklist(spec, tree, nodes)
|
|
16
|
-
return [] unless applicable?(spec)
|
|
17
|
-
nodes.map do |node|
|
|
18
|
-
new(spec, tree, node)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Only applicable if `fnmatch` field is in spec.
|
|
23
|
-
def self.applicable?(spec)
|
|
24
|
-
spec['fnmatch']
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Validate file glob match. This uess standard unix-style file matching,
|
|
28
|
-
# primarily '*` and `?`, to detrmine a mathing node value.
|
|
29
|
-
# All values are converted to strings (using #to_s) for comparison.
|
|
30
|
-
#
|
|
31
|
-
# @return [Boolean] validity
|
|
32
|
-
def validate(spec)
|
|
33
|
-
fnmatch = spec['fnmatch']
|
|
34
|
-
|
|
35
|
-
File.fnmatch(fnmatch, node.value)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Inclusion can either be a boolean expression in
|
|
6
|
-
# which case it validates that there is at least one matching
|
|
7
|
-
# node. Otherwise, the value is taken to be a ypath and validates
|
|
8
|
-
# that there are matching paths if the main selection is present.
|
|
9
|
-
#--
|
|
10
|
-
# TODO: Provide $parent$ path substitution ?
|
|
11
|
-
#++
|
|
12
|
-
class Inclusive < TreeConstraint
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
# @return [Array<Constraint>]
|
|
16
|
-
def self.checklist(spec, tree, nodes)
|
|
17
|
-
return [] unless applicable?(spec)
|
|
18
|
-
[new(spec, tree, nodes)]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Only applicable if `inclusive` field in in the spec.
|
|
22
|
-
def self.applicable?(spec)
|
|
23
|
-
spec['inclusive']
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Validate inclusion - This can either be a boolean expression in
|
|
27
|
-
# which case it validates that there is at least one matching
|
|
28
|
-
# node. Otherwise, the value is taken to be a ypath and validates
|
|
29
|
-
# that there are matching paths if the main selection is present.
|
|
30
|
-
#
|
|
31
|
-
# @return [Boolean] validity
|
|
32
|
-
def valid?
|
|
33
|
-
return true unless applicable?
|
|
34
|
-
|
|
35
|
-
inclusive = spec['inclusive']
|
|
36
|
-
|
|
37
|
-
case inclusive
|
|
38
|
-
when true, false
|
|
39
|
-
nodes.size > 0
|
|
40
|
-
else
|
|
41
|
-
in_nodes = tree.select(inclusive)
|
|
42
|
-
nodes.size == 0 or in_nodes.size > 0
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
end
|
data/lib/yes/constraints/key.rb
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Validate if a mapping node's _keys_ conforms to a constraint.
|
|
6
|
-
#
|
|
7
|
-
# //authors:
|
|
8
|
-
# type: map
|
|
9
|
-
# key:
|
|
10
|
-
# type: str
|
|
11
|
-
#
|
|
12
|
-
class Key < NodeConstraint
|
|
13
|
-
|
|
14
|
-
# For key constraint, the work is all handled by the
|
|
15
|
-
# checklist method.
|
|
16
|
-
#
|
|
17
|
-
# @return [Array<Constraint>]
|
|
18
|
-
def self.checklist(spec, tree, nodes)
|
|
19
|
-
return [] unless applicable?(spec)
|
|
20
|
-
|
|
21
|
-
key_spec = spec['key']
|
|
22
|
-
list = []
|
|
23
|
-
|
|
24
|
-
nodes.each do |node|
|
|
25
|
-
case node.kind
|
|
26
|
-
when :map
|
|
27
|
-
YES.constraints.each do |c|
|
|
28
|
-
list.concat(c.checklist(key_spec, tree, node.value.keys))
|
|
29
|
-
end
|
|
30
|
-
else
|
|
31
|
-
raise "key constraint applies only to mappings"
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
list
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
def self.applicable?(spec)
|
|
41
|
-
spec['key']
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
#
|
|
45
|
-
# no-op
|
|
46
|
-
#
|
|
47
|
-
# @return [Boolean] validity
|
|
48
|
-
def validate(spec)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
end
|
data/lib/yes/constraints/kind.rb
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Validate the <i>kind of node</i>. There are only three kinds
|
|
6
|
-
# of nodes: `scalar`, `map` and `seq`.
|
|
7
|
-
#
|
|
8
|
-
class Kind < NodeConstraint
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
# @return [Array<Constraint>]
|
|
12
|
-
def self.checklist(spec, tree, nodes)
|
|
13
|
-
return [] unless applicable?(spec)
|
|
14
|
-
nodes.map do |node|
|
|
15
|
-
new(spec, tree, node)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
def self.applicable?(spec)
|
|
21
|
-
spec['kind']
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Validate type.
|
|
25
|
-
#
|
|
26
|
-
def validate(spec)
|
|
27
|
-
node.kind.to_s == spec['kind']
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
module YES
|
|
2
|
-
|
|
3
|
-
module Constraints
|
|
4
|
-
|
|
5
|
-
# Validate if a node's value is within a certain length.
|
|
6
|
-
# The value is converted to a string using #to_s for the
|
|
7
|
-
# comparison.
|
|
8
|
-
#
|
|
9
|
-
# //code:
|
|
10
|
-
# length: 3
|
|
11
|
-
#
|
|
12
|
-
# A valid code value could then have no more than three characters.
|
|
13
|
-
class Length < NodeConstraint
|
|
14
|
-
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# @return [Array<Constraint>]
|
|
18
|
-
def self.checklist(spec, tree, nodes)
|
|
19
|
-
return [] unless applicable?(spec)
|
|
20
|
-
nodes.map do |node|
|
|
21
|
-
new(spec, tree, node)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
def self.applicable?(spec)
|
|
28
|
-
spec['length']
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
#
|
|
32
|
-
# Validate if a node value is within a certain length.
|
|
33
|
-
# The value is converted to a string using #to_s for the
|
|
34
|
-
# comparison.
|
|
35
|
-
#
|
|
36
|
-
# @return [Boolean] validity
|
|
37
|
-
def validate(spec)
|
|
38
|
-
length = spec['length']
|
|
39
|
-
match_delta(length, node.value.to_s.size)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|