typestrict 0.0.6 → 0.0.8
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/History.txt +13 -1
- data/Manifest.txt +2 -0
- data/README +0 -6
- data/lib/base.rb +149 -0
- data/lib/supertypes.rb +85 -0
- data/lib/typestrict.rb +9 -183
- metadata +6 -4
data/History.txt
CHANGED
@@ -1,5 +1,17 @@
|
|
1
|
+
=== 0.0.8 / 2010-08-08
|
2
|
+
* 1 major enhancement
|
3
|
+
|
4
|
+
* Updated manifest + version bump
|
5
|
+
|
6
|
+
=== 0.0.7 / 2010-08-08
|
7
|
+
* 2 major enhancements
|
8
|
+
|
9
|
+
* Revamped implementation and architecture
|
10
|
+
* Supertypes are now implemented using dynamic handlers + dynamic handlers
|
11
|
+
|
12
|
+
|
1
13
|
=== 0.0.5 / 2010-08-07
|
2
|
-
* 2 major
|
14
|
+
* 2 major enhancements
|
3
15
|
|
4
16
|
* Added :procedure supertype
|
5
17
|
* Added :character supertype
|
data/Manifest.txt
CHANGED
data/README
CHANGED
data/lib/base.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
module Strict
|
2
|
+
module Base
|
3
|
+
|
4
|
+
class StrictTypeError < Exception
|
5
|
+
attr :errors
|
6
|
+
def initialize(error_list)
|
7
|
+
enforce_primitive!(Array, error_list, "lib/typestrict")
|
8
|
+
error_list.each {|item| enforce_primitive!(String, item, "lib/typestrict")}
|
9
|
+
@errors = error_list
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
msg = "StrictTypeError#{@errors.size > 1 ? "s" : ""} caught:\n"
|
14
|
+
@errors.each do |e|
|
15
|
+
msg += "#{e}\n"
|
16
|
+
end
|
17
|
+
return msg
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@@errors = []
|
21
|
+
@@raise_exception = true
|
22
|
+
@@dynamic_handlers = {}
|
23
|
+
|
24
|
+
def setmode_raise!
|
25
|
+
@@errors = []
|
26
|
+
@@raise_exception = true
|
27
|
+
end
|
28
|
+
|
29
|
+
def setmode_catch!
|
30
|
+
@@errors = []
|
31
|
+
@@raise_exception = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def catch_error error
|
35
|
+
if @@raise_exception
|
36
|
+
t = StrictTypeError.new([error])
|
37
|
+
raise(t, t.inspect, caller)
|
38
|
+
else
|
39
|
+
@@errors << error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def raise_hell!
|
44
|
+
if @@errors.size > 0
|
45
|
+
t = StrictTypeError.new(@@errors)
|
46
|
+
setmode_raise!
|
47
|
+
raise(t, t.inspect, caller)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def register_supertype(supertype, handler, verbose=true)
|
52
|
+
enforce_primitive!(Symbol, supertype, "typestrict/register_supertype")
|
53
|
+
enforce_primitive!(Proc, handler, "typestrict/register_supertype")
|
54
|
+
|
55
|
+
@@dynamic_handlers[supertype] = handler
|
56
|
+
puts "registered a handler for supertype: #{supertype}" if verbose
|
57
|
+
end
|
58
|
+
|
59
|
+
def header(context, data)
|
60
|
+
"#{context}; #{data.class.inspect}::#{data.inspect}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def enforce_primitive!(type, data, context="Value")
|
64
|
+
catch_error "#{header(context, data)} must be of type #{type}" unless (data.is_a? type and type.is_a? Class)
|
65
|
+
return data
|
66
|
+
end
|
67
|
+
|
68
|
+
def enforce_strict_primitives!(types, data, context="Value")
|
69
|
+
enforce_primitive!(Array, types, 'lib/typestrict')
|
70
|
+
types.each {|type| enforce_primitive!(Object, type, 'lib/typestrict')}
|
71
|
+
types.each do |type|
|
72
|
+
enforce_primitive!(type, data, context)
|
73
|
+
end
|
74
|
+
return data
|
75
|
+
end
|
76
|
+
|
77
|
+
def enforce_weak_primitives!(types, data, context="Value")
|
78
|
+
enforce_primitive!(Array, types, 'lib/typestrict')
|
79
|
+
types.each {|type| enforce_primitive!(Object, type, 'lib/typestrict')}
|
80
|
+
|
81
|
+
raise_set_before = @@raise_exception
|
82
|
+
previous_errors = @@errors
|
83
|
+
setmode_catch!
|
84
|
+
|
85
|
+
match_found = false
|
86
|
+
types.each do |type|
|
87
|
+
begin
|
88
|
+
s = @@errors.size
|
89
|
+
enforce_primitive!(type, data, context)
|
90
|
+
match_found = true unless @@errors.size > s
|
91
|
+
rescue
|
92
|
+
next
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
@@errors = previous_errors
|
97
|
+
|
98
|
+
catch_error "#{header(context, data)} must be of one of the types of #{types.inspect}" unless match_found
|
99
|
+
|
100
|
+
if raise_set_before
|
101
|
+
raise_hell! unless match_found
|
102
|
+
setmode_raise!
|
103
|
+
end
|
104
|
+
|
105
|
+
return data
|
106
|
+
end
|
107
|
+
|
108
|
+
def enforce_non_nil!(obj, context="Value")
|
109
|
+
catch_error "#{context}: Object is nil!" if obj.nil?
|
110
|
+
return obj
|
111
|
+
end
|
112
|
+
|
113
|
+
def enforce!(supertype, data, context="Value")
|
114
|
+
enforce_non_nil!(data, context)
|
115
|
+
|
116
|
+
if supertype.is_a? Array #enumeration of values
|
117
|
+
catch_error "#{header(context, data)} should take on a value within #{supertype.inspect}" unless supertype.include? data
|
118
|
+
|
119
|
+
else
|
120
|
+
if supertype.is_a? Symbol #distinct supertype
|
121
|
+
if @@dynamic_handlers.has_key? supertype
|
122
|
+
@@dynamic_handlers[supertype].call(data, context)
|
123
|
+
else
|
124
|
+
catch_error "undefined symbol-supertype encountered: #{supertype.inspect}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
return data
|
129
|
+
end
|
130
|
+
|
131
|
+
def enforce_map!(matrix, map)
|
132
|
+
enforce_primitive!(Hash, matrix, "lib/typestrict")
|
133
|
+
enforce_primitive!(Hash, map, "lib/typestrict")
|
134
|
+
|
135
|
+
setmode_catch!
|
136
|
+
|
137
|
+
matrix.each do |param, type|
|
138
|
+
if map.has_key? param
|
139
|
+
enforce!(type, map[param], "map[#{param.inspect}]")
|
140
|
+
else
|
141
|
+
catch_error "map: missing required param: #{param.inspect}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
raise_hell!
|
145
|
+
setmode_raise!
|
146
|
+
return map
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/supertypes.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
module Strict
|
2
|
+
module SuperTypes
|
3
|
+
|
4
|
+
@@handlers = {}
|
5
|
+
@@called = false
|
6
|
+
|
7
|
+
def registered?(supertype)
|
8
|
+
enforce_primitive!(Symbol, supertype)
|
9
|
+
Strict::Base.has_key? supertype
|
10
|
+
end
|
11
|
+
|
12
|
+
def register_default_supertypes! #must be called from an env including Base
|
13
|
+
if @@called
|
14
|
+
return
|
15
|
+
else
|
16
|
+
@@called = true
|
17
|
+
end
|
18
|
+
|
19
|
+
@@handlers[:string] = proc do |data, context|
|
20
|
+
enforce_primitive!(String, data, context)
|
21
|
+
catch_error "#{header(context, data)} can't be empty string" unless (data.size > 0)
|
22
|
+
end
|
23
|
+
|
24
|
+
@@handlers[:natural_number] = proc do |data, context|
|
25
|
+
enforce_primitive!(Fixnum, data, context)
|
26
|
+
catch_error "#{header(context, data)} must be > 0" unless (data > 0)
|
27
|
+
end
|
28
|
+
|
29
|
+
@@handlers[:integer] = proc do |data, context|
|
30
|
+
enforce_primitive!(Fixnum, data, context)
|
31
|
+
end
|
32
|
+
|
33
|
+
@@handlers[:numeric] = proc do |data, context|
|
34
|
+
enforce_primitive!(Numeric, data, context)
|
35
|
+
end
|
36
|
+
|
37
|
+
@@handlers[:boolean] = proc do |data, context|
|
38
|
+
enforce_weak_primitives!([TrueClass, FalseClass], data, context)
|
39
|
+
end
|
40
|
+
|
41
|
+
@@handlers[:float] = proc do |data, context|
|
42
|
+
enforce_primitive!(Float, data, context)
|
43
|
+
end
|
44
|
+
|
45
|
+
@@handlers[:character] = proc do |data, context|
|
46
|
+
enforce!(:string, data, context)
|
47
|
+
catch_error "#{header(context, data)} must be a single character!" unless data.size == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
@@handlers[:procedure] = proc do |data, context|
|
51
|
+
enforce_primitive!(Proc, data, context)
|
52
|
+
end
|
53
|
+
|
54
|
+
@@handlers[:string_array] = proc do |data, context|
|
55
|
+
enforce_primitive!(Array, data, context)
|
56
|
+
data.each {|item| enforce_primitive!(String, item, context)}
|
57
|
+
end
|
58
|
+
|
59
|
+
@@handlers[:numeric_array] = proc do |data, context|
|
60
|
+
enforce_primitive!(Array, data, context)
|
61
|
+
data.each {|item| enforce_primitive!(Numeric, item, context)}
|
62
|
+
end
|
63
|
+
|
64
|
+
@@handlers[:float_array] = proc do |data, context|
|
65
|
+
enforce_primitive!(Array, data, context)
|
66
|
+
data.each {|item| enforce_primitive!(Float, item, context)}
|
67
|
+
end
|
68
|
+
|
69
|
+
@@handlers[ :integer_array] = proc do |data, context|
|
70
|
+
enforce_primitive!(Array, data, context)
|
71
|
+
data.each {|item| enforce_primitive!(Fixnum, item, context)}
|
72
|
+
end
|
73
|
+
|
74
|
+
@@handlers[:hex_color] = proc do |data, context|
|
75
|
+
enforce!(:string, data, context)
|
76
|
+
catch_error "#{header(context, data)} must be six characters long" unless (data.size == 6)
|
77
|
+
data.upcase.each_byte {|c| catch_error "#{header(context, data)} must contain only hexadecimal characters" unless ((48 <= c and c <= 57) or (65 <= c and c <= 70))}
|
78
|
+
end
|
79
|
+
|
80
|
+
@@handlers.each do |supertype, handler|
|
81
|
+
Base::register_supertype(supertype, handler, false) #verbose set to false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/typestrict.rb
CHANGED
@@ -1,185 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class TypeError < Exception
|
5
|
-
attr :errors
|
6
|
-
def initialize(error_list)
|
7
|
-
enforce!(:string_array, error_list, 'lib/typestrict')
|
8
|
-
@errors = error_list
|
9
|
-
end
|
10
|
-
|
11
|
-
def inspect
|
12
|
-
msg = "TypeError#{@errors.size > 1 ? "s" : ""} caught:\n"
|
13
|
-
@errors.each do |e|
|
14
|
-
msg += "#{e}\n"
|
15
|
-
end
|
16
|
-
return msg
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
@@errors = []
|
21
|
-
@@raise_exception = true
|
22
|
-
@@dynamic_handlers = {}
|
23
|
-
|
24
|
-
def setmode_raise!
|
25
|
-
@@errors = []
|
26
|
-
@@raise_exception = true
|
27
|
-
end
|
28
|
-
|
29
|
-
def setmode_catch!
|
30
|
-
@@errors = [] unless @@errors.is_a? Array
|
31
|
-
@@raise_exception = false
|
32
|
-
end
|
33
|
-
|
34
|
-
def catch_error error
|
35
|
-
@@errors << error
|
36
|
-
t = TypeError.new([error])
|
37
|
-
raise(t, t.inspect, caller) if @@raise_exception
|
38
|
-
end
|
39
|
-
|
40
|
-
def raise_hell!
|
41
|
-
t = TypeError.new(@@errors)
|
42
|
-
raise(t, t.inspect, caller) if @@errors.size > 0
|
43
|
-
end
|
44
|
-
|
45
|
-
def register_supertype(supertype, handler)
|
46
|
-
enforce_primitive!(Symbol, supertype, "typestrict/register_supertype")
|
47
|
-
enforce_primitive!(Proc, handler, "typestrict/register_supertype")
|
48
|
-
|
49
|
-
@@dynamic_handlers[supertype] = handler
|
50
|
-
puts "registered a dynamic handler for supertype: #{supertype}"
|
51
|
-
end
|
52
|
-
|
53
|
-
def header(context, data)
|
54
|
-
"#{context}; #{data.class.inspect}::#{data.inspect}"
|
55
|
-
end
|
56
|
-
|
57
|
-
def enforce_primitive!(type, data, context="Value")
|
58
|
-
catch_error "#{header(context, data)} must be of type #{type}" unless (data.is_a? type and type.is_a? Class)
|
59
|
-
return data
|
60
|
-
end
|
61
|
-
|
62
|
-
def enforce_strict_primitives!(types, data, context="Value")
|
63
|
-
enforce_primitive!(Array, types, 'lib/typestrict')
|
64
|
-
types.each {|type| enforce_primitive!(Object, type, 'lib/typestrict')}
|
65
|
-
types.each do |type|
|
66
|
-
enforce_primitive!(type, data, context)
|
67
|
-
end
|
68
|
-
return data
|
69
|
-
end
|
70
|
-
|
71
|
-
def enforce_weak_primitives!(types, data, context="Value")
|
72
|
-
enforce_primitive!(Array, types, 'lib/typestrict')
|
73
|
-
types.each {|type| enforce_primitive!(Object, type, 'lib/typestrict')}
|
74
|
-
|
75
|
-
raise_set_before = @@raise_exception
|
76
|
-
setmode_catch!
|
77
|
-
|
78
|
-
match_found = false
|
79
|
-
types.each do |type|
|
80
|
-
begin
|
81
|
-
s = @@errors.size
|
82
|
-
enforce_primitive!(type, data, context)
|
83
|
-
match_found = true unless s != @@errors.size
|
84
|
-
rescue
|
85
|
-
next
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
setmode_raise! if raise_set_before
|
90
|
-
|
91
|
-
catch_error "#{header(context, data)} must be of one of the types of #{types.inspect}" unless match_found
|
92
|
-
return data
|
93
|
-
end
|
94
|
-
|
95
|
-
def enforce_non_nil!(obj, context="Value")
|
96
|
-
catch_error "#{context}: Object is nil!" if obj.nil?
|
97
|
-
return obj
|
98
|
-
end
|
99
|
-
|
100
|
-
def enforce!(supertype, data, context="Value") #write a more generic handler, for new types?
|
101
|
-
enforce_non_nil!(data, context)
|
102
|
-
|
103
|
-
if supertype.is_a? Array #enumeration of values
|
104
|
-
catch_error "#{header(context, data)} should take on a value within #{supertype.inspect}" unless supertype.include? data
|
1
|
+
require File.join(File.dirname(__FILE__), 'base')
|
2
|
+
require File.join(File.dirname(__FILE__), 'supertypes')
|
105
3
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
catch_error "#{header(context, data)} can't be empty string" unless (data.size > 0)
|
111
|
-
|
112
|
-
when :natural_number
|
113
|
-
enforce_primitive!(Fixnum, data, context)
|
114
|
-
catch_error "#{header(context, data)} must be > 0" unless (data > 0)
|
115
|
-
|
116
|
-
when :integer
|
117
|
-
enforce_primitive!(Fixnum, data, context)
|
118
|
-
|
119
|
-
when :numeric
|
120
|
-
enforce_primitive!(Numeric, data, context)
|
121
|
-
|
122
|
-
when :boolean
|
123
|
-
enforce_weak_primitives!([TrueClass, FalseClass], data, context)
|
124
|
-
|
125
|
-
when :float
|
126
|
-
enforce_primitive!(Float, data, context)
|
127
|
-
|
128
|
-
when :character
|
129
|
-
enforce!(:string, data, context)
|
130
|
-
catch_error "#{header(context, data)} must be a single character!" unless data.size == 1
|
131
|
-
|
132
|
-
when :procedure
|
133
|
-
enforce_primitive!(Proc, data, context)
|
134
|
-
|
135
|
-
when :string_array
|
136
|
-
enforce_primitive!(Array, data, context)
|
137
|
-
data.each {|item| enforce_primitive!(String, item, context)}
|
138
|
-
|
139
|
-
when :numeric_array
|
140
|
-
enforce_primitive!(Array, data, context)
|
141
|
-
data.each {|item| enforce_primitive!(Numeric, item, context)}
|
142
|
-
|
143
|
-
when :float_array
|
144
|
-
enforce_primitive!(Array, data, context)
|
145
|
-
data.each {|item| enforce_primitive!(Float, item, context)}
|
146
|
-
|
147
|
-
when :integer_array
|
148
|
-
enforce_primitive!(Array, data, context)
|
149
|
-
data.each {|item| enforce_primitive!(Fixnum, item, context)}
|
150
|
-
|
151
|
-
when :hex_color
|
152
|
-
enforce!(:string, data, context)
|
153
|
-
catch_error "#{header(context, data)} must be six characters long" unless (data.size == 6)
|
154
|
-
data.upcase.each_byte {|c| catch_error "#{header(context, data)} must contain only hexadecimal characters" unless ((48 <= c and c <= 57) or (65 <= c and c <= 70))}
|
155
|
-
|
156
|
-
else
|
157
|
-
if @@dynamic_handlers.has_key? supertype
|
158
|
-
@@dynamic_handlers[supertype].call(data, context="Value")
|
159
|
-
else
|
160
|
-
catch_error "undefined symbol-supertype encountered: #{supertype.inspect}"
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
return data
|
166
|
-
end
|
167
|
-
|
168
|
-
def enforce_map!(matrix, map)
|
169
|
-
enforce_primitive!(Hash, matrix, "lib/typestrict")
|
170
|
-
enforce_primitive!(Hash, map, "lib/typestrict")
|
171
|
-
|
172
|
-
setmode_catch!
|
173
|
-
|
174
|
-
matrix.each do |param, type|
|
175
|
-
if map.has_key? param
|
176
|
-
enforce!(type, map[param], "map[#{param.inspect}]")
|
177
|
-
else
|
178
|
-
catch_error "map: missing required param: #{param.inspect}"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
raise_hell!
|
182
|
-
setmode_raise!
|
183
|
-
return map
|
184
|
-
end
|
4
|
+
module Strict
|
5
|
+
VERSION = '0.0.8'
|
6
|
+
include Strict::Base
|
7
|
+
include Strict::SuperTypes
|
185
8
|
end
|
9
|
+
|
10
|
+
include Strict
|
11
|
+
SuperTypes::register_default_supertypes!
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typestrict
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Raeez Lorgat
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-08 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -68,6 +68,8 @@ files:
|
|
68
68
|
- Rakefile
|
69
69
|
- bin/typestrict
|
70
70
|
- lib/typestrict.rb
|
71
|
+
- lib/base.rb
|
72
|
+
- lib/supertypes.rb
|
71
73
|
- test/test_strict.rb
|
72
74
|
has_rdoc: true
|
73
75
|
homepage: http://www.raeez.com/strict
|