kwalify 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +29 -62
- data/README.txt +39 -11
- data/bin/kwalify +16 -177
- data/doc/users-guide.html +279 -145
- data/examples/address-book/Makefile +1 -0
- data/examples/address-book/address-book.schema.yaml +10 -10
- data/examples/invoice/Makefile +1 -0
- data/examples/invoice/invoice.schema.yaml +17 -34
- data/examples/tapkit/Makefile +5 -0
- data/examples/tapkit/tapkit.schema.yaml +137 -0
- data/examples/tapkit/tapkit.yaml +85 -0
- data/lib/kwalify.rb +12 -3
- data/lib/kwalify/errors.rb +36 -60
- data/lib/kwalify/main-program.rb +214 -0
- data/lib/kwalify/messages.rb +91 -0
- data/lib/kwalify/meta-validator.rb +199 -76
- data/lib/kwalify/rule.rb +326 -0
- data/lib/kwalify/types.rb +86 -20
- data/lib/kwalify/util/assert-diff.rb +1 -1
- data/lib/kwalify/util/option-parser.rb +1 -1
- data/lib/kwalify/util/yaml-helper.rb +6 -6
- data/lib/kwalify/validator.rb +111 -218
- data/test/test-metavalidator.rb +608 -0
- data/test/test-metavalidator.rb.error +490 -0
- data/test/test-validator.rb +526 -0
- data/test/test.rb +12 -351
- data/todo.txt +14 -4
- metadata +12 -3
- data/lib/kwalify/error-msg.rb +0 -41
data/ChangeLog
CHANGED
@@ -1,62 +1,29 @@
|
|
1
|
-
.=title:
|
2
|
-
.?
|
3
|
-
.?
|
4
|
-
.?
|
5
|
-
|
6
|
-
.: 2005-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
.- [enhance] add 'lib/kwalify/util/option-parser.rb'
|
31
|
-
|
32
|
-
.: 2005-07-25 (rev.5)
|
33
|
-
.- [enhance] Kwalify::DEFAULT_TYPE is String
|
34
|
-
.- [change] array index starts with 1
|
35
|
-
.- [change] command-line option '-s' is changed to '-f'
|
36
|
-
.- [enhance] new command-line option '-s' (silent)
|
37
|
-
.- [change] output format of bin/kwalify changed
|
38
|
-
.- [enhance] untabify schema and document file using YAML::Helper
|
39
|
-
.- [enhance] add new file 'lib/kwalify/util/yaml-helper.rb'
|
40
|
-
|
41
|
-
.: 2005-07-25 (rev.4)
|
42
|
-
.- [change] class Kwalify::RuleSet is renamed to Kwalify::Schema
|
43
|
-
.- [enhance] add new class Kwalify::Validator
|
44
|
-
.- [enhance] add bin/kwalify
|
45
|
-
.- [enhance] add doc/users-guide.txt
|
46
|
-
.- [enhance] add README.txt, COPYING, setup.rb, kwalify.gemspec
|
47
|
-
|
48
|
-
.: 2005-07-25 (rev.3)
|
49
|
-
.- [change] use mappings at elements of Hash
|
50
|
-
.- [change] rename 'children' to 'elements'
|
51
|
-
.- [enhance] support recursive collections
|
52
|
-
.- [enhance] add RuleSet#inspect
|
53
|
-
.- [change] rename 'error-messages.rb' to 'error-msg.rb'
|
54
|
-
.- [change] rename Text and Boolean to Kwalify::Text and Kwalify::Boolean
|
55
|
-
|
56
|
-
.: 2005-07-24 (rev.2)
|
57
|
-
.- [enhance] add pattern check
|
58
|
-
.- [enhance] add Text class
|
59
|
-
.- [enhance] add test script
|
60
|
-
|
61
|
-
.: 2005-07-24 (rev.1)
|
62
|
-
.- initial commit
|
1
|
+
.=title: ChangeLog
|
2
|
+
.?release: $Release: 0.2.0 $
|
3
|
+
.?lastupdate: $Date$
|
4
|
+
.?version: $Rev$
|
5
|
+
|
6
|
+
.: 2005-09-25 (release 0.2.0)
|
7
|
+
.* Enhances:
|
8
|
+
.- New type 'scalar' and 'timestamp' added
|
9
|
+
.- Add new rule 'range:' which validates value range.
|
10
|
+
See users' guide for details.
|
11
|
+
.- Add new rule 'length:' which validate length of string value.
|
12
|
+
See users' guide for details.
|
13
|
+
.- Add experimental rule 'assert:' which validates value with an
|
14
|
+
expression. See users' guide for details.
|
15
|
+
.- New method 'Kwalify::Validator#validate_hook()' is added.
|
16
|
+
This method is called by Kwalify::Validator#validate().
|
17
|
+
See users' guide for details.
|
18
|
+
.- New class 'MetaValidator' added.
|
19
|
+
.- New test script 'test/test-metavalidator.rb' added.
|
20
|
+
.* Changes:
|
21
|
+
.- Type name changed to suite YAML data type:
|
22
|
+
.= string -> str
|
23
|
+
.= integer -> int
|
24
|
+
.= boolean -> bool
|
25
|
+
.- Error index starts with 0 (before starts with 1).
|
26
|
+
.- Class 'Schema' is renamed to 'Rule'.
|
27
|
+
|
28
|
+
.: 2005-08-01 (release 0.1.0)
|
29
|
+
.- beta release
|
data/README.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.=title: README
|
2
|
-
.?version: $Rev:
|
3
|
-
.?lastupdate: $Date: 2005-
|
4
|
-
.?release: $Release: 0.
|
2
|
+
.?version: $Rev: 18 $
|
3
|
+
.?lastupdate: $Date: 2005-09-25 22:36:35 +0900 (Sun, 25 Sep 2005) $
|
4
|
+
.?release: $Release: 0.2.0 $
|
5
5
|
|
6
6
|
|
7
7
|
.$ About Kwalify
|
@@ -15,14 +15,42 @@
|
|
15
15
|
|
16
16
|
.$ Installation
|
17
17
|
|
18
|
-
Just type 'gem install --remote kwalify' if you have installed RubyGems.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
.* Just type 'gem install --remote kwalify' if you have installed RubyGems.
|
19
|
+
.====================
|
20
|
+
$ sudo gem install --remote kwalify
|
21
|
+
.====================
|
22
|
+
|
23
|
+
.* If you can be root user, use 'setup.rb' as following:
|
24
|
+
.====================
|
25
|
+
$ tar xjf kwalify_x.x.x.tar.bz2
|
26
|
+
$ cd kwalify_x.x.x/
|
27
|
+
$ ruby setup.rb config
|
28
|
+
$ ruby setup.rb setup
|
29
|
+
$ sudo ruby setup.rb install
|
30
|
+
.====================
|
31
|
+
|
32
|
+
.* If you can't be root user, copy script and libraries to proper directory.
|
33
|
+
.====================
|
34
|
+
$ tar xjf kwalify_x.x.x.tar.bz2
|
35
|
+
$ cd kwalify_x.x.x/
|
36
|
+
$ mkdir -p $HOME/bin
|
37
|
+
$ cp -a bin/* $HOME/bin
|
38
|
+
$ export PATH=$PATH:$HOME/bin
|
39
|
+
$ mkdir -p $HOME/lib/ruby
|
40
|
+
$ cp -a lib/* $HOME/lib/ruby
|
41
|
+
$ export RUBYLIB=$HOME/lib/ruby
|
42
|
+
.====================
|
43
|
+
|
44
|
+
.* Or use 'contrib/inline-require' script to concatenate all script and
|
45
|
+
libraries into one file.
|
46
|
+
.====================
|
47
|
+
$ tar xjf kwalify_x.x.x.tar.bz2
|
48
|
+
$ cd kwalify_x.x.x/
|
49
|
+
$ unset RUBYLIB
|
50
|
+
$ ruby contrib/inline-require -I ./lib bin/kwalify > kwalify
|
51
|
+
$ mv kwalify $HOME/bin
|
52
|
+
$ chmod a+x $HOME/bin/kwalify
|
53
|
+
.====================
|
26
54
|
|
27
55
|
|
28
56
|
.$ License
|
data/bin/kwalify
CHANGED
@@ -1,185 +1,24 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
###
|
4
|
-
### $Rev:
|
5
|
-
### $Release: 0.
|
4
|
+
### $Rev: 12 $
|
5
|
+
### $Release: 0.2.0 $
|
6
6
|
### copyright(c) 2005 kuwata-lab all rights reserved.
|
7
7
|
###
|
8
8
|
|
9
9
|
require 'kwalify'
|
10
|
-
require '
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@command = command
|
25
|
-
@options, @proerties = parse_argv(argv)
|
26
|
-
@filenames = argv
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def execute(out=$stdout)
|
31
|
-
if @options[:help] || @options[:version]
|
32
|
-
$stderr.puts "Kwalify: #{RELEASE}" if @options[:version]
|
33
|
-
$stderr.puts usage() if @options[:help]
|
34
|
-
return
|
35
|
-
end
|
36
|
-
if !@options[:meta] && !@options[:schema]
|
37
|
-
raise CommandOptionError.new("command-line option '-f' or '-m' required.")
|
38
|
-
end
|
39
|
-
#
|
40
|
-
if @options[:meta]
|
41
|
-
meta_validate(out)
|
42
|
-
else
|
43
|
-
validate(out)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
|
51
|
-
def meta_validate(out)
|
52
|
-
meta_validator = @options[:meta2] ? Kwalify.meta_validator2() : Kwalify.meta_validator()
|
53
|
-
if @filenames.empty?
|
54
|
-
_meta_validate(out, meta_validator, nil)
|
55
|
-
else
|
56
|
-
@filenames.each do |fname|
|
57
|
-
_meta_validate(out, meta_validator, fname)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
def _meta_validate(out, meta_validator, filename=nil)
|
64
|
-
s = filename ? File.open(filename) { |f| f.read() } : $stdin.read()
|
65
|
-
s = YamlHelper.untabify(s) if @options[:untabify]
|
66
|
-
yaml = YAML.load(s)
|
67
|
-
yaml = yaml.value if yaml.is_a?(YAML::Syck::DomainType)
|
68
|
-
filename ||= "(stdin)"
|
69
|
-
if !yaml || yaml.empty?
|
70
|
-
out.puts "#{filename}: empty."
|
71
|
-
return
|
72
|
-
end
|
73
|
-
errors = meta_validator.validate(yaml)
|
74
|
-
if !errors.empty?
|
75
|
-
out.puts "#{filename}: NG!"
|
76
|
-
errors.each { |error| out.puts " - #{error.message}" }
|
77
|
-
return
|
78
|
-
end
|
79
|
-
begin
|
80
|
-
validator = Kwalify::Validator.new(yaml) # error raised when schema is wrong
|
81
|
-
out.puts "#{filename}: ok." unless @options[:silent]
|
82
|
-
rescue Kwalify::SchemaError => ex
|
83
|
-
out.puts "#{filename}: NG! #{ex.message}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
def validate(out)
|
89
|
-
schema_filename = @options[:schema]
|
90
|
-
s = File.open(schema_filename) { |f| f.read() }
|
91
|
-
s = YamlHelper.untabify(s) if @options[:untabify]
|
92
|
-
yaml = YAML.load(s)
|
93
|
-
yaml = yaml.value if yaml.is_a?(YAML::Syck::DomainType)
|
94
|
-
validator = Kwalify::Validator.new(yaml)
|
95
|
-
#
|
96
|
-
if @filenames.empty?
|
97
|
-
_validate(out, validator, nil)
|
98
|
-
else
|
99
|
-
@filenames.each do |fname|
|
100
|
-
_validate(out, validator, fname)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
def _validate(out, validator, filename=nil)
|
107
|
-
s = filename ? File.open(filename) { |f| f.read() } : $stdin.read()
|
108
|
-
s = YamlHelper.untabify(s) if @options[:untabify]
|
109
|
-
stream = YAML::load_stream(s)
|
110
|
-
filename ||= "(stdin)"
|
111
|
-
i = 0
|
112
|
-
stream.documents.each do |document|
|
113
|
-
i += 1
|
114
|
-
document = document.value if document.is_a?(YAML::Syck::DomainType)
|
115
|
-
if !document || document.empty?
|
116
|
-
out.puts "#{filename}: empty."
|
117
|
-
return
|
118
|
-
end
|
119
|
-
errors = validator.validate(document)
|
120
|
-
if errors.empty?
|
121
|
-
out.puts "#{filename}\##{i}: valid." unless @options[:silent]
|
122
|
-
else
|
123
|
-
out.puts "#{filename}\##{i}: INVALID"
|
124
|
-
errors.each { |error| out.puts " - #{error.message}" }
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
def usage()
|
131
|
-
s = ""
|
132
|
-
s << "Usage1: #{@command} [-hvs] -f schema.yaml document.yaml [document2.yaml ...]\n"
|
133
|
-
s << "Usage2: #{@command} [-hvs] -c schema.yaml [schema2.yaml ...]\n"
|
134
|
-
s << " -h, --help : help\n"
|
135
|
-
s << " -v : version\n"
|
136
|
-
s << " -s : silent\n"
|
137
|
-
s << " -f schema.yaml : schema definition file\n"
|
138
|
-
s << " -m : meta-validation mode\n"
|
139
|
-
s << " -t : expand tab character automatically\n"
|
140
|
-
return s
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
def parse_argv(argv)
|
145
|
-
opt_parser = CommandOptionParser.new("hvstmM", "f")
|
146
|
-
#opts, props = opt_parser.parse(argv)
|
147
|
-
#properties = {}
|
148
|
-
#props.each do |pname, pvalue|
|
149
|
-
# key = pname.gsub(/-/, '_').intern
|
150
|
-
# value = value == nil ? true: CommandOptionParser.to_value(pvalue)
|
151
|
-
# properties[key] = value
|
152
|
-
#end
|
153
|
-
auto_convert = true
|
154
|
-
opts, properties = opt_parser.parse(argv, auto_convert)
|
155
|
-
options = {}
|
156
|
-
options[:help] = opts[?h] || properties[:help]
|
157
|
-
options[:version] = opts[?v] || properties[:version]
|
158
|
-
options[:silent] = opts[?s]
|
159
|
-
options[:schema] = opts[?f]
|
160
|
-
options[:meta] = opts[?m] || opts[?M]
|
161
|
-
options[:meta2] = opts[?M]
|
162
|
-
options[:untabify] = opts[?t]
|
163
|
-
return options, properties
|
164
|
-
end
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
|
171
|
-
#if __FILE__ == $0
|
172
|
-
unless defined?(KWALIFY_NOEXEC)
|
173
|
-
command = File.basename($0)
|
174
|
-
begin
|
175
|
-
main = Kwalify::Main.new(command, ARGV)
|
176
|
-
main.execute()
|
177
|
-
exit 0
|
178
|
-
rescue Kwalify::KwalifyError => ex
|
179
|
-
$stderr.puts "ERROR: #{ex.message}"
|
180
|
-
exit 1
|
181
|
-
#rescue => ex
|
182
|
-
# $stderr.puts ex.message
|
183
|
-
# exit 1
|
184
|
-
end
|
10
|
+
require 'kwalify/main-program'
|
11
|
+
|
12
|
+
|
13
|
+
command = File.basename($0)
|
14
|
+
begin
|
15
|
+
main = Kwalify::MainProgram.new(ARGV, command)
|
16
|
+
s = main.execute()
|
17
|
+
print s if s
|
18
|
+
rescue CommandOptionError => ex
|
19
|
+
$stderr.puts ex.message
|
20
|
+
exit 1
|
21
|
+
rescue Kwalify::KwalifyError => ex
|
22
|
+
$stderr.puts "ERROR: #{ex.message}"
|
23
|
+
exit 1
|
185
24
|
end
|
data/doc/users-guide.html
CHANGED
@@ -15,14 +15,46 @@
|
|
15
15
|
<div align="left"><h1>Kwalify Users' Guide</h1></div>
|
16
16
|
<div align="left">
|
17
17
|
makoto kuwata <kwa(at)kuwata-lab.com><br>
|
18
|
-
last update: $Date: 2005-
|
18
|
+
last update: $Date: 2005-09-25 22:36:35 +0900 (Sun, 25 Sep 2005) $<br>
|
19
19
|
</div>
|
20
20
|
|
21
21
|
<a name="preface"></a>
|
22
22
|
<h2 class="section1">Preface</h2>
|
23
23
|
<p>Kwalify<sup>(<a href="#fnref:1" name="fnlink:1">*1</a>)</sup> is a tiny schema validator for YAML document.
|
24
24
|
</p>
|
25
|
-
<p>
|
25
|
+
<p>Do you know "80-20 rule" known as Pareto Law? This rule suggests that 20% of the population owns 80% of the wealth.
|
26
|
+
Kwalify is based on a new "50-5 rule" which suggests that 5% of the population owns 50 of the wealth.
|
27
|
+
This rule is more aggressive and cost-effective than Pareto Law. The rule is named as "Levi's Law".
|
28
|
+
</p>
|
29
|
+
<div align="center">
|
30
|
+
<table class="table1" border="1" cellspacing="0">
|
31
|
+
<tr class="tr1">
|
32
|
+
<th class="th1">schema technology</th>
|
33
|
+
<th class="th1">(A) cover range</th>
|
34
|
+
<th class="th1">(B) cost to pay</th>
|
35
|
+
<th class="th1">(A)/(B) effectiveness</th>
|
36
|
+
</tr>
|
37
|
+
<tr class="tr1">
|
38
|
+
<td class="td1">XML Schema</td>
|
39
|
+
<td class="td1">96%</td>
|
40
|
+
<td class="td1">80%</td>
|
41
|
+
<td class="td1">1.2 (= 96/80)</td>
|
42
|
+
</tr>
|
43
|
+
<tr class="tr1">
|
44
|
+
<td class="td1">RelaxNG</td>
|
45
|
+
<td class="td1">80%</td>
|
46
|
+
<td class="td1">20%</td>
|
47
|
+
<td class="td1">4.0 (= 80/20)</td>
|
48
|
+
</tr>
|
49
|
+
<tr class="tr1">
|
50
|
+
<td class="td1">Kwalify</td>
|
51
|
+
<td class="td1">50%</td>
|
52
|
+
<td class="td1">5%</td>
|
53
|
+
<td class="td1">10.0 (= 50/5)</td>
|
54
|
+
</tr>
|
55
|
+
</table>
|
56
|
+
</div>
|
57
|
+
<p>Kwalify is very small and in fact very poor compared to RelaxNG or XML Schema.
|
26
58
|
I hope you extend/customize Kwalify for your own way.
|
27
59
|
</p>
|
28
60
|
Table of Contents:
|
@@ -50,6 +82,8 @@ Table of Contents:
|
|
50
82
|
</li>
|
51
83
|
<li><a href="#schema-rules">Rules</a>
|
52
84
|
</li>
|
85
|
+
<li><a href="#schema-hook">Validator#validator_hook()</a>
|
86
|
+
</li>
|
53
87
|
<li><a href="#schema-block">Validator with Block</a>
|
54
88
|
</li>
|
55
89
|
</ul>
|
@@ -89,7 +123,7 @@ usage2: validate schema definition in command-line</div>
|
|
89
123
|
</p>
|
90
124
|
<dl class="dl3">
|
91
125
|
<dt class="dt3"><strong>
|
92
|
-
<code>-h</code>, <code>--help</code
|
126
|
+
<code>-h</code>, <code>--help</code> </strong></dt>
|
93
127
|
<dd class="dd3">
|
94
128
|
Print help message.
|
95
129
|
</dd>
|
@@ -129,17 +163,15 @@ validate YAML document in Ruby script</div>
|
|
129
163
|
<pre class="program">require 'kwalify'
|
130
164
|
|
131
165
|
## parse schema definition and create validator
|
132
|
-
|
133
|
-
|
134
|
-
validator = Kwalify::Validator.new(schema_def) # raises Kwalify::SchemaError if wrong
|
166
|
+
schema = YAML.load_file('schema.yaml')
|
167
|
+
validator = Kwalify::Validator.new(schema) # raises Kwalify::SchemaError if wrong
|
135
168
|
|
136
169
|
## validate YAML document
|
137
|
-
|
138
|
-
document = YAML.load(str)
|
170
|
+
document = YAML.load_file('document.yaml')
|
139
171
|
error_list = validator.validate(document)
|
140
172
|
unless error_list.empty?
|
141
|
-
error_list.each do |error| # error is Kwalify::
|
142
|
-
|
173
|
+
error_list.each do |error| # error is Kwalify::ValidationError
|
174
|
+
puts "[#{error.path}] #{error.message}"
|
143
175
|
end
|
144
176
|
end
|
145
177
|
</pre>
|
@@ -158,7 +190,7 @@ end
|
|
158
190
|
<code>schema01.yaml</code> : sequence of string</div>
|
159
191
|
<pre class="program">type: seq
|
160
192
|
sequence:
|
161
|
-
- type:
|
193
|
+
- type: str
|
162
194
|
</pre>
|
163
195
|
<a name="document01a.yaml"></a>
|
164
196
|
<div class="program_caption">
|
@@ -170,7 +202,7 @@ sequence:
|
|
170
202
|
<div class="terminal_caption">
|
171
203
|
validate</div>
|
172
204
|
<pre class="terminal">$ kwalify -f schema01.yaml document01a.yaml
|
173
|
-
document01a.yaml#
|
205
|
+
document01a.yaml#0: valid.
|
174
206
|
</pre>
|
175
207
|
<a name="document01b.yaml"></a>
|
176
208
|
<div class="program_caption">
|
@@ -182,10 +214,10 @@ document01a.yaml#1: valid.
|
|
182
214
|
<div class="terminal_caption">
|
183
215
|
validate</div>
|
184
216
|
<pre class="terminal">$ kwalify -f schema01.yaml document01b.yaml
|
185
|
-
document01b.yaml#
|
186
|
-
- [/
|
217
|
+
document01b.yaml#0: INVALID
|
218
|
+
- [/1] '123': not a string.
|
187
219
|
</pre>
|
188
|
-
<p>Default '<code>type:</code>' is <code>
|
220
|
+
<p>Default '<code>type:</code>' is <code>str</code> so you can omit '<code>type: str</code>'.
|
189
221
|
</p>
|
190
222
|
<br>
|
191
223
|
|
@@ -198,13 +230,13 @@ document01b.yaml#1: INVALID
|
|
198
230
|
<pre class="program">type: map
|
199
231
|
mapping:
|
200
232
|
name:
|
201
|
-
type:
|
233
|
+
type: str
|
202
234
|
required: yes
|
203
235
|
email:
|
204
|
-
type:
|
236
|
+
type: str
|
205
237
|
pattern: /@/
|
206
238
|
age:
|
207
|
-
type:
|
239
|
+
type: int
|
208
240
|
birth:
|
209
241
|
type: date
|
210
242
|
</pre>
|
@@ -219,7 +251,7 @@ birth: 1985-01-01
|
|
219
251
|
<div class="terminal_caption">
|
220
252
|
validate</div>
|
221
253
|
<pre class="terminal">$ kwalify -f schema02.yaml document02a.yaml
|
222
|
-
document02a.yaml#
|
254
|
+
document02a.yaml#0: valid.
|
223
255
|
</pre>
|
224
256
|
<a name="document02b.yaml"></a>
|
225
257
|
<div class="program_caption">
|
@@ -232,10 +264,10 @@ birth: Jun 01, 1985
|
|
232
264
|
<div class="terminal_caption">
|
233
265
|
validate</div>
|
234
266
|
<pre class="terminal">$ kwalify -f schema02.yaml document02b.yaml
|
235
|
-
document02b.yaml#
|
236
|
-
- [/birth]
|
237
|
-
- [/age]
|
238
|
-
- [/email] 'foo(at)mail.com'
|
267
|
+
document02b.yaml#0: INVALID
|
268
|
+
- [/birth] 'Jun 01, 1985': not a date.
|
269
|
+
- [/age] 'twenty': not a integer.
|
270
|
+
- [/email] 'foo(at)mail.com': not matched to pattern /@/.
|
239
271
|
</pre>
|
240
272
|
<br>
|
241
273
|
|
@@ -250,10 +282,10 @@ sequence:
|
|
250
282
|
- type: map
|
251
283
|
mapping:
|
252
284
|
name:
|
253
|
-
type:
|
285
|
+
type: str
|
254
286
|
required: true
|
255
287
|
email:
|
256
|
-
type:
|
288
|
+
type: str
|
257
289
|
</pre>
|
258
290
|
<a name="document03a.yaml"></a>
|
259
291
|
<div class="program_caption">
|
@@ -268,7 +300,7 @@ sequence:
|
|
268
300
|
<div class="terminal_caption">
|
269
301
|
validate</div>
|
270
302
|
<pre class="terminal">$ kwalify -f schema03.yaml document03a.yaml
|
271
|
-
document03a.yaml#
|
303
|
+
document03a.yaml#0: valid.
|
272
304
|
</pre>
|
273
305
|
<a name="document03b.yaml"></a>
|
274
306
|
<div class="program_caption">
|
@@ -283,10 +315,10 @@ document03a.yaml#1: valid.
|
|
283
315
|
<div class="terminal_caption">
|
284
316
|
validate</div>
|
285
317
|
<pre class="terminal">$ kwalify -f schema03.yaml document03b.yaml
|
286
|
-
document03b.yaml#
|
287
|
-
- [/
|
288
|
-
- [/
|
289
|
-
- [/
|
318
|
+
document03b.yaml#0: INVALID
|
319
|
+
- [/1] key 'name:' is required.
|
320
|
+
- [/1] key 'naem:' is undefined.
|
321
|
+
- [/2] key 'mail:' is undefined.
|
290
322
|
</pre>
|
291
323
|
<br>
|
292
324
|
|
@@ -299,23 +331,23 @@ document03b.yaml#1: INVALID
|
|
299
331
|
<pre class="program">type: map
|
300
332
|
mapping:
|
301
333
|
company:
|
302
|
-
type:
|
334
|
+
type: str
|
303
335
|
required: yes
|
304
336
|
email:
|
305
|
-
type:
|
337
|
+
type: str
|
306
338
|
employees:
|
307
339
|
type: seq
|
308
340
|
sequence:
|
309
341
|
- type: map
|
310
342
|
mapping:
|
311
343
|
code:
|
312
|
-
type:
|
344
|
+
type: int
|
313
345
|
required: yes
|
314
346
|
name:
|
315
|
-
type:
|
347
|
+
type: str
|
316
348
|
required: yes
|
317
349
|
email:
|
318
|
-
type:
|
350
|
+
type: str
|
319
351
|
</pre>
|
320
352
|
<a name="document04a.yaml"></a>
|
321
353
|
<div class="program_caption">
|
@@ -333,7 +365,7 @@ employees:
|
|
333
365
|
<div class="terminal_caption">
|
334
366
|
validate</div>
|
335
367
|
<pre class="terminal">$ kwalify -f schema04.yaml document04a.yaml
|
336
|
-
document04a.yaml#
|
368
|
+
document04a.yaml#0: valid.
|
337
369
|
</pre>
|
338
370
|
<a name="document04b.yaml"></a>
|
339
371
|
<div class="program_caption">
|
@@ -351,9 +383,9 @@ employees:
|
|
351
383
|
<div class="terminal_caption">
|
352
384
|
validate</div>
|
353
385
|
<pre class="terminal">$ kwalify -f schema04.yaml document04b.yaml
|
354
|
-
document04b.yaml#
|
355
|
-
- [/employees/
|
356
|
-
- [/employees/
|
386
|
+
document04b.yaml#0: INVALID
|
387
|
+
- [/employees/0/code] 'A101': not a integer.
|
388
|
+
- [/employees/1] key 'mail:' is undefined.
|
357
389
|
</pre>
|
358
390
|
<br>
|
359
391
|
|
@@ -364,7 +396,7 @@ document04b.yaml#1: INVALID
|
|
364
396
|
<dt class="dt3"><strong>
|
365
397
|
<code>required:</code> </strong></dt>
|
366
398
|
<dd class="dd3">
|
367
|
-
Value is required (default is false).
|
399
|
+
Value is required when true (default is false).
|
368
400
|
</dd>
|
369
401
|
<dt class="dt3"><strong>
|
370
402
|
<code>enum:</code> </strong></dt>
|
@@ -391,30 +423,50 @@ document04b.yaml#1: INVALID
|
|
391
423
|
<dd class="dd3">
|
392
424
|
Type of value. The followings are available:
|
393
425
|
<ul type="circle">
|
394
|
-
<li><code>
|
426
|
+
<li><code>str</code>
|
395
427
|
</li>
|
396
|
-
<li><code>
|
428
|
+
<li><code>int</code>
|
397
429
|
</li>
|
398
430
|
<li><code>float</code>
|
399
431
|
</li>
|
400
|
-
<li><code>number</code> (==
|
432
|
+
<li><code>number</code> (== int or float)
|
401
433
|
</li>
|
402
|
-
<li><code>text</code> (==
|
434
|
+
<li><code>text</code> (== str or number)
|
403
435
|
</li>
|
404
|
-
<li><code>
|
436
|
+
<li><code>bool</code>
|
405
437
|
</li>
|
406
438
|
<li><code>date</code>
|
407
439
|
</li>
|
408
440
|
<li><code>time</code>
|
409
441
|
</li>
|
442
|
+
<li><code>timestamp</code>
|
443
|
+
</li>
|
410
444
|
<li><code>seq</code>
|
411
445
|
</li>
|
412
446
|
<li><code>map</code>
|
413
447
|
</li>
|
414
|
-
<li><code>
|
448
|
+
<li><code>scalar</code> (all but seq and map)
|
449
|
+
</li>
|
450
|
+
<li><code>any</code> (means any data)
|
415
451
|
</li>
|
416
452
|
</ul>
|
417
453
|
</dd>
|
454
|
+
<dt class="dt3"><strong>
|
455
|
+
<code>range:</code> </strong></dt>
|
456
|
+
<dd class="dd3">
|
457
|
+
Range of value between max and min. Type <code>seq</code>, <code>map</code>, <code>bool</code> and <code>any</code> are not available with <code>range:</code>.
|
458
|
+
</dd>
|
459
|
+
<dt class="dt3"><strong>
|
460
|
+
<code>length:</code> </strong></dt>
|
461
|
+
<dd class="dd3">
|
462
|
+
Range of length of value between max and min. Only type <code>str</code> and <code>text</code> are available with <code>length:</code>.
|
463
|
+
</dd>
|
464
|
+
<dt class="dt3"><strong>
|
465
|
+
<code>assert:</code> </strong></dt>
|
466
|
+
<dd class="dd3">
|
467
|
+
String which represents validation expression. String should contain variable name <code>val</code> which repsents value.
|
468
|
+
(This is an experimental function.)
|
469
|
+
</dd>
|
418
470
|
</dl>
|
419
471
|
<a name="schema05.yaml"></a>
|
420
472
|
<div class="program_caption">
|
@@ -424,16 +476,21 @@ sequence:
|
|
424
476
|
- type: map
|
425
477
|
mapping:
|
426
478
|
name:
|
427
|
-
|
479
|
+
type: str
|
428
480
|
required: yes
|
429
481
|
email:
|
430
|
-
|
482
|
+
type: str
|
431
483
|
required: yes
|
432
484
|
pattern: /@/
|
485
|
+
password:
|
486
|
+
type: str
|
487
|
+
length: { max: 16, min: 8 }
|
433
488
|
age:
|
434
|
-
type:
|
489
|
+
type: int
|
490
|
+
range: { max: 30, min: 18 }
|
491
|
+
# or assert: 30 <= val && val <= 18
|
435
492
|
blood:
|
436
|
-
|
493
|
+
type: str
|
437
494
|
enum:
|
438
495
|
- A
|
439
496
|
- B
|
@@ -441,92 +498,127 @@ sequence:
|
|
441
498
|
- AB
|
442
499
|
birth:
|
443
500
|
type: date
|
501
|
+
memo:
|
502
|
+
type: any
|
444
503
|
</pre>
|
445
504
|
<a name="document05a.yaml"></a>
|
446
505
|
<div class="program_caption">
|
447
506
|
<code>document05a.yaml</code> : valid document example</div>
|
448
|
-
<pre class="program">- name:
|
449
|
-
email:
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
507
|
+
<pre class="program">- name: foo
|
508
|
+
email: foo@mail.com
|
509
|
+
password: xxx123456
|
510
|
+
age: 20
|
511
|
+
blood: A
|
512
|
+
birth: 1985-01-01
|
513
|
+
- name: bar
|
514
|
+
email: bar@mail.net
|
515
|
+
age: 25
|
516
|
+
blood: AB
|
517
|
+
birth: 1980-01-01
|
458
518
|
</pre>
|
459
519
|
<div class="terminal_caption">
|
460
520
|
validate</div>
|
461
521
|
<pre class="terminal">$ kwalify -f schema05.yaml document05a.yaml
|
462
|
-
document05a.yaml#
|
522
|
+
document05a.yaml#0: valid.
|
463
523
|
</pre>
|
464
524
|
<a name="document05b.yaml"></a>
|
465
525
|
<div class="program_caption">
|
466
526
|
<code>document05b.yaml</code> : invalid document example</div>
|
467
|
-
<pre class="program">- name:
|
468
|
-
email:
|
469
|
-
|
470
|
-
|
471
|
-
|
527
|
+
<pre class="program">- name: foo
|
528
|
+
email: foo(at)mail.com
|
529
|
+
password: xxx123
|
530
|
+
age: twenty
|
531
|
+
blood: a
|
532
|
+
birth: 1985-01-01
|
472
533
|
- given-name: bar
|
473
534
|
family-name: Bar
|
474
|
-
email:
|
475
|
-
age:
|
476
|
-
blood:
|
477
|
-
birth:
|
535
|
+
email: bar@mail.net
|
536
|
+
age: 15
|
537
|
+
blood: AB
|
538
|
+
birth: 1980/01/01
|
478
539
|
</pre>
|
479
540
|
<div class="terminal_caption">
|
480
541
|
validate</div>
|
481
542
|
<pre class="terminal">$ kwalify -f schema05.yaml document05b.yaml
|
482
|
-
document05b.yaml#
|
483
|
-
- [/
|
484
|
-
- [/
|
485
|
-
- [/
|
486
|
-
- [/
|
487
|
-
- [/
|
488
|
-
- [/
|
489
|
-
- [/
|
543
|
+
document05b.yaml#0: INVALID
|
544
|
+
- [/0/blood] 'a': invalid blood value.
|
545
|
+
- [/0/age] 'twenty': not a integer.
|
546
|
+
- [/0/password] 'xxx123': too short (length 6 < min 8).
|
547
|
+
- [/0/email] 'foo(at)mail.com': not matched to pattern /@/.
|
548
|
+
- [/1] key 'name:' is required.
|
549
|
+
- [/1] key 'family-name:' is undefined.
|
550
|
+
- [/1] key 'given-name:' is undefined.
|
551
|
+
- [/1/birth] '1980/01/01': not a date.
|
552
|
+
- [/1/age] '15': too small (< min 18).
|
490
553
|
</pre>
|
491
554
|
<br>
|
492
555
|
|
493
556
|
|
494
|
-
<a name="schema-
|
495
|
-
<h3 class="section2">Validator
|
496
|
-
<p
|
497
|
-
|
498
|
-
<p><code>Kwalify::Validator.new()</code> method can take a block which is invoked when validation.
|
557
|
+
<a name="schema-hook"></a>
|
558
|
+
<h3 class="section2">Validator#validator_hook()</h3>
|
559
|
+
<p>You can extend Kwalify::Validator class and override Kwalify::Validator#validator_hook() method.
|
560
|
+
This method is called by Kwalify::Validator#validate().
|
499
561
|
</p>
|
562
|
+
<a name="schema06.yaml"></a>
|
563
|
+
<div class="program_caption">
|
564
|
+
schema06.yaml : 'name:' is important.</div>
|
565
|
+
<pre class="program">type: map
|
566
|
+
mapping:
|
567
|
+
questionnaires:
|
568
|
+
type: seq
|
569
|
+
sequence:
|
570
|
+
- type: map
|
571
|
+
<strong>name: Questionnaire</strong>
|
572
|
+
mapping:
|
573
|
+
name:
|
574
|
+
type: str
|
575
|
+
required: yes
|
576
|
+
answer:
|
577
|
+
type: str
|
578
|
+
required: yes
|
579
|
+
enum:
|
580
|
+
- good
|
581
|
+
- not bad
|
582
|
+
- bad
|
583
|
+
reason:
|
584
|
+
type: str
|
585
|
+
</pre>
|
500
586
|
<a name="validate06.rb"></a>
|
501
587
|
<div class="program_caption">
|
502
|
-
|
588
|
+
validate06.rb : validate script</div>
|
503
589
|
<pre class="program">#!/usr/bin/env ruby
|
504
590
|
|
505
591
|
require 'kwalify'
|
506
592
|
require 'yaml'
|
507
593
|
|
508
|
-
##
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
594
|
+
## validator class for questionnaires
|
595
|
+
class QuestionnairesValidator < Kwalify::Validator
|
596
|
+
|
597
|
+
## load schema definition
|
598
|
+
@@schema = YAML.load_file('schema06.yaml')
|
599
|
+
|
600
|
+
def initialize()
|
601
|
+
super(@@schema)
|
602
|
+
end
|
603
|
+
|
604
|
+
## hook method called by Validator#validate()
|
605
|
+
<strong>def validate_hook(value, rule, path, errors)</strong>
|
606
|
+
<strong>case rule.name</strong>
|
607
|
+
<strong>when 'Questionnaire'</strong>
|
608
|
+
if value['answer'] == 'bad'
|
609
|
+
reason = value['reason']
|
610
|
+
if !reason || reason.empty?
|
611
|
+
msg = "reason is required when answer is 'bad'."
|
612
|
+
errors << Kwalify::ValidationError.new(msg, path)
|
613
|
+
end
|
614
|
+
end
|
527
615
|
end
|
528
616
|
end
|
529
|
-
|
617
|
+
|
618
|
+
end
|
619
|
+
|
620
|
+
## create validator
|
621
|
+
validator = QuestionnairesValidator.new
|
530
622
|
|
531
623
|
## load YAML document
|
532
624
|
input = ARGF.read()
|
@@ -540,40 +632,22 @@ else
|
|
540
632
|
puts "*** INVALID!"
|
541
633
|
errors.each do |error|
|
542
634
|
# error.class == Kwalify::ValidationError
|
543
|
-
puts " - #{error.message}"
|
635
|
+
puts " - [#{error.path}] : #{error.message}"
|
544
636
|
end
|
545
637
|
end
|
546
638
|
</pre>
|
547
|
-
<a name="schema06.yaml"></a>
|
548
|
-
<div class="program_caption">
|
549
|
-
<code>schema06.yaml</code> : 'name:' is important.</div>
|
550
|
-
<pre class="program">type: map
|
551
|
-
mapping:
|
552
|
-
members:
|
553
|
-
type: seq
|
554
|
-
sequence:
|
555
|
-
- type: map
|
556
|
-
mapping:
|
557
|
-
username:
|
558
|
-
required: yes
|
559
|
-
<strong>name:</strong> <strong>USERNAME</strong>
|
560
|
-
email:
|
561
|
-
required: yes
|
562
|
-
pattern: /@/
|
563
|
-
age:
|
564
|
-
type: integer
|
565
|
-
<strong>name:</strong> <strong>AGE</strong>
|
566
|
-
</pre>
|
567
639
|
<a name="document06a.yaml"></a>
|
568
640
|
<div class="program_caption">
|
569
641
|
<code>document06a.yaml</code> : valid document example</div>
|
570
|
-
<pre class="program">
|
571
|
-
-
|
572
|
-
|
573
|
-
|
574
|
-
-
|
575
|
-
|
576
|
-
|
642
|
+
<pre class="program">questionnaires:
|
643
|
+
- name: Foo
|
644
|
+
answer: good
|
645
|
+
reason: I like this style.
|
646
|
+
- name: Bar
|
647
|
+
answer: not bad
|
648
|
+
- name: Baz
|
649
|
+
answer: bad
|
650
|
+
reason: I don't like this style.
|
577
651
|
</pre>
|
578
652
|
<div class="terminal_caption">
|
579
653
|
validate</div>
|
@@ -583,20 +657,80 @@ Valid.
|
|
583
657
|
<a name="document06b.yaml"></a>
|
584
658
|
<div class="program_caption">
|
585
659
|
<code>document06b.yaml</code> : invalid document example</div>
|
586
|
-
<pre class="program">
|
587
|
-
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
660
|
+
<pre class="program">questionnaires:
|
661
|
+
- name: Foo
|
662
|
+
answer: good
|
663
|
+
- name: Bar
|
664
|
+
answer: bad
|
665
|
+
- name: Baz
|
666
|
+
answer: not bad
|
593
667
|
</pre>
|
594
668
|
<div class="terminal_caption">
|
595
669
|
validate</div>
|
596
670
|
<pre class="terminal">$ ruby validate06.rb document06b.yaml
|
597
671
|
*** INVALID!
|
598
|
-
- [/
|
599
|
-
|
672
|
+
- [/questionnaires/1] : reason is required when answer is 'bad'.
|
673
|
+
</pre>
|
674
|
+
<br>
|
675
|
+
|
676
|
+
|
677
|
+
<a name="schema-block"></a>
|
678
|
+
<h3 class="section2">Validator with Block</h3>
|
679
|
+
<p><strong>Notice: This is an experimental feature.</strong>
|
680
|
+
</p>
|
681
|
+
<p><code>Kwalify::Validator.new()</code> method can take a block which is invoked when validation.
|
682
|
+
</p>
|
683
|
+
<a name="validate07.rb"></a>
|
684
|
+
<div class="program_caption">
|
685
|
+
<code>validate07.rb</code> : validate script</div>
|
686
|
+
<pre class="program">#!/usr/bin/env ruby
|
687
|
+
|
688
|
+
require 'kwalify'
|
689
|
+
require 'yaml'
|
690
|
+
|
691
|
+
## load schema definition
|
692
|
+
schema = YAML.load_file('schema06.yaml')
|
693
|
+
|
694
|
+
## create validator for questionnaires
|
695
|
+
validator = Kwalify::Validator.new(schema) <strong>{ |value, rule, path, errors|</strong>
|
696
|
+
<strong>case rule.name</strong>
|
697
|
+
<strong>when 'Questionnaire'</strong>
|
698
|
+
if value['answer'] == 'bad'
|
699
|
+
reason = value['reason']
|
700
|
+
if !reason || reason.empty?
|
701
|
+
msg = "reason is required when answer is 'bad'."
|
702
|
+
errors << Kwalify::ValidationError.new(msg, path)
|
703
|
+
end
|
704
|
+
end
|
705
|
+
end
|
706
|
+
<strong>}</strong>
|
707
|
+
|
708
|
+
## load YAML document
|
709
|
+
input = ARGF.read()
|
710
|
+
document = YAML.load(input)
|
711
|
+
|
712
|
+
## validate
|
713
|
+
errors = validator.validate(document)
|
714
|
+
if errors.empty?
|
715
|
+
puts "Valid."
|
716
|
+
else
|
717
|
+
puts "*** INVALID!"
|
718
|
+
errors.each do |error|
|
719
|
+
# error.class == Kwalify::ValidationError
|
720
|
+
puts " - [#{error.path}] : #{error.message}"
|
721
|
+
end
|
722
|
+
end
|
723
|
+
</pre>
|
724
|
+
<div class="terminal_caption">
|
725
|
+
validate</div>
|
726
|
+
<pre class="terminal">$ ruby validate07.rb document06a.yaml
|
727
|
+
Valid.
|
728
|
+
</pre>
|
729
|
+
<div class="terminal_caption">
|
730
|
+
validate</div>
|
731
|
+
<pre class="terminal">$ ruby validate07.rb document06b.yaml
|
732
|
+
*** INVALID!
|
733
|
+
- [/questionnaires/1] : reason is required when answer is 'bad'.
|
600
734
|
</pre>
|
601
735
|
<br>
|
602
736
|
|
@@ -620,7 +754,7 @@ mapping:
|
|
620
754
|
"email":
|
621
755
|
pattern: /@/
|
622
756
|
"age":
|
623
|
-
type:
|
757
|
+
type: int
|
624
758
|
"birth":
|
625
759
|
type: date
|
626
760
|
</pre>
|
@@ -635,7 +769,7 @@ mapping:
|
|
635
769
|
"email":
|
636
770
|
pattern: /@/
|
637
771
|
"age":
|
638
|
-
type:
|
772
|
+
type: int
|
639
773
|
"birth":
|
640
774
|
type: date
|
641
775
|
</pre>
|
@@ -655,7 +789,7 @@ sequence:
|
|
655
789
|
type: map
|
656
790
|
mapping:
|
657
791
|
"given-name": <strong>&name</strong>
|
658
|
-
type:
|
792
|
+
type: str
|
659
793
|
required: yes
|
660
794
|
"family-name": <strong>*name</strong>
|
661
795
|
"post":
|
@@ -691,7 +825,7 @@ sequence:
|
|
691
825
|
<div class="terminal_caption">
|
692
826
|
validate</div>
|
693
827
|
<pre class="terminal">$ kwalify -f schema12.yaml document12a.yaml
|
694
|
-
document12a.yaml#
|
828
|
+
document12a.yaml#0: valid.
|
695
829
|
</pre>
|
696
830
|
<br>
|
697
831
|
|