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.
@@ -1,55 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # The NodeConstraint class is an abstract class
6
- # and used for create constraint subclasses that
7
- # apply constraints on a sigle node.
8
- #
9
- class NodeConstraint < AbstractConstraint
10
-
11
- # Like {Abstract#initialize} but takes a `node` qas well.
12
- def initialize(spec, tree, node)
13
- super(spec, tree, [node])
14
- @node = node
15
- end
16
-
17
- public
18
-
19
- # YAML Node.
20
- attr :node
21
-
22
- # Get the applicable node's tag.
23
- def tag
24
- node.type_id
25
- end
26
-
27
- # Get the applicable node's value.
28
- def value
29
- node.value
30
- end
31
-
32
- # # Covert a YAML node (Syck) node into a generic representation.
33
- # #
34
- # # TODO: Should `style` be part of this? Also, is `kind` the proper term?
35
- # def catholic_node(node)
36
- # n = {}
37
- # n['tag'] = node.type_id
38
- # #n['type'] = #base_type_id(node)
39
- # n['kind'] = node.kind.to_s
40
- # n['value'] = node.value
41
- # n['style'] = node.instance_variable_get('@style').to_s
42
- # n
43
- # end
44
-
45
- #
46
- #
47
- def self.applicable?(spec)
48
- false
49
- end
50
-
51
- end
52
-
53
- end
54
-
55
- end
@@ -1,43 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # Validate the a nodes value is within a certain range.
6
- # Primarily this works for numeric values, but it can
7
- # also work for string in ASCII/UTF-8 order, by using
8
- # a 2-element array for comparison.
9
- #
10
- # //note:
11
- # range: ['A','G']
12
- #
13
- # Valid values for are then only A, B, C, D, E, F and G.
14
- class Range < NodeConstraint
15
-
16
- #
17
- # @return [Array<Validaiton>]
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
- def self.applicable?(spec)
27
- spec['range']
28
- end
29
-
30
- # Validate if a node is the only one of it's value in a sequence
31
- # or mapping.
32
- #
33
- # @return [Boolean] validity
34
- def validate(spec)
35
- range = spec['range']
36
- match_delta(range, node.transform) ? true : false
37
- end
38
-
39
- end
40
-
41
- end
42
-
43
- end
@@ -1,52 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # Validate matching values against a regular expression.
6
- # All values are converted to strings (using #to_s) for comparison.
7
- #
8
- # //pin:
9
- # regexp: /^\d\s\d\d$/
10
- #
11
- class Regexp < NodeConstraint
12
-
13
- #
14
- # @return [Array<Validaiton>]
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
- #
23
- def self.applicable?(spec)
24
- spec['regexp']
25
- end
26
-
27
- # Validate matching values against a regular expression.
28
- # All values are converted to strings (using #to_s) for comparison.
29
- #
30
- # @return [Boolean] validity
31
- def validate(spec)
32
- regexp = parse_regexp(spec['regexp'])
33
- regexp =~ node.value ? true : false
34
- end
35
-
36
- # The regular expression from `spec`.
37
- #
38
- # @return [Regexp] spec's regular expression
39
- def parse_regexp(re)
40
- case re
41
- when /^\/(.*?)\/(\w*)$/
42
- ::Regexp.new($1) # TODO: modifiers
43
- else
44
- ::Regexp.new(re)
45
- end
46
- end
47
-
48
- end
49
-
50
- end
51
-
52
- end
@@ -1,45 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- #
6
- # TODO: For the moment this is the same as Inclusive.
7
- # It was originall inteded to work like {RequiresValidation}
8
- # but it rpoved hard to work out the validation procedure
9
- # when matching to the subfield. If we can fix it maybe we will
10
- # keep, but for now THIS IS NOT USED.
11
- #
12
- class Required < 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 `required` field appears in spec.
22
- def self.applicable?(spec)
23
- spec['required']
24
- end
25
-
26
- # Validates whether a matching node must be present within it's parent.
27
- #
28
- # @return [Boolean] validity
29
- def validate(spec)
30
- required = spec['required']
31
-
32
- case required
33
- when true, false
34
- nodes.size > 0
35
- else
36
- in_nodes = tree.select(required)
37
- nodes.size == 0 or in_nodes.size > 0
38
- end
39
- end
40
-
41
- end
42
-
43
- end
44
-
45
- end
@@ -1,57 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # Takes a list of relative YPaths and ensures they are present.
6
- # This is most useful for ensuring the existance of mapping fields.
7
- #
8
- # foo:
9
- # requires:
10
- # - bar
11
- #
12
- # A valid document would be:
13
- #
14
- # foo:
15
- # bar: true
16
- #
17
- # The literal meaing of this example is "if `foo` exists, the make sure
18
- # `foo/bar` also exists.
19
- class Requires < NodeConstraint
20
-
21
- #
22
- # @return [Array<Constraint>]
23
- def self.checklist(spec, tree, nodes)
24
- return [] unless applicable?(spec)
25
- nodes.map do |node|
26
- new(spec, tree, node)
27
- end
28
- end
29
-
30
- #
31
- def self.applicable?(spec)
32
- spec['requires']
33
- end
34
-
35
- # Validates whether a matching node must be present within it's parent.
36
- #
37
- # @return [Boolen] validity
38
- def validate(spec)
39
- requires = Array(spec['requires'])
40
-
41
- requires.each do |rq|
42
- case rq
43
- when /^\// # absolute path
44
- rq_nodes = tree.select(rq)
45
- else
46
- rq_nodes = node.select(rq)
47
- end
48
- return false unless rq_nodes.size > 0
49
- end
50
-
51
- end
52
-
53
- end
54
-
55
- end
56
-
57
- end
@@ -1,55 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # Validate that a node has specific tag.
6
- # This ensure all the matching nodes have the given tag.
7
- # Be sure to used quotes when starting the tag with `!`.
8
- #
9
- # NOTE: the tag should honer %TAG directives in the document, but as of
10
- # yet this is not supported. Thus fully qualified tags need to be used
11
- # for anything beyond default !! and ! tags.
12
- #
13
- class Tag < NodeConstraint
14
-
15
- #
16
- # @return [Array<Constraint>]
17
- def self.checklist(spec, tree, nodes)
18
- return [] unless applicable?(spec)
19
- nodes.map do |node|
20
- new(spec, tree, node)
21
- end
22
- end
23
-
24
- #
25
- def self.applicable?(spec)
26
- spec['tag']
27
- end
28
-
29
- # Validate the tag.
30
- #
31
- # @return [Boolean] validity
32
- def validate(spec)
33
- tag = spec['tag']
34
- match_tag(tag, node)
35
- end
36
-
37
- private
38
-
39
- def match_tag(tag, node)
40
- node_tag = node.type_id || "tag:yaml.org,2002:#{node.kind}"
41
- case node_tag
42
- when /^x-private:/
43
- tag == $' or tag == '!'+$'
44
- when /^tag:yaml.org,2002:/
45
- tag == node_tag or tag == '!!'+$'
46
- else
47
- tag == node_tag
48
- end
49
- end
50
-
51
- end
52
-
53
- end
54
-
55
- end
@@ -1,14 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # The TreeValidation class is an abstract class
6
- # and used for create validation subclasses than
7
- # needs access to the complete list of matching nodes.
8
- class TreeConstraint < AbstractConstraint
9
-
10
- end
11
-
12
- end
13
-
14
- end
@@ -1,91 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # Validate the <i>tag type</i>. This ensure all the matching nodes
6
- # have the same base type specified. The tag type is the portion
7
- # of the tag the occcurs after the last non-alphanumeric character,
8
- # usually a `:`. In essence the tag type is the tag regardless of namespace.
9
- #
10
- # Also, `#` is treated specially as a subset fo they type, so it will
11
- # be used if given in the type comparison.
12
- #
13
- # @example
14
- # 'foo' =~ '!!foo'
15
- # 'foo' =~ '!<tag:foo.org/bar:foo>'
16
- # 'foo' =~ '!<tag:foo.org/bar:foo>'
17
- # 'foo' =~ '!!foo#alt'
18
- # 'foo#alt' =~ '!!foo#alt'
19
- #
20
- class Type < NodeConstraint
21
-
22
- #
23
- # @return [Array<Constraint>]
24
- def self.checklist(spec, tree, nodes)
25
- return [] unless applicable?(spec)
26
- nodes.map do |node|
27
- new(spec, tree, node)
28
- end
29
- end
30
-
31
- #
32
- def self.applicable?(spec)
33
- spec['type']
34
- end
35
-
36
- # Validate type.
37
- #
38
- def validate(spec)
39
- type_match(node, spec['type'])
40
- end
41
-
42
- private
43
-
44
- # Get the nodes base type see if matches the given type.
45
- # The {TYPE_MATCH} chart is used to map a node base types
46
- # to a given type.
47
- #
48
- # @return [Boolean] node's type matches given type
49
- def type_match(node, type)
50
- node_type, node_subtype = base_type_id(node).split('#')
51
- want_type, want_subtype = type.split('#')
52
-
53
- return false if want_subtype && want_subtype != node_subtype
54
-
55
- pick_type = TYPE_MATCH[want_type] || [want_type]
56
- pick_type.any?{ |t| t == node_type }
57
- end
58
-
59
- # Get the base of the node's type tag, i.e. the part after the last
60
- # non-alphanumeric characeter plus `#`.
61
- #
62
- # @return [String] base type
63
- def base_type_id(node)
64
- fixed_type_id(node).split(/[^#A-Za-z0-9_-]/).last
65
- end
66
-
67
- # Return the `type_id` of a node. If the type_id is `nil` then
68
- # returns the `kind`.
69
- #
70
- # @return [String] type_id or kind of node
71
- def fixed_type_id(node)
72
- type_id = node.type_id
73
- if type_id
74
- type_id
75
- else
76
- node.kind.to_s
77
- end
78
- end
79
-
80
- #
81
- TYPE_MATCH = {
82
- 'date' => ['timestamp'],
83
- 'bool' => ['bool'],
84
- 'number' => ['int', 'float']
85
- }
86
-
87
- end
88
-
89
- end
90
-
91
- end
@@ -1,62 +0,0 @@
1
- module YES
2
-
3
- module Constraints
4
-
5
- # Validate if a node's _value_ conforms to a constraint, where a
6
- # value is either an sequence element or a mapping value.
7
- #
8
- # //authors:
9
- # type: seq
10
- # value:
11
- # type: str
12
- #
13
- # A valid code value could then have no more than three characters.
14
- class Value < NodeConstraint
15
-
16
- # For value constraint, the work is all handled by the
17
- # checklist method.
18
- #
19
- # @return [Array<Constraint>]
20
- def self.checklist(spec, tree, nodes)
21
- return [] unless applicable?(spec)
22
-
23
- vspec = spec['value']
24
- list = []
25
-
26
- nodes.each do |node|
27
- case node.kind
28
- when :seq
29
- YES.constraints.each do |c|
30
- list.concat(c.checklist(vspec, tree, node.children))
31
- end
32
- when :map
33
- YES.constraints.each do |c|
34
- list.concat(c.checklist(vspec, tree, node.value.values))
35
- end
36
- else
37
- # TODO: might value for scalars have a useful meaning?
38
- raise "value constraint does not apply to scalars"
39
- end
40
- end
41
-
42
- list
43
- end
44
-
45
- #
46
- #
47
- def self.applicable?(spec)
48
- spec['value']
49
- end
50
-
51
- #
52
- # no-op
53
- #
54
- # @return [Boolean] validity
55
- def validate(spec)
56
- end
57
-
58
- end
59
-
60
- end
61
-
62
- end
data/lib/yes/genclass.rb DELETED
@@ -1,2 +0,0 @@
1
- # TODO: Idea from Kwalify, to use the scheam to grenerate a validating RUby class.
2
-
data/lib/yes/lint.rb DELETED
@@ -1,101 +0,0 @@
1
- module YES
2
-
3
- # YAML Easy Schema - Constrain Validator ("Lint")
4
- #
5
- # Issues
6
- #
7
- # * Matching fully-quaified tags.
8
- # * Handling namespaces.
9
- # * Handling YAML version directive.
10
- #
11
- class Lint
12
-
13
- # The schema document.
14
- attr :schema
15
-
16
- # The tree, which is populate when #validate is called.
17
- #attr :tree
18
-
19
- # The constraint checklist.
20
- attr :checklist
21
-
22
- #
23
- def initialize(schema)
24
- @schema = YAML.load(schema)
25
- @checklist = []
26
- end
27
-
28
- #
29
- # @param [String] yaml
30
- # A YAML document.
31
- #
32
- # @return [Array]
33
- # List of constraints that were invalid.
34
- #
35
- def validate(yaml)
36
- @checklist = []
37
-
38
- tree = YAML.parse(yaml)
39
-
40
- @schema.each do |ypath, spec|
41
- validate_ypath(ypath, spec, tree)
42
- end
43
-
44
- @checklist.reject{ |v| v.valid? }
45
- end
46
-
47
- #
48
- def validate_ypath(ypath, spec, tree)
49
- validate_spec(ypath, spec, tree)
50
-
51
- ## handle sub-paths
52
- if spec['map']
53
- spec['map'].each do |sub_path, sub_spec|
54
- sub_ypath = ypath + '/' + sub_path
55
- validate_ypath(sub_ypath, sub_spec, tree)
56
- end
57
- end
58
- end
59
-
60
- # Process all validations.
61
- #
62
- # FIXME: Add logic handling.
63
- def validate_spec(ypath, spec, tree)
64
- nodes = select_nodes(ypath, tree)
65
-
66
- YES.constraints.each do |c|
67
- @checklist.concat(c.checklist(spec, tree, nodes))
68
- end
69
- end
70
-
71
- # TODO: Maybe this should be a class method, too ?
72
- def select_nodes(ypath, tree)
73
- case ypath
74
- when Hash
75
- if path = ypath['path'] || ypath['ypath']
76
- nodes = tree.select(path)
77
- else
78
- nodes = tree.select('*') # all nodes
79
- end
80
- YES.constraints.each do |c|
81
- next unless Constraints::NodeConstraint === c
82
- checklist = c.checklist(spec, tree, nodes)
83
- selection = checklist.select{ |v| v.valid? }
84
- nodes.concat(selection.map{ |s| s.node })
85
- end
86
- nodes
87
- else
88
- tree.select(ypath)
89
- end
90
- end
91
-
92
- ## Validate if a node is the only one of it's value in a sequence
93
- ## or mapping.
94
- #def validate_unique(spec, nodes)
95
- # return unless unique = spec['unique']
96
- # # TODO: how to do?
97
- #end
98
-
99
- end
100
-
101
- end
@@ -1,13 +0,0 @@
1
- module YES
2
-
3
- class And < Array
4
- def intialize(data)
5
- concat(data)
6
- end
7
- end
8
-
9
- YAML.add_domain_type('http://rubyworks.github.com/yes', 'and') do |data|
10
- And.new(data)
11
- end
12
-
13
- end