typestrict 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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 enhancement
14
+ * 2 major enhancements
3
15
 
4
16
  * Added :procedure supertype
5
17
  * Added :character supertype
data/Manifest.txt CHANGED
@@ -5,4 +5,6 @@ README.txt
5
5
  Rakefile
6
6
  bin/typestrict
7
7
  lib/typestrict.rb
8
+ lib/base.rb
9
+ lib/supertypes.rb
8
10
  test/test_strict.rb
data/README CHANGED
@@ -105,9 +105,3 @@ valid_data = {
105
105
  }
106
106
 
107
107
  validate_map!(type_matrix, invalid_data) # => all checks pass
108
-
109
- TODO
110
- ----
111
- Implement generic handler for super-types
112
- Performance analysis
113
- Implement low-level?
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
- module Strict
2
- VERSION = '0.0.6'
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
- else if supertype.is_a? Symbol #distinct type
107
- case supertype
108
- when :string
109
- enforce_primitive!(String, data, context)
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: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
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-07 00:00:00 -04:00
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