kwalify 0.1.0 → 0.2.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.
- 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
|
|