kwalify 0.1.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.
@@ -0,0 +1,4 @@
1
+
2
+ all:
3
+ kwalify -f address-book.schema.yaml address-book.yaml
4
+
@@ -0,0 +1,43 @@
1
+ ##
2
+ ## Kwalify schema example for address book
3
+ ##
4
+ ## $Release: 0.1.0 $
5
+ ## copyright(c) 2005 kuwata-lab all rights reserved.
6
+ ##
7
+ ##
8
+ ## NOTE: 'type: string' is omitted in this example because 'string' is default type.
9
+ ##
10
+
11
+ type: seq
12
+ required: yes
13
+ sequence:
14
+ - type: map
15
+ required: yes
16
+ mapping:
17
+ "name":
18
+ #type: string
19
+ required: yes
20
+ "email":
21
+ #type: string
22
+ pattern: /@/
23
+ "tel":
24
+ #type: string
25
+ pattern: /^\d+-\d+-\d+$/
26
+ "birth":
27
+ type: date
28
+ "age":
29
+ type: integer
30
+ "zip":
31
+ #type: string
32
+ pattern: /^\d+-\d+$/
33
+ "addr":
34
+ #type: string
35
+ "blood":
36
+ #type: string
37
+ enum:
38
+ - A
39
+ - B
40
+ - O
41
+ - AB
42
+ "memo":
43
+ type: object
@@ -0,0 +1,36 @@
1
+ ##
2
+ ## address book example
3
+ ##
4
+
5
+ - name: Sumire
6
+ email: amethyst@mail.com
7
+ tel: 012-111-1111
8
+ birth: 1985-01-01
9
+ age: 20
10
+ zip: 123-4567
11
+ addr: xxxx xxxx xxxx
12
+ blood: B
13
+ memo: My friend
14
+
15
+ - name: Kasumi
16
+ email: mist@mail.net
17
+ tel: 012-222-2222
18
+ birth: 1980-02-02
19
+ age: 25
20
+ blood: AB
21
+ memo:
22
+ - Home tutor
23
+ - A doctor (university)
24
+
25
+ - name: Nana
26
+ email: seven@mail.com
27
+ tel: 012-333-3333
28
+ birth: 1990-03-03
29
+ age: 15
30
+ blood: O
31
+ memo: My sister
32
+
33
+ - name: Sizuka
34
+ email: quiet@mail.org
35
+ memo: Firend of Sumire
36
+
@@ -0,0 +1,3 @@
1
+ all:
2
+ kwalify -f invoice.schema.yaml invoice.yaml
3
+
@@ -0,0 +1,59 @@
1
+ ###
2
+ ### Kwalify schema example for invoice
3
+ ###
4
+ ### $Rev$
5
+ ### $Release: 0.1.0 $
6
+ ### copyright(c) 2005 kuwata-lab all rights reserved.
7
+ ###
8
+
9
+ type: map
10
+ required: yes
11
+ mapping:
12
+ "invoice":
13
+ type: integer
14
+ required: yes
15
+ "date":
16
+ type: date
17
+ required: yes
18
+ "bill-to": &customer
19
+ type: map
20
+ required: yes
21
+ mapping:
22
+ "given":
23
+ required: yes
24
+ "family":
25
+ required: yes
26
+ "address":
27
+ type: map
28
+ required: yes
29
+ mapping:
30
+ "lines":
31
+ "city":
32
+ "state":
33
+ "postal":
34
+ type: integer
35
+ "ship-to": *customer
36
+ "product":
37
+ type: seq
38
+ required: yes
39
+ sequence:
40
+ - type: map
41
+ required: yes
42
+ mapping:
43
+ "sku":
44
+ required: yes
45
+ pattern: /^[A-Z0-9]+$/
46
+ "quantity":
47
+ type: integer
48
+ required: yes
49
+ "description":
50
+ "price":
51
+ type: float
52
+ "tax":
53
+ type: float
54
+ "total":
55
+ type: float
56
+ required: yes
57
+ "comments":
58
+ type: text
59
+
@@ -0,0 +1,32 @@
1
+ ##
2
+ ## from http://www.yaml.org/start.html
3
+ ##
4
+ --- !clarkevans.com/^invoice
5
+ invoice: 34843
6
+ date : 2001-01-23
7
+ bill-to: &id001
8
+ given : Chris
9
+ family : Dumars
10
+ address:
11
+ lines: |
12
+ 458 Walkman Dr.
13
+ Suite #292
14
+ city : Royal Oak
15
+ state : MI
16
+ postal : 48046
17
+ ship-to: *id001
18
+ product:
19
+ - sku : BL394D
20
+ quantity : 4
21
+ description : Basketball
22
+ price : 450.00
23
+ - sku : BL4438H
24
+ quantity : 1
25
+ description : Super Hoop
26
+ price : 2392.00
27
+ tax : 251.42
28
+ total: 4443.52
29
+ comments: >
30
+ Late afternoon is best.
31
+ Backup contact is Nancy
32
+ Billsmer @ 338-4338.
@@ -0,0 +1,10 @@
1
+ ###
2
+ ### $Rev: 5 $
3
+ ### $Release: 0.1.0 $
4
+ ### copyright(c) 2005 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ require 'kwalify/types'
8
+ require 'kwalify/error-msg'
9
+ require 'kwalify/errors'
10
+ require 'kwalify/validator'
@@ -0,0 +1,41 @@
1
+ ###
2
+ ### $Rev: 8 $
3
+ ### $Release: 0.1.0 $
4
+ ### copyright(c) 2005 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ module Kwalify
8
+
9
+ ERROR_MESSAGES = {}
10
+
11
+ ## validation error
12
+ ERROR_MESSAGES[:missing_value] = "value required but not found."
13
+ ERROR_MESSAGES[:invalid_type] = "%s type expected but got %s."
14
+ ERROR_MESSAGES[:invalid_enum] = "'%s' is invalid enum value."
15
+ ERROR_MESSAGES[:invalid_pattern] = "'%s' is not matched to pattern %s."
16
+ ERROR_MESSAGES[:missing_key] = "key '%s' required but not found."
17
+ ERROR_MESSAGES[:invalid_key] = "key '%s' is not expected."
18
+
19
+ ## ruleset error
20
+ ERROR_MESSAGES[:ruleset_not_hash] = "ruleset is not a hash."
21
+ ERROR_MESSAGES[:type_not_found] = "type '%s' is not found."
22
+ ERROR_MESSAGES[:required_not_boolean] = "'required:' is not 'true' nor 'false'."
23
+ ERROR_MESSAGES[:regexp_error] = "'pattern:' has regexp error (= %s)."
24
+ ERROR_MESSAGES[:enum_not_seq] = "'enum:' is not a sequence."
25
+ ERROR_MESSAGES[:sequence_not_seq] = "'sequence:' should be a sequence."
26
+ ERROR_MESSAGES[:sequence_no_elem] = "'sequence:' requires one element."
27
+ ERROR_MESSAGES[:sequence_too_many] = "'sequence:' requires just one element."
28
+ ERROR_MESSAGES[:mapping_not_map] = "'mapping:' should be a mapping."
29
+ ERROR_MESSAGES[:mapping_no_elem] = "'mapping:' requires at least one element."
30
+ ERROR_MESSAGES[:duplicate_key] = "key '%s' is duplicated."
31
+ ERROR_MESSAGES[:unexpected_key] = "'%s' is not expected."
32
+ ERROR_MESSAGES[:seq_has_enum] = "'enum:' is not available with sequence type."
33
+ ERROR_MESSAGES[:seq_has_pattern] = "'pattern:' is not available with sequence type."
34
+ ERROR_MESSAGES[:seq_has_mapping] = "'mapping:' is not available with sequence type."
35
+ ERROR_MESSAGES[:map_has_enum] = "'enum:' is not available with mapping type."
36
+ ERROR_MESSAGES[:map_has_pattern] = "'pattern:' is not available with mapping type."
37
+ ERROR_MESSAGES[:map_has_sequence] = "'sequence:' is not available with mapping type."
38
+ ERROR_MESSAGES[:scalar_has_sequence] = "scalar cannot take 'sequence:'."
39
+ ERROR_MESSAGES[:scalar_has_mapping] = "scalar cannot take 'mapping:'."
40
+
41
+ end
@@ -0,0 +1,112 @@
1
+ ###
2
+ ### $Rev: 8 $
3
+ ### $Release: 0.1.0 $
4
+ ### copyright(c) 2005 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ module Kwalify
8
+
9
+ class KwalifyError < StandardError
10
+ end
11
+
12
+
13
+ class AssertionError < KwalifyError
14
+ def initialize(msg)
15
+ super("*** assertion error: " + msg)
16
+ end
17
+ end
18
+
19
+
20
+ class BaseError < KwalifyError
21
+ def initialize(message="", path=nil, schema=nil, error_symbol=nil)
22
+ super(message)
23
+ @error_symbol = error_symbol
24
+ @schema = schema
25
+ @path = path
26
+ end
27
+ attr_reader :error_symbol, :schema, :path
28
+
29
+ def to_s
30
+ return super() if @path == nil
31
+ return "[/] #{super()}" if @path.empty?
32
+ return "[#{@path}] #{super()}"
33
+ end
34
+ end
35
+
36
+
37
+ class SchemaError < BaseError
38
+ def initialize(message="", path=nil, schema=nil, error_symbol=nil)
39
+ super(message, path, schema, error_symbol)
40
+ end
41
+ end
42
+
43
+
44
+ class ValidationError < BaseError
45
+ def initialize(message="", path=nil, schema=nil, error_symbol=nil, data=nil)
46
+ super(message, path, schema, error_symbol)
47
+ @data = data
48
+ end
49
+ attr_reader :data
50
+ end
51
+
52
+
53
+ module Errors
54
+
55
+ def assert_error(message="")
56
+ raise AssertionError.new(message)
57
+ end
58
+
59
+
60
+ def error_message(error_symbol, schema, data, arg)
61
+ msg = nil
62
+ case error_symbol
63
+
64
+ ## validation error
65
+ when :missing_value
66
+ msg = ERROR_MESSAGES[error_symbol]
67
+ when :invalid_type
68
+ msg = ERROR_MESSAGES[error_symbol] % [ schema.type, data.class.name ]
69
+ when :invalid_enum
70
+ msg = ERROR_MESSAGES[error_symbol] % [ data.to_s ]
71
+ when :invalid_pattern
72
+ msg = ERROR_MESSAGES[error_symbol] % [ data.to_s, schema.pattern.inspect ]
73
+ when :missing_key
74
+ msg = ERROR_MESSAGES[error_symbol] % [ arg ] # arg is keyname
75
+ when :invalid_key
76
+ msg = ERROR_MESSAGES[error_symbol] % [ arg ] # arg is keyname
77
+
78
+ ## schema error
79
+ when :unexpected_key
80
+ msg = ERROR_MESSAGES[error_symbol] % [ arg ] # arg is keyname
81
+ when :duplicate_key
82
+ msg = ERROR_MESSAGES[error_symbol] % [ arg ] # arg is keyname
83
+ when :type_not_found
84
+ msg = ERROR_MESSAGES[error_symbol] % [ arg ] # arg is typename
85
+ when :regexp_error
86
+ msg = ERROR_MESSAGES[error_symbol] % [ data ]
87
+ else
88
+ msg = ERROR_MESSAGES[error_symbol]
89
+ end
90
+
91
+ ##
92
+ return msg
93
+ end
94
+
95
+
96
+ def validate_error(error_symbol, schema, path, data, arg=nil)
97
+ msg = error_message(error_symbol, schema, data, arg)
98
+ return ValidationError.new(msg, path, schema, error_symbol, data)
99
+ end
100
+
101
+
102
+ def schema_error(error_symbol, schema, path, arg=nil)
103
+ msg = error_message(error_symbol, schema, nil, arg)
104
+ return SchemaError.new(msg, path, schema, error_symbol)
105
+ end
106
+
107
+
108
+ module_function :assert_error, :validate_error, :schema_error, :error_message
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,137 @@
1
+ ###
2
+ ### $Rev: 9 $
3
+ ### $Release: 0.1.0 $
4
+ ### copyright(c) 2005 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ require 'kwalify/errors'
8
+ require 'kwalify/validator'
9
+ require 'yaml'
10
+
11
+ module Kwalify
12
+
13
+ META_SCHEMA_DEF = <<'END'
14
+
15
+ name: MAIN
16
+ type: map
17
+ required: yes
18
+ mapping: &main-schema
19
+ "name":
20
+ type: string
21
+ "desc":
22
+ type: text
23
+ "type":
24
+ type: string
25
+ enum:
26
+ - seq
27
+ - sequence
28
+ #- list
29
+ - map
30
+ - mapping
31
+ #- hash
32
+ - string
33
+ - integer
34
+ - float
35
+ - number
36
+ - numeric
37
+ - bool
38
+ - boolean
39
+ - text
40
+ - date
41
+ - time
42
+ - object
43
+ - any
44
+ "required":
45
+ type: boolean
46
+ "enum":
47
+ type: seq
48
+ sequence:
49
+ - type: object
50
+ "pattern":
51
+ type: string
52
+ "sequence":
53
+ name: SEQUENCE
54
+ type: seq
55
+ sequence:
56
+ - type: map
57
+ mapping: *main-schema
58
+ name: MAIN
59
+ "mapping":
60
+ name: MAPPING
61
+ type: map
62
+ mapping:
63
+ '*':
64
+ type: map
65
+ mapping: *main-schema
66
+ name: MAIN
67
+
68
+ END
69
+
70
+
71
+ def self.meta_validator()
72
+ yaml = YAML.load(META_SCHEMA_DEF)
73
+ validator = Kwalify::Validator.new(yaml)
74
+ return validator
75
+ end
76
+
77
+
78
+ def self.meta_validator2()
79
+ yaml = YAML.load(META_SCHEMA_DEF)
80
+ validator = Kwalify::Validator.new(yaml) { |schema, obj, errors, path|
81
+ next if obj == nil ## realy?
82
+ if schema.name == "MAIN"
83
+ hash = obj
84
+ if hash.key?('pattern')
85
+ val = hash['pattern']
86
+ pat = (val =~ /\A\/(.*)\/\z/ ? $1 : val)
87
+ begin
88
+ Regexp.compile(pat)
89
+ rescue RegexpError => ex
90
+ errors << Kwalify::Errors.validate_error(:regexp_error, schema, path, obj)
91
+ end
92
+ end
93
+ type = hash['type']
94
+ if type == nil
95
+ if hash.key?('sequence')
96
+ type = 'seq'
97
+ elsif hash.key?('mapping')
98
+ type = 'map'
99
+ else
100
+ type = Kwalify::DEFAULT_TYPE
101
+ end
102
+ end
103
+ klass = Kwalify.type_table[type]
104
+ if klass == nil
105
+ errors << Kwalify::Errors.validate_error(:invalid_type, schema, path, obj)
106
+ elsif klass == Array
107
+ errors << Kwalify::Errors.validate_error(:seq_has_enum, schema, path, obj) if hash.key?('enum')
108
+ errors << Kwalify::Errors.validate_error(:seq_has_pattern, schema, path, obj) if hash.key?('pattern')
109
+ errors << Kwalify::Errors.validate_error(:seq_has_mapping, schema, path, obj) if hash.key?('mapping')
110
+ elsif klass == Hash
111
+ errors << Kwalify::Errors.validate_error(:map_has_enum, schema, path, obj) if hash.key?('enum')
112
+ errors << Kwalify::Errors.validate_error(:map_has_pattern, schema, path, obj) if hash.key?('pattern')
113
+ errors << Kwalify::Errors.validate_error(:map_has_sequence, schema, path, obj) if hash.key?('sequence')
114
+ else
115
+ errors << Kwalify::Errors.validate_error(:scalar_has_sequence, schema, path, obj) if hash.key?('sequence')
116
+ errors << Kwalify::Errors.validate_error(:scalar_has_mapping, schema, path, obj) if hash.key?('mapping')
117
+ end
118
+ elsif schema.name == "SEQUENCE"
119
+ if !obj.is_a?(Array)
120
+ errors << Kwalify::Errors.validate_error(:sequence_not_seq, schema, path, obj)
121
+ else
122
+ errors << Kwalify::Errors.validate_error(:sequence_no_elem, schema, path, obj) if obj.empty?
123
+ errors << Kwalify::Errors.validate_error(:sequence_too_many, schema, path, obj) if obj.length > 1
124
+ end
125
+ elsif schema.name == "MAPPING"
126
+ if !obj.is_a?(Hash)
127
+ errors << Kwalify::Errors.validate_error(:mapping_not_map, schema, path, obj)
128
+ else
129
+ errors << Kwalify::Errors.validate_error(:mapping_no_elem, schema, path, obj) if obj.empty?
130
+ end
131
+ end
132
+ }
133
+ return validator
134
+ end
135
+
136
+ end
137
+