yes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,91 @@
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
@@ -0,0 +1,62 @@
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
@@ -0,0 +1,2 @@
1
+ # TODO: Idea from Kwalify, to use the scheam to grenerate a validating RUby class.
2
+
@@ -0,0 +1,101 @@
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
@@ -0,0 +1,13 @@
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
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: "yes"
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Thomas Sawyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-07-13 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: qed
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :development
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: detroit
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id002
37
+ description: YAML Easy Schemas it a straight-foward but powerful YPath-based schema format and validation program for YAML documents.
38
+ email: transfire@gmail.com
39
+ executables:
40
+ - yes-lint
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - README.rdoc
45
+ files:
46
+ - .ruby
47
+ - .yardopts
48
+ - bin/yes-lint
49
+ - data/yes/yes.yes
50
+ - lib/yes/cli.rb
51
+ - lib/yes/constraints/abstract_constraint.rb
52
+ - lib/yes/constraints/choice.rb
53
+ - lib/yes/constraints/count.rb
54
+ - lib/yes/constraints/exclusive.rb
55
+ - lib/yes/constraints/fnmatch.rb
56
+ - lib/yes/constraints/inclusive.rb
57
+ - lib/yes/constraints/key.rb
58
+ - lib/yes/constraints/kind.rb
59
+ - lib/yes/constraints/length.rb
60
+ - lib/yes/constraints/node_constraint.rb
61
+ - lib/yes/constraints/range.rb
62
+ - lib/yes/constraints/regexp.rb
63
+ - lib/yes/constraints/required.rb
64
+ - lib/yes/constraints/requires.rb
65
+ - lib/yes/constraints/tag.rb
66
+ - lib/yes/constraints/tree_constraint.rb
67
+ - lib/yes/constraints/type.rb
68
+ - lib/yes/constraints/value.rb
69
+ - lib/yes/genclass.rb
70
+ - lib/yes/lint.rb
71
+ - lib/yes/logical_and.rb
72
+ - lib/yes.rb
73
+ - HISTORY.rdoc
74
+ - README.rdoc
75
+ - QED.rdoc
76
+ - LICENSE.rdoc
77
+ - THANKS.rdoc
78
+ homepage: http://rubyworks.github.com/yes
79
+ licenses:
80
+ - BSD-2-Clause
81
+ - BSD-2-Clause
82
+ post_install_message:
83
+ rdoc_options:
84
+ - --title
85
+ - YES API
86
+ - --main
87
+ - README.rdoc
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ requirements: []
103
+
104
+ rubyforge_project: "yes"
105
+ rubygems_version: 1.8.2
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: YAML Easy Schema
109
+ test_files: []
110
+