grayskull 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 <Your Name Here>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
File without changes
data/bin/grayskull ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "grayskull"
4
+ require "optparse"
5
+
6
+ Grayskull::CLI.start
data/lib/grayskull.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'grayskull/version'
2
+
3
+ # Base module for gem.
4
+ module Grayskull
5
+ autoload :Formats, 'grayskull/formats'
6
+ autoload :Validator, 'grayskull/validator'
7
+ autoload :CLI, 'grayskull/cli'
8
+ end
@@ -0,0 +1,27 @@
1
+ require 'thor'
2
+
3
+ module Grayskull
4
+
5
+ # The *CLI* class provides an interface for the command line functions
6
+ class CLI < Thor
7
+
8
+ desc "validate FILE SCHEMA" ,"Checks TEMPLATE is a valid file and matches SCHEMA."
9
+ # Creates a new *Validator* and validates the file
10
+ def validate(file,schema)
11
+ validator = Grayskull::Validator.new(file,schema)
12
+ results = validator.validate
13
+
14
+ if !results['result']
15
+ puts 'Validation Failed!'
16
+ results['errors'].each{
17
+ |error|
18
+ puts error
19
+ }
20
+ else
21
+ puts 'Validated Successfully!'
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,29 @@
1
+ module Grayskull
2
+
3
+ module Formats
4
+
5
+ autoload :YAMLHandler, 'grayskull/formats/yaml_handler'
6
+ autoload :JSONHandler, 'grayskull/formats/json_handler'
7
+
8
+ FILENAME_PATTERN = /(.+)\.([^\/\.]+)/
9
+
10
+ def self.detect_format(filename)
11
+ matches = FILENAME_PATTERN.match(filename.downcase).to_a
12
+ if matches
13
+ ext = matches[2]
14
+ case ext
15
+ when 'json'
16
+ return 'json'
17
+ when 'yml'
18
+ return 'yaml'
19
+ else
20
+ raise TypeError, "Not a supported file format: " + ext
21
+ end
22
+ else
23
+ raise LoadError, "Not a valid filename: " + filename
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,23 @@
1
+ require 'json'
2
+
3
+ module Grayskull
4
+
5
+ module Formats
6
+
7
+ class JSONHandler
8
+
9
+ def self.load(file)
10
+ loaded = File.open(file)
11
+ content = loaded.gets nil
12
+ begin
13
+ return JSON.parse(content)
14
+ rescue Exception => e
15
+ raise e.class, 'File could not be parsed as valid JSON'
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'yaml'
2
+
3
+ module Grayskull
4
+
5
+ module Formats
6
+
7
+ class YAMLHandler
8
+
9
+ def self.load(file)
10
+ begin
11
+ return YAML.load_file(file)
12
+ rescue Exception => e
13
+ raise e.class, 'File could not be parsed as valid YAML'
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,184 @@
1
+ module Grayskull
2
+
3
+ class Validator
4
+
5
+ def initialize(file,schema)
6
+
7
+ @file = file
8
+ @schema = schema
9
+
10
+ @loaded_file = self.load(file)
11
+ @loaded_schema = self.load(schema)
12
+ @types = @loaded_schema['types'] || {}
13
+
14
+ @errors = []
15
+ end
16
+
17
+ def load(file)
18
+
19
+ format = Formats::detect_format File.basename(file)
20
+
21
+ case format
22
+ when 'yaml'
23
+ return Formats::YAMLHandler.load(file)
24
+ when 'json'
25
+ return Formats::JSONHandler.load(file)
26
+ end
27
+
28
+ end
29
+
30
+ def validate()
31
+ failed = []
32
+
33
+ @loaded_schema['sections'].each{
34
+ |section|
35
+
36
+ #check required sections are there
37
+ if (section['required'] && !@loaded_file.has_key?(section['name']))
38
+ @errors.push('Error: missing required section - ' + section['name'])
39
+ failed.push(section['name'])
40
+ elsif @loaded_file.has_key?(section['name'])
41
+ node = @loaded_file[section['name']]
42
+ validated = match_node(node,section,section['name'])
43
+ if(!validated)
44
+ failed.push(section['name'])
45
+ end
46
+ end
47
+
48
+ }
49
+
50
+ result = {}
51
+ result["result"] = failed.empty?
52
+
53
+ if !failed.empty? && !@errors.empty?
54
+ result["errors"] = @errors
55
+ end
56
+
57
+ return result
58
+ end
59
+
60
+ # Checks template node matches the schema.
61
+ #
62
+ # Checks type of node against expected type and
63
+ # checks any children are of the accepted types.
64
+ def match_node(node,expected,label)
65
+
66
+ #check type
67
+ if !check_type(node,expected['type'],label,expected['ok_empty'])
68
+ return false
69
+ end
70
+
71
+ if (node.kind_of?(Hash) || node.kind_of?(Array))
72
+
73
+ if node.empty? && !expected['ok_empty']
74
+ @errors.push('Error: node ' + label + ' cannot be empty')
75
+ return false
76
+ elsif !node.empty? && expected.has_key?('accepts')
77
+ valid_content = false
78
+
79
+ if node.kind_of?(Hash)
80
+ matched = []
81
+ unmatched = []
82
+ node.each_pair{
83
+ |key,value|
84
+
85
+ expected['accepts'].each{
86
+ |accepts|
87
+
88
+ result = check_type(value,accepts,key)
89
+
90
+ if result
91
+ matched.push(key)
92
+ if !unmatched.find_index(key).nil?
93
+ unmatched.slice(unmatched.find_index(key))
94
+ end
95
+ break
96
+ else
97
+ unmatched.push(key)
98
+ end
99
+
100
+ }
101
+
102
+ }
103
+
104
+ if(matched.count==node.count)
105
+ valid_content = true
106
+ else
107
+ unmatched.each{
108
+ |node|
109
+
110
+ @errors.push('Error: node ' + node + ' is not of an accepted type. Should be one of ' + expected['accepts'].join(', '))
111
+ }
112
+ end
113
+
114
+ elsif node.kind_of?(Array)
115
+ matched = []
116
+ unmatched = []
117
+ node.each_index{
118
+ |n|
119
+
120
+ expected['accepts'].each{
121
+ |accepts|
122
+
123
+ key = label + '[' + n.to_s + ']'
124
+ result = check_type(node[n],accepts,key)
125
+
126
+ if result
127
+
128
+ matched.push(key)
129
+ if !unmatched.find_index(key).nil?
130
+ unmatched.slice(unmatched.find_index(key))
131
+ end
132
+ break
133
+ else
134
+ unmatched.push(key)
135
+ end
136
+
137
+ }
138
+ }
139
+
140
+ if(matched.count==node.count)
141
+ valid_content = true
142
+ else
143
+ unmatched.each{
144
+ |node|
145
+
146
+ @errors.push('Error: node ' + node + ' is not of an accepted type. Should be one of ' + expected['accepts'].join(', '))
147
+ }
148
+ end
149
+
150
+ end
151
+
152
+ if !valid_content
153
+ @errors.push('Error: node ' + label + ' contains an unaccepted type.')
154
+ return false
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+ return true
161
+
162
+ end
163
+
164
+ # Checks that the node is of the correct type
165
+ #
166
+ # If the expected node is a custom node type as defined in the schema
167
+ # It will run `match_node` to check that the node schema matches the
168
+ # custom type.
169
+ def check_type(node,expected_type,label,accept_nil = false)
170
+
171
+ valid_type = true;
172
+ if(@types.has_key?(expected_type))
173
+ valid_type = match_node(node,@types[expected_type],label)
174
+ elsif node.class.to_s != expected_type && !(node.kind_of?(NilClass) && (expected_type=='empty' || accept_nil))
175
+ valid_type = false
176
+ end
177
+
178
+ return valid_type
179
+
180
+ end
181
+
182
+ end
183
+
184
+ end
@@ -0,0 +1,3 @@
1
+ module Grayskull
2
+ Grayskull::VERSION = "0.1.2"
3
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grayskull
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 2
9
+ version: 0.1.2
10
+ platform: ruby
11
+ authors:
12
+ - Will McKenzie
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-10-01 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: thor
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: json
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ description: Will validate YAML and JSON files based on a provided schema
47
+ email:
48
+ - will@oinutter.co.uk
49
+ executables:
50
+ - grayskull
51
+ extensions: []
52
+
53
+ extra_rdoc_files: []
54
+
55
+ files:
56
+ - README
57
+ - LICENSE
58
+ - lib/grayskull/cli.rb
59
+ - lib/grayskull/formats/json_handler.rb
60
+ - lib/grayskull/formats/yaml_handler.rb
61
+ - lib/grayskull/formats.rb
62
+ - lib/grayskull/validator.rb
63
+ - lib/grayskull/version.rb
64
+ - lib/grayskull.rb
65
+ - bin/grayskull
66
+ has_rdoc: true
67
+ homepage: http://github.com/OiNutter/grayskull
68
+ licenses:
69
+ - MIT
70
+ post_install_message:
71
+ rdoc_options: []
72
+
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ requirements: []
92
+
93
+ rubyforge_project: grayskull
94
+ rubygems_version: 1.3.7
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Validates data files based on a provided schema
98
+ test_files: []
99
+