instantcache 0.1.0a1
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/.gemtest +0 -0
- data/History.txt +4 -0
- data/LICENCE.txt +201 -0
- data/Manifest.txt +15 -0
- data/README.txt +245 -0
- data/Rakefile +38 -0
- data/instantcache.gemspec +43 -0
- data/lib/instantcache/exceptions.rb +240 -0
- data/lib/instantcache.rb +1254 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/test_helper.rb +8 -0
- data/test/test_instantcache.rb +62 -0
- data/test/test_sharing_complex.rb +187 -0
- data/test/test_sharing_simple.rb +164 -0
- metadata +142 -0
@@ -0,0 +1,240 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright © 2011 Ken Coar
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#++
|
18
|
+
|
19
|
+
module InstantCache
|
20
|
+
|
21
|
+
#
|
22
|
+
# = InstantCache exceptions
|
23
|
+
#
|
24
|
+
# Author:: Ken Coar
|
25
|
+
# Copyright:: Copyright © 2011 Ken Coar
|
26
|
+
# License:: Apache Licence 2.0
|
27
|
+
#
|
28
|
+
# == Description
|
29
|
+
#
|
30
|
+
# InstantCache reports problems using Ruby's exception mechanism. Its
|
31
|
+
# exceptions are a little different from the usual run-of-the-mill
|
32
|
+
# ones, however. Each exception declaration (aside from the
|
33
|
+
# superclass) consists solely of a constant named
|
34
|
+
# <tt>MessageFormat</tt>, which is a two-element array of strings.
|
35
|
+
# The first element is the default text of the message, which is used
|
36
|
+
# when the exception is raised without arguments. <i>E.g.</i>,
|
37
|
+
#
|
38
|
+
# raise InstantCache::Destroyed
|
39
|
+
#
|
40
|
+
# The second element of the <tt>MessageFormat</tt> array is utilised
|
41
|
+
# when a new instance of the exception is created, and the
|
42
|
+
# constructor's arguments are used as <tt>sprintf</tt>-style arguments
|
43
|
+
# with the <tt>MessageFormat</tt> text.
|
44
|
+
#
|
45
|
+
|
46
|
+
#
|
47
|
+
# The superclass for all of the InstantCache exceptions. It
|
48
|
+
# provides all the infrastructure needed by the individual specific
|
49
|
+
# exceptions.
|
50
|
+
#
|
51
|
+
class Exception < StandardError
|
52
|
+
|
53
|
+
#
|
54
|
+
# === Description
|
55
|
+
#
|
56
|
+
# As the superclass, this exception is not intended for direct invocation.
|
57
|
+
#
|
58
|
+
# === Arguments
|
59
|
+
# N/A
|
60
|
+
#
|
61
|
+
# === Exceptions
|
62
|
+
# [<tt>InstantCache::IncompleteException</tt>] This class was
|
63
|
+
# subclassed, but the
|
64
|
+
# subclass didn't
|
65
|
+
# declare the
|
66
|
+
# requisite
|
67
|
+
# <tt>MessageFormat</tt>
|
68
|
+
# constant.
|
69
|
+
#
|
70
|
+
def initialize(*args)
|
71
|
+
@appargs = args.dup
|
72
|
+
super(args[0])
|
73
|
+
unless (self.class.constants.include?('MessageFormat'))
|
74
|
+
raise IncompleteException.new(self.class.name)
|
75
|
+
end
|
76
|
+
end # End of def initialize
|
77
|
+
|
78
|
+
#
|
79
|
+
# === Description
|
80
|
+
# This is an override of the standard exception <tt>message</tt>
|
81
|
+
# method, enhanced to deal with our with-or-without-arguments
|
82
|
+
# invocation decision mechanism.
|
83
|
+
#
|
84
|
+
# If the current class has a <b><tt>MessageFormat</tt></b>
|
85
|
+
# constant array defined, the first element will be used for the
|
86
|
+
# exception message if no arguments were passed to the invocation.
|
87
|
+
# Otherwise, the second element of the <tt>MessageFormat</tt>
|
88
|
+
# array will be treated as a '%' format string and the invocation
|
89
|
+
# arguments as input to the formatting process, the result of
|
90
|
+
# which becomes the exception message string.
|
91
|
+
#
|
92
|
+
# === Arguments
|
93
|
+
# <i>None.</i>
|
94
|
+
#
|
95
|
+
# === Exceptions
|
96
|
+
# <i>None.</i>
|
97
|
+
#
|
98
|
+
def message
|
99
|
+
if (self.class.constants.include?('MessageFormat'))
|
100
|
+
fmt = self.class::MessageFormat[@appargs.empty? ? 0 : 1]
|
101
|
+
return fmt % [ *@appargs ]
|
102
|
+
end
|
103
|
+
return @message
|
104
|
+
end # End of def message
|
105
|
+
|
106
|
+
#
|
107
|
+
# === Description
|
108
|
+
# Return the message text of the exception as a string, after
|
109
|
+
# applying any appropriate formating.
|
110
|
+
#
|
111
|
+
# === Arguments
|
112
|
+
# <i>None.</i>
|
113
|
+
#
|
114
|
+
# === Exceptions
|
115
|
+
# <i>None.</i>
|
116
|
+
#
|
117
|
+
def to_s
|
118
|
+
return self.message
|
119
|
+
end # End of def to_s
|
120
|
+
|
121
|
+
end # End of class Exception
|
122
|
+
|
123
|
+
#
|
124
|
+
# Some exception was raised with the wrong arguments.
|
125
|
+
#
|
126
|
+
class IncompleteException < InstantCache::Exception
|
127
|
+
#
|
128
|
+
# ==== <tt>raise IncompleteException</tt>
|
129
|
+
# => InstantCache::IncompleteException: improperly-coded exception raised
|
130
|
+
#
|
131
|
+
# ==== <tt>raise IncompleteException.new('<i>arg</i>')</tt>
|
132
|
+
# => InstantCache::IncompleteException: improperly-coded exception "arg" raised
|
133
|
+
#
|
134
|
+
MessageFormat = [
|
135
|
+
'improperly-coded exception raised',
|
136
|
+
'improperly-coded exception "%s" raised',
|
137
|
+
]
|
138
|
+
end # End of class IncompleteException
|
139
|
+
|
140
|
+
#
|
141
|
+
# Once a variable has been hit by the 'destroy!' method, it
|
142
|
+
# becomes inaccessible to the instance.
|
143
|
+
#
|
144
|
+
class Destroyed < InstantCache::Exception
|
145
|
+
#
|
146
|
+
# ==== <tt>raise Destroyed</tt>
|
147
|
+
# => InstantCache::Destroyed: attempt to access destroyed variable
|
148
|
+
#
|
149
|
+
# ==== <tt>raise Destroyed.new('<i>arg</i>')</tt>
|
150
|
+
# => InstantCache::Destroyed: attempt to access destroyed variable "arg"
|
151
|
+
#
|
152
|
+
MessageFormat = [
|
153
|
+
'attempt to access destroyed variable',
|
154
|
+
'attempt to access destroyed variable "%s"',
|
155
|
+
]
|
156
|
+
end # End of class Destroyed
|
157
|
+
|
158
|
+
#
|
159
|
+
# Our record of the locked status of a cell differs from the information
|
160
|
+
# stored in the memcache about it. This Is Not Good.
|
161
|
+
#
|
162
|
+
class LockInconsistency < InstantCache::Exception
|
163
|
+
#
|
164
|
+
# ==== <tt>raise LockInconsistency</tt>
|
165
|
+
# => InstantCache::LockInconsistency: interlock cell inconsistency
|
166
|
+
#
|
167
|
+
# ==== <tt>raise LockInconsistency.new('<i>name</i>', '<i>true</i>', '<i>false</i>')</tt>
|
168
|
+
# => InstantCache::LockInconsistency: interlock cell inconsistency
|
169
|
+
# cell='name', expected='true', actual='false'
|
170
|
+
#
|
171
|
+
MessageFormat = [
|
172
|
+
'interlock cell inconsistency',
|
173
|
+
"interlock cell inconsistency\n" +
|
174
|
+
"\tcell='%s', expected='%s', actual='%s'",
|
175
|
+
]
|
176
|
+
end # End of class LockInconsistency
|
177
|
+
|
178
|
+
#
|
179
|
+
# User-supplied names are only permitted for shared variables;
|
180
|
+
# otherwise private ones may get inadvertently shared and bollixed.
|
181
|
+
#
|
182
|
+
class SharedOnly < InstantCache::Exception
|
183
|
+
#
|
184
|
+
# ==== <tt>raise SharedOnly</tt>
|
185
|
+
# => InstantCache::SharedOnly: custom names are only permitted for shared variables
|
186
|
+
#
|
187
|
+
# ==== <tt>raise SharedOnly.new('<i>name</i>')</tt>
|
188
|
+
# => InstantCache::SharedOnly: custom names are only permitted for shared variables; 'name' is labelled as private
|
189
|
+
#
|
190
|
+
MessageFormat = [
|
191
|
+
'custom names are only permitted for shared variables',
|
192
|
+
('custom names are only permitted for shared variables; ' +
|
193
|
+
"'%s' is labelled as private"),
|
194
|
+
]
|
195
|
+
end # End of class SharedOnly
|
196
|
+
|
197
|
+
#
|
198
|
+
# Counter variables are only permitted to be frobbed with integers.
|
199
|
+
# We gritch if anything else is attempted.
|
200
|
+
#
|
201
|
+
class CounterIntegerOnly < InstantCache::Exception
|
202
|
+
#
|
203
|
+
# ==== <tt>raise CounterIntegerOnly</tt>
|
204
|
+
# => InstantCache::CounterIntegerOnly: variables declared as counters are integer-only
|
205
|
+
#
|
206
|
+
# ==== <tt>raise CounterIntegerOnly.new('<i>name</i>')</tt>
|
207
|
+
# => InstantCache::CounterIntegerOnly: variables declared as counters are integer-only: name
|
208
|
+
#
|
209
|
+
MessageFormat = [
|
210
|
+
'variables declared as counters are integer-only',
|
211
|
+
'variables declared as counters are integer-only: %s',
|
212
|
+
]
|
213
|
+
end # End of class CounterIntegerOnly
|
214
|
+
|
215
|
+
#
|
216
|
+
# Because of the annotation of returned values with callback singleton
|
217
|
+
# methods, it's possible for multiple user variables to hold references
|
218
|
+
# to a cell. <i>E.g.</i>, one might remember the cell as a hash and
|
219
|
+
# modify an element, even though the cell has actually be explicitly
|
220
|
+
# set to something else. This exception is raised if there's a mismatch
|
221
|
+
# when an annotation tries to update the cell.
|
222
|
+
#
|
223
|
+
# TODO: This is not working properly yet.
|
224
|
+
#
|
225
|
+
class IncompatibleType < InstantCache::Exception
|
226
|
+
#
|
227
|
+
# ==== <tt>raise IncompatibleType</tt>
|
228
|
+
# => InstantCache::IncompatibleType: variable class incompatible with cached value
|
229
|
+
#
|
230
|
+
# ==== <tt>raise IncompatibleType.new('<i>Hash</i>', '<i>Array</i>', '<i>name</i>')</tt>
|
231
|
+
# => InstantCache::IncompatibleType: variable class "Hash" incompatible with class "Array" of cached variable "name"',
|
232
|
+
#
|
233
|
+
MessageFormat = [
|
234
|
+
'variable class incompatible with cached value',
|
235
|
+
'variable class "%s" incompatible with class "%s" ' +
|
236
|
+
'of cached variable "%s"',
|
237
|
+
]
|
238
|
+
end # End of class IncompatibleType
|
239
|
+
|
240
|
+
end # End of module InstantCache
|