kwalify 0.4.1 → 0.5.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 +14 -3
- data/README.txt +3 -3
- data/bin/kwalify +4 -15
- data/doc/users-guide.html +237 -61
- data/examples/address-book/address-book.schema.yaml +1 -1
- data/examples/invoice/invoice.schema.yaml +2 -2
- data/examples/tapkit/tapkit.schema.yaml +39 -39
- data/lib/kwalify.rb +4 -4
- data/lib/kwalify/errors.rb +21 -14
- data/lib/kwalify/main.rb +357 -0
- data/lib/kwalify/messages.rb +38 -9
- data/lib/kwalify/meta-validator.rb +96 -64
- data/lib/kwalify/rule.rb +356 -269
- data/lib/kwalify/types.rb +53 -35
- data/lib/kwalify/util/assert-diff.rb +2 -2
- data/lib/kwalify/util/option-parser.rb +2 -2
- data/lib/kwalify/util/yaml-helper.rb +2 -2
- data/lib/kwalify/validator.rb +8 -17
- data/lib/kwalify/{parser.rb → yaml-parser.rb} +70 -41
- data/test/test-main.rb +179 -0
- data/test/test-main.yaml +756 -0
- data/test/test-metavalidator.rb +38 -721
- data/test/test-metavalidator.yaml +1104 -0
- data/test/test-rule.rb +60 -0
- data/test/test-rule.yaml +314 -0
- data/test/test-validator.rb +5 -5
- data/test/test-validator.yaml +816 -0
- data/test/{test-parser.rb → test-yamlparser.rb} +17 -17
- data/test/test-yamlparser.yaml +1080 -0
- data/test/test.rb +5 -3
- data/todo.txt +1 -0
- metadata +16 -11
- data/lib/kwalify/main-program.rb +0 -258
data/lib/kwalify/types.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
###
|
2
|
-
### $Rev:
|
3
|
-
### $Release: 0.
|
2
|
+
### $Rev: 42 $
|
3
|
+
### $Release: 0.5.0 $
|
4
4
|
### copyright(c) 2005 kuwata-lab all rights reserved.
|
5
5
|
###
|
6
6
|
|
@@ -79,41 +79,49 @@ end
|
|
79
79
|
|
80
80
|
module Kwalify
|
81
81
|
|
82
|
-
DEFAULT_TYPE = "str" ## use "str" as default of @type
|
83
|
-
|
84
|
-
@@type_table = {
|
85
|
-
"seq" => Array,
|
86
|
-
"map" => Hash,
|
87
|
-
"str" => String,
|
88
|
-
#"string" => String,
|
89
|
-
"text" => Text,
|
90
|
-
"int" => Integer,
|
91
|
-
#"integer" => Integer,
|
92
|
-
"float" => Float,
|
93
|
-
"number" => Numeric,
|
94
|
-
#"numeric" => Numeric,
|
95
|
-
"date" => Date,
|
96
|
-
"time" => Time,
|
97
|
-
"timestamp" => Time,
|
98
|
-
"bool" => Boolean,
|
99
|
-
#"boolean" => Boolean,
|
100
|
-
#"object" => Object,
|
101
|
-
"any" => Object,
|
102
|
-
"scalar" => Scalar,
|
103
|
-
}
|
104
|
-
|
105
|
-
def self.type_table
|
106
|
-
return @@type_table
|
107
|
-
end
|
108
82
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
83
|
+
module Types
|
84
|
+
|
85
|
+
|
86
|
+
DEFAULT_TYPE = "str" ## use "str" as default of @type
|
87
|
+
|
88
|
+
@@type_table = {
|
89
|
+
"seq" => Array,
|
90
|
+
"map" => Hash,
|
91
|
+
"str" => String,
|
92
|
+
#"string" => String,
|
93
|
+
"text" => Text,
|
94
|
+
"int" => Integer,
|
95
|
+
#"integer" => Integer,
|
96
|
+
"float" => Float,
|
97
|
+
"number" => Numeric,
|
98
|
+
#"numeric" => Numeric,
|
99
|
+
"date" => Date,
|
100
|
+
"time" => Time,
|
101
|
+
"timestamp" => Time,
|
102
|
+
"bool" => Boolean,
|
103
|
+
#"boolean" => Boolean,
|
104
|
+
#"object" => Object,
|
105
|
+
"any" => Object,
|
106
|
+
"scalar" => Scalar,
|
107
|
+
}
|
108
|
+
|
109
|
+
def self.type_table
|
110
|
+
return @@type_table
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.type_class(type)
|
114
|
+
klass = @@type_table[type]
|
115
|
+
#assert_error('type=#{type.inspect}') unless klass
|
116
|
+
return klass
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.get_type_class(type)
|
120
|
+
return type_class(type)
|
121
|
+
end
|
122
|
+
|
114
123
|
|
115
124
|
|
116
|
-
module TypeHelper
|
117
125
|
#--
|
118
126
|
#def collection_class?(klass)
|
119
127
|
# return klass.is_a?(Array) || klass.is_a?(Hash)
|
@@ -130,8 +138,18 @@ module Kwalify
|
|
130
138
|
def scalar?(val)
|
131
139
|
return !val.is_a?(Array) && !val.is_a?(Hash) && val.class != Object
|
132
140
|
end
|
141
|
+
|
142
|
+
def collection_type?(type)
|
143
|
+
return type == 'seq' || type == 'map'
|
144
|
+
end
|
145
|
+
|
146
|
+
def scalar_type?(type)
|
147
|
+
return type != 'seq' && type != 'map' && type == 'any'
|
148
|
+
end
|
149
|
+
|
150
|
+
module_function 'collection?', 'scalar?', 'collection_type?', 'scalar_type?'
|
133
151
|
end
|
134
152
|
|
135
|
-
extend
|
153
|
+
extend Types
|
136
154
|
|
137
155
|
end
|
data/lib/kwalify/validator.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
###
|
2
|
-
### $Rev:
|
3
|
-
### $Release: 0.
|
2
|
+
### $Rev: 42 $
|
3
|
+
### $Release: 0.5.0 $
|
4
4
|
### copyright(c) 2005 kuwata-lab all rights reserved.
|
5
5
|
###
|
6
6
|
|
@@ -11,7 +11,6 @@ require 'kwalify/rule'
|
|
11
11
|
|
12
12
|
module Kwalify
|
13
13
|
|
14
|
-
|
15
14
|
##
|
16
15
|
## ex.
|
17
16
|
## schema = YAML.load_file('schema.yaml')
|
@@ -54,8 +53,8 @@ module Kwalify
|
|
54
53
|
|
55
54
|
|
56
55
|
def _validate(value, rule, path, errors, done)
|
57
|
-
if
|
58
|
-
return
|
56
|
+
if Types.collection?(value)
|
57
|
+
return if done[value.__id__] # avoid infinite loop
|
59
58
|
done[value.__id__] = true
|
60
59
|
end
|
61
60
|
if rule.required && value == nil
|
@@ -63,7 +62,7 @@ module Kwalify
|
|
63
62
|
errors << validate_error(:required_novalue, rule, path, value)
|
64
63
|
return
|
65
64
|
end
|
66
|
-
if rule.
|
65
|
+
if rule.type_class && value != nil && !value.is_a?(rule.type_class)
|
67
66
|
#* key=:type_unmatch msg="not a %s."
|
68
67
|
errors << validate_error(:type_unmatch, rule, path, value, [Kwalify.word(rule.type)])
|
69
68
|
return
|
@@ -108,13 +107,13 @@ module Kwalify
|
|
108
107
|
return if value == nil
|
109
108
|
#
|
110
109
|
if rule.pattern
|
111
|
-
unless value.to_s =~ rule.
|
110
|
+
unless value.to_s =~ rule.regexp
|
112
111
|
#* key=:pattern_unmatch msg="not matched to pattern %s."
|
113
|
-
errors << validate_error(:pattern_unmatch, rule, path, value, [rule.pattern
|
112
|
+
errors << validate_error(:pattern_unmatch, rule, path, value, [rule.pattern])
|
114
113
|
end
|
115
114
|
end
|
116
115
|
if rule.range
|
117
|
-
assert_error("value.class=#{value.class.name}") unless
|
116
|
+
assert_error("value.class=#{value.class.name}") unless Types.scalar?(value)
|
118
117
|
if rule.range['max'] && rule.range['max'] < value
|
119
118
|
#* key=:range_toolarge msg="too large (> max %s)."
|
120
119
|
errors << validate_error(:range_toolarge, rule, path, value, [rule.range['max'].to_s])
|
@@ -223,11 +222,3 @@ module Kwalify
|
|
223
222
|
end
|
224
223
|
|
225
224
|
end
|
226
|
-
|
227
|
-
if __FILE__ == $0
|
228
|
-
require 'kwalify/parser'
|
229
|
-
parser = Kwalify::Parser.new(File.read(ARGV.shift))
|
230
|
-
schema = parser.parse()
|
231
|
-
validator = Kwalify::Validator.new(schema)
|
232
|
-
YARGF.read()
|
233
|
-
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
###
|
2
|
-
### $Rev:
|
3
|
-
### $Release: 0.
|
2
|
+
### $Rev: 42 $
|
3
|
+
### $Release: 0.5.0 $
|
4
4
|
### copyright(c) 2005 kuwata-lab all rights reserved.
|
5
5
|
###
|
6
6
|
|
@@ -13,15 +13,14 @@ require 'date'
|
|
13
13
|
|
14
14
|
module Kwalify
|
15
15
|
|
16
|
-
|
17
16
|
##
|
18
17
|
## ex.
|
19
18
|
## str = ARGF.read()
|
20
|
-
## parser = Kwalify::
|
19
|
+
## parser = Kwalify::PlainYamlParser.new(str)
|
21
20
|
## doc = parser.parse()
|
22
21
|
## p doc
|
23
22
|
##
|
24
|
-
class
|
23
|
+
class PlainYamlParser
|
25
24
|
|
26
25
|
class Alias
|
27
26
|
def initialize(label, linenum)
|
@@ -51,6 +50,21 @@ module Kwalify
|
|
51
50
|
end
|
52
51
|
|
53
52
|
|
53
|
+
def has_next()
|
54
|
+
return @end_flag != 'EOF'
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def parse_all
|
59
|
+
list = []
|
60
|
+
while has_next()
|
61
|
+
doc = parse()
|
62
|
+
list << doc
|
63
|
+
end
|
64
|
+
return list
|
65
|
+
end
|
66
|
+
|
67
|
+
|
54
68
|
protected
|
55
69
|
|
56
70
|
|
@@ -159,11 +173,11 @@ module Kwalify
|
|
159
173
|
end
|
160
174
|
|
161
175
|
|
162
|
-
def syntax_error(
|
163
|
-
|
176
|
+
def syntax_error(error_symbol, linenum=@linenum)
|
177
|
+
msg = Kwalify.msg(error_symbol) % [linenum]
|
178
|
+
return Kwalify::YamlSyntaxError.new(msg, linenum,error_symbol)
|
164
179
|
end
|
165
180
|
|
166
|
-
|
167
181
|
def parse_child(column)
|
168
182
|
line = getline()
|
169
183
|
return create_scalar(nil) if !line
|
@@ -225,7 +239,8 @@ module Kwalify
|
|
225
239
|
assert ch == ?] || ch == ?}
|
226
240
|
ch = getchar_or_nl()
|
227
241
|
unless ch == ?\n || ch == ?# || ch == nil
|
228
|
-
|
242
|
+
#* key=:flow_hastail msg="flow style sequence is closed but got '%s'."
|
243
|
+
raise syntax_error(:flow_hastail, [ch.chr])
|
229
244
|
end
|
230
245
|
getline() if ch != nil
|
231
246
|
return data
|
@@ -235,7 +250,8 @@ module Kwalify
|
|
235
250
|
ch = current_char()
|
236
251
|
#ch = getchar()
|
237
252
|
if ch == nil
|
238
|
-
|
253
|
+
#* key=:flow_eof msg="found EOF when parsing flow style."
|
254
|
+
rase syntax_error(:flow_eof)
|
239
255
|
end
|
240
256
|
if ch == ?[
|
241
257
|
data = parse_flow_seq(depth)
|
@@ -258,7 +274,8 @@ module Kwalify
|
|
258
274
|
while (ch = current_char()) == ?,
|
259
275
|
ch = getchar()
|
260
276
|
if ch == ?]
|
261
|
-
|
277
|
+
#* key=:flow_noseqitem msg="sequence item required (or last comma is extra)."
|
278
|
+
raise syntax_error(:flow_noseqitem)
|
262
279
|
end
|
263
280
|
#break if ch == ?]
|
264
281
|
linenum = current_linenum()
|
@@ -267,7 +284,8 @@ module Kwalify
|
|
267
284
|
end
|
268
285
|
end
|
269
286
|
unless current_char() == ?]
|
270
|
-
|
287
|
+
#* key=:flow_seqnotclosed msg="flow style sequence requires ']'."
|
288
|
+
raise syntax_error(:flow_seqnotclosed)
|
271
289
|
end
|
272
290
|
getchar() if depth > 0
|
273
291
|
return seq
|
@@ -289,7 +307,8 @@ module Kwalify
|
|
289
307
|
while (ch = current_char()) == ?,
|
290
308
|
ch = getchar()
|
291
309
|
if ch == ?}
|
292
|
-
|
310
|
+
#* key=:flow_mapnoitem msg="mapping item required (or last comma is extra)."
|
311
|
+
raise syntax_error(:flow_mapnoitem)
|
293
312
|
end
|
294
313
|
#break if ch == ?}
|
295
314
|
linenum = current_linenum()
|
@@ -299,7 +318,8 @@ module Kwalify
|
|
299
318
|
end
|
300
319
|
end
|
301
320
|
unless current_char() == ?}
|
302
|
-
|
321
|
+
#* key=:flow_mapnotclosed msg="flow style mapping requires '}'."
|
322
|
+
raise syntax_error(:flow_mapnotclosed)
|
303
323
|
end
|
304
324
|
getchar() if depth > 0
|
305
325
|
return map
|
@@ -309,7 +329,8 @@ module Kwalify
|
|
309
329
|
key = parse_flow(depth)
|
310
330
|
unless (ch = current_char()) == ?:
|
311
331
|
s = ch ? "'#{ch.chr}'" : "EOF"
|
312
|
-
|
332
|
+
#* key=:flow_nocolon msg="':' expected but got '%s'."
|
333
|
+
raise syntax_error(:flow_nocolon)
|
313
334
|
end
|
314
335
|
getchar()
|
315
336
|
value = parse_flow(depth)
|
@@ -374,7 +395,8 @@ module Kwalify
|
|
374
395
|
|
375
396
|
def register_anchor(label, data)
|
376
397
|
if @anchors[label]
|
377
|
-
|
398
|
+
#* key=:anchor_duplicated msg="anchor '%s' is already used."
|
399
|
+
raise syntax_error(:anchor_duplicated, [label])
|
378
400
|
end
|
379
401
|
@anchors[label] = data
|
380
402
|
end
|
@@ -385,7 +407,8 @@ module Kwalify
|
|
385
407
|
space = $3
|
386
408
|
value2 = $4
|
387
409
|
if value2 && !value2.empty? && value2[0] != ?\#
|
388
|
-
|
410
|
+
#* key=:alias_extradata msg="alias cannot take any data."
|
411
|
+
raise syntax_error(:alias_extradata)
|
389
412
|
end
|
390
413
|
data = @anchors[label]
|
391
414
|
unless data
|
@@ -417,7 +440,8 @@ module Kwalify
|
|
417
440
|
#seq[i] = @anchors[anchor.label]
|
418
441
|
set_seq_at(seq, i, @anchors[anchor.label], anchor.linenum)
|
419
442
|
else
|
420
|
-
|
443
|
+
#* key=:anchor_notfound msg="anchor '%s' not found"
|
444
|
+
raise syntax_error(:anchor_notfound, [val.linenum])
|
421
445
|
end
|
422
446
|
elsif val.is_a?(Array) || val.is_a?(Hash)
|
423
447
|
resolve_aliases(val)
|
@@ -432,7 +456,8 @@ module Kwalify
|
|
432
456
|
#map[key] = @anchors[anchor.label]
|
433
457
|
set_map_with(map, key, @anchors[anchor.label], anchor.linenum)
|
434
458
|
else
|
435
|
-
|
459
|
+
## :anchor_notfound is already defined on above
|
460
|
+
raise syntax_error(:anchor_notfound, [val.linenum])
|
436
461
|
end
|
437
462
|
elsif val.is_a?(Array) || val.is_a?(Hash)
|
438
463
|
resolve_aliases(val)
|
@@ -488,7 +513,8 @@ module Kwalify
|
|
488
513
|
seq = create_sequence() # []
|
489
514
|
while true
|
490
515
|
unless value =~ /^-(( +)(.*))?$/
|
491
|
-
|
516
|
+
#* key=:sequence_noitem msg="sequence item is expected."
|
517
|
+
raise syntax_error(:sequence_noitem)
|
492
518
|
end
|
493
519
|
value2 = $3
|
494
520
|
space = $2
|
@@ -510,7 +536,8 @@ module Kwalify
|
|
510
536
|
if indent < column
|
511
537
|
break
|
512
538
|
elsif indent > column
|
513
|
-
|
539
|
+
#* key=:sequence_badindent msg="illegal indent of sequence."
|
540
|
+
raise syntax_error(:sequence_badindent)
|
514
541
|
end
|
515
542
|
value = $2
|
516
543
|
end
|
@@ -525,7 +552,8 @@ module Kwalify
|
|
525
552
|
while true
|
526
553
|
#unless value =~ /^(:?["']?[-.\w]+["']? *):(( +)(.*))?$/ #'
|
527
554
|
unless value =~ /^((?::?[-.\w]+|'.*?'|".*?"|=|<<) *):(( +)(.*))?$/
|
528
|
-
|
555
|
+
#* key=:mapping_noitem msg="mapping item is expected."
|
556
|
+
raise syntax_error(:mapping_noitem)
|
529
557
|
end
|
530
558
|
v = $1.strip
|
531
559
|
key = to_scalar(v)
|
@@ -555,7 +583,8 @@ module Kwalify
|
|
555
583
|
if indent < column
|
556
584
|
break
|
557
585
|
elsif indent > column
|
558
|
-
|
586
|
+
#* key=:mapping_badindent msg="illegal indent of mapping."
|
587
|
+
raise syntax_error(:mapping_badindent)
|
559
588
|
end
|
560
589
|
value = $2
|
561
590
|
end
|
@@ -621,9 +650,9 @@ module Kwalify
|
|
621
650
|
|
622
651
|
##
|
623
652
|
## ex.
|
624
|
-
## # load document with
|
653
|
+
## # load document with YamlParser
|
625
654
|
## str = ARGF.read()
|
626
|
-
## parser = Kwalify::
|
655
|
+
## parser = Kwalify::YamlParser.new(str)
|
627
656
|
## document = parser.parse()
|
628
657
|
##
|
629
658
|
## # validate document
|
@@ -633,13 +662,13 @@ module Kwalify
|
|
633
662
|
##
|
634
663
|
## # print validation result
|
635
664
|
## if errors && !errors.empty?
|
636
|
-
## parser.
|
637
|
-
## errors.sort
|
665
|
+
## parser.set_errors_linenum(errors)
|
666
|
+
## errors.sort.each do |error|
|
638
667
|
## print "line %d: path %s: %s" % [error.linenum, error.path, error.message]
|
639
668
|
## end
|
640
669
|
## end
|
641
670
|
##
|
642
|
-
class
|
671
|
+
class YamlParser < PlainYamlParser
|
643
672
|
|
644
673
|
def initialize(*args)
|
645
674
|
super
|
@@ -675,12 +704,17 @@ module Kwalify
|
|
675
704
|
return linenum
|
676
705
|
end
|
677
706
|
|
678
|
-
def
|
707
|
+
def set_errors_linenum(errors)
|
679
708
|
errors.each do |error|
|
680
709
|
error.linenum = path_linenum(error.path)
|
681
710
|
end
|
682
711
|
end
|
683
712
|
|
713
|
+
def set_error_linenums(errors)
|
714
|
+
$stderr.puts "*** Kwalify::YamlParser#set_error_linenums() is obsolete. You should use set_errors_linenum() instead."
|
715
|
+
set_errors_linenum(errors)
|
716
|
+
end
|
717
|
+
|
684
718
|
protected
|
685
719
|
|
686
720
|
def create_sequence(linenum=current_linenum())
|
@@ -742,18 +776,13 @@ module Kwalify
|
|
742
776
|
|
743
777
|
end
|
744
778
|
|
745
|
-
end
|
746
779
|
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
else
|
754
|
-
parser = Kwalify::Parser.new(ARGF.read())
|
780
|
+
## obsolete
|
781
|
+
class Parser < YamlParser
|
782
|
+
def initialize(yaml_str)
|
783
|
+
super(yaml_str)
|
784
|
+
$stderr.puts "*** class Kwalify::Parser is obsolete. Please use Kwalify::YamlParser instead."
|
785
|
+
end
|
755
786
|
end
|
756
|
-
|
757
|
-
pp doc
|
758
|
-
#y doc
|
787
|
+
|
759
788
|
end
|