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 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