yes 0.0.1

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.
@@ -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
+