protocol 0.8.1 → 0.8.2
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/CHANGES +3 -0
- data/Rakefile +45 -18
- data/VERSION +1 -1
- data/doc-main.txt +238 -0
- data/lib/protocol.rb +2 -243
- data/lib/protocol/version.rb +8 -0
- data/make_doc.rb +1 -4
- data/protocol.gemspec +27 -0
- metadata +20 -18
data/CHANGES
CHANGED
data/Rakefile
CHANGED
@@ -4,13 +4,14 @@ begin
|
|
4
4
|
require 'rake/gempackagetask'
|
5
5
|
rescue LoadError
|
6
6
|
end
|
7
|
+
require 'rake/clean'
|
7
8
|
require 'rbconfig'
|
8
|
-
|
9
9
|
include Config
|
10
10
|
|
11
11
|
PKG_NAME = 'protocol'
|
12
12
|
PKG_VERSION = File.read('VERSION').chomp
|
13
13
|
PKG_FILES = FileList['**/*'].exclude(/(CVS|\.svn|pkg|coverage)/)
|
14
|
+
CLEAN.include 'coverage', 'doc'
|
14
15
|
|
15
16
|
desc "Installing library"
|
16
17
|
task :install do
|
@@ -32,19 +33,13 @@ task :coverage do
|
|
32
33
|
sh 'rcov -Ilib tests/test_protocol.rb'
|
33
34
|
end
|
34
35
|
|
35
|
-
desc "Clean created files"
|
36
|
-
task :clean do
|
37
|
-
rm_rf %w[doc coverage]
|
38
|
-
end
|
39
|
-
|
40
|
-
desc "Prepare a release"
|
41
|
-
task :release => [ :test, :clean, :package ]
|
42
|
-
|
43
36
|
if defined? Gem
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
s.
|
37
|
+
spec_src =<<GEM
|
38
|
+
# -*- encoding: utf-8 -*-
|
39
|
+
Gem::Specification.new do |s|
|
40
|
+
s.name = '#{PKG_NAME}'
|
41
|
+
s.version = '#{PKG_VERSION}'
|
42
|
+
s.files = #{PKG_FILES.to_a.sort.inspect}
|
48
43
|
s.summary = 'Method Protocols for Ruby Classes'
|
49
44
|
s.description = <<EOT
|
50
45
|
This library offers an implementation of protocols against which you can check
|
@@ -55,21 +50,53 @@ for methods specified in a protocol.
|
|
55
50
|
EOT
|
56
51
|
|
57
52
|
s.require_path = 'lib'
|
58
|
-
s.add_dependency 'ParseTree', '~>
|
53
|
+
s.add_dependency 'ParseTree', '~> 3.0'
|
59
54
|
|
60
55
|
s.has_rdoc = true
|
61
|
-
s.rdoc_options << '--
|
62
|
-
|
56
|
+
s.rdoc_options << '--main' << 'doc-main.txt'
|
57
|
+
s.extra_rdoc_files << 'doc-main.txt'
|
63
58
|
s.test_files << 'tests/test_protocol.rb'
|
64
59
|
|
65
60
|
s.author = "Florian Frank"
|
66
61
|
s.email = "flori@ping.de"
|
67
|
-
s.homepage = "http
|
68
|
-
s.rubyforge_project = "
|
62
|
+
s.homepage = "http://#{PKG_NAME}.rubyforge.org"
|
63
|
+
s.rubyforge_project = "#{PKG_NAME}"
|
64
|
+
end
|
65
|
+
GEM
|
66
|
+
|
67
|
+
desc 'Create a gemspec file'
|
68
|
+
task :gemspec do
|
69
|
+
File.open("#{PKG_NAME}.gemspec", 'w') do |f|
|
70
|
+
f.puts spec_src
|
71
|
+
end
|
69
72
|
end
|
70
73
|
|
74
|
+
spec = eval(spec_src)
|
71
75
|
Rake::GemPackageTask.new(spec) do |pkg|
|
72
76
|
pkg.need_tar = true
|
73
77
|
pkg.package_files += PKG_FILES
|
74
78
|
end
|
75
79
|
end
|
80
|
+
|
81
|
+
desc m = "Writing version information for #{PKG_VERSION}"
|
82
|
+
task :version do
|
83
|
+
puts m
|
84
|
+
File.open(File.join('lib', 'protocol', 'version.rb'), 'w') do |v|
|
85
|
+
v.puts <<EOT
|
86
|
+
module Protocol
|
87
|
+
# Protocol version
|
88
|
+
VERSION = '#{PKG_VERSION}'
|
89
|
+
VERSION_ARRAY = VERSION.split(/\\./).map { |x| x.to_i } # :nodoc:
|
90
|
+
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
|
91
|
+
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
|
92
|
+
VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
|
93
|
+
end
|
94
|
+
EOT
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
desc "Default task"
|
99
|
+
task :default => [ :version, :gemspec, :test ]
|
100
|
+
|
101
|
+
desc "Prepare a release"
|
102
|
+
task :release => [ :clean, :version, :gemspec, :package ]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.2
|
data/doc-main.txt
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
== Protocol - Method Protocol Specifications in Ruby
|
2
|
+
|
3
|
+
=== Author
|
4
|
+
|
5
|
+
Florian Frank mailto:flori@ping.de
|
6
|
+
|
7
|
+
=== License
|
8
|
+
|
9
|
+
This is free software; you can redistribute it and/or modify it under the
|
10
|
+
terms of the GNU General Public License Version 2 as published by the Free
|
11
|
+
Software Foundation: www.gnu.org/copyleft/gpl.html
|
12
|
+
|
13
|
+
=== Download
|
14
|
+
|
15
|
+
The latest version of <b>protocol</b> can be found at
|
16
|
+
|
17
|
+
* http://rubyforge.org/frs/?group_id=4778
|
18
|
+
|
19
|
+
The homepage of this library is located at
|
20
|
+
|
21
|
+
* http://protocol.rubyforge.org
|
22
|
+
|
23
|
+
=== Description
|
24
|
+
|
25
|
+
This library offers an implementation of protocols against which you can
|
26
|
+
check the conformity of your classes or instances of your classes. They are a
|
27
|
+
bit like Java Interfaces, but as mixin modules they can also contain already
|
28
|
+
implemented methods. Additionally you can define preconditions/postconditions
|
29
|
+
for methods specified in a protocol.
|
30
|
+
|
31
|
+
=== Usage
|
32
|
+
|
33
|
+
This defines a protocol named +Enumerating+:
|
34
|
+
|
35
|
+
Enumerating = Protocol do
|
36
|
+
# Iterate over each element of this Enumerating class and pass it to the
|
37
|
+
# +block+.
|
38
|
+
def each(&block) end
|
39
|
+
|
40
|
+
include Enumerable
|
41
|
+
end
|
42
|
+
|
43
|
+
Every class, that conforms to this protocol, has to implement the understood
|
44
|
+
messages (+each+ in this example - with no ordinary arguments and a block
|
45
|
+
argument). The following would be an equivalent protocol definition:
|
46
|
+
|
47
|
+
Enumerating = Protocol do
|
48
|
+
# Iterate over each element of this Enumerating class and pass it to the
|
49
|
+
# +block+.
|
50
|
+
understand :each, 0, true
|
51
|
+
|
52
|
+
include Enumerable
|
53
|
+
end
|
54
|
+
|
55
|
+
An example of a conforming class is the class +Ary+:
|
56
|
+
class Ary
|
57
|
+
def initialize
|
58
|
+
@ary = [1, 2, 3]
|
59
|
+
end
|
60
|
+
|
61
|
+
def each(&block)
|
62
|
+
@ary.each(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
conform_to Enumerating
|
66
|
+
end
|
67
|
+
|
68
|
+
The last line (this command being the last line of the class definition is
|
69
|
+
important!) of class +Ary+ <tt>conform_to Enumerating</tt> checks the
|
70
|
+
conformance of +Ary+ to the +Enumerating+ protocol. If the +each+ method were
|
71
|
+
not implemented in +Ary+ a CheckFailed exception would have been thrown,
|
72
|
+
containing all the offending CheckError instances.
|
73
|
+
|
74
|
+
It also mixes in all the methods that were included in protocol +Enumerating+
|
75
|
+
(+Enumerable+'s instance methods). More examples of this can be seen in the
|
76
|
+
examples sub directory of the source distribution of this library in file
|
77
|
+
examples/enumerating.rb.
|
78
|
+
|
79
|
+
==== Template Method Pattern
|
80
|
+
|
81
|
+
It's also possible to mix protocol specification and behaviour implementation
|
82
|
+
like this:
|
83
|
+
|
84
|
+
Locking = Protocol do
|
85
|
+
specification # not necessary, because Protocol defaults to specification
|
86
|
+
# mode already
|
87
|
+
|
88
|
+
def lock() end
|
89
|
+
|
90
|
+
def unlock() end
|
91
|
+
|
92
|
+
implementation
|
93
|
+
|
94
|
+
def synchronize
|
95
|
+
lock
|
96
|
+
begin
|
97
|
+
yield
|
98
|
+
ensure
|
99
|
+
unlock
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
This specifies a Locking protocol against which several class implementations
|
105
|
+
can be checked against for conformance. Here's a FileMutex implementation:
|
106
|
+
|
107
|
+
class FileMutex
|
108
|
+
def initialize
|
109
|
+
@tempfile = Tempfile.new 'file-mutex'
|
110
|
+
end
|
111
|
+
|
112
|
+
def path
|
113
|
+
@tempfile.path
|
114
|
+
end
|
115
|
+
|
116
|
+
def lock
|
117
|
+
puts "Locking '#{path}'."
|
118
|
+
@tempfile.flock File::LOCK_EX
|
119
|
+
end
|
120
|
+
|
121
|
+
def unlock
|
122
|
+
puts "Unlocking '#{path}'."
|
123
|
+
@tempfile.flock File::LOCK_UN
|
124
|
+
end
|
125
|
+
|
126
|
+
conform_to Locking
|
127
|
+
end
|
128
|
+
|
129
|
+
The Locking#synchronize method is a template method (see
|
130
|
+
http://en.wikipedia.org/wiki/Template_method_pattern), that uses the
|
131
|
+
implemtented methods, to make block based locking possbile:
|
132
|
+
|
133
|
+
mutex = FileMutex.new
|
134
|
+
mutex.synchronize do
|
135
|
+
puts "Synchronized with '#{file.path}'."
|
136
|
+
end
|
137
|
+
|
138
|
+
Now it's easy to swap the implementation to a memory based mutex
|
139
|
+
implementation instead:
|
140
|
+
|
141
|
+
class MemoryMutex
|
142
|
+
def initialize
|
143
|
+
@mutex = Mutex.new
|
144
|
+
end
|
145
|
+
|
146
|
+
def lock
|
147
|
+
@mutex.lock
|
148
|
+
end
|
149
|
+
|
150
|
+
def unlock
|
151
|
+
@mutex.unlock
|
152
|
+
end
|
153
|
+
|
154
|
+
conform_to Locking # actually Mutex itself would conform as well ;)
|
155
|
+
end
|
156
|
+
|
157
|
+
To check an +object+ for conformity to the Locking protocol call
|
158
|
+
Locking.check +object+ and rescue a CheckFailed. Here's an example class
|
159
|
+
|
160
|
+
class MyClass
|
161
|
+
def initialize
|
162
|
+
@mutex = FileMutex.new
|
163
|
+
end
|
164
|
+
|
165
|
+
attr_reader :mutex
|
166
|
+
|
167
|
+
def mutex=(mutex)
|
168
|
+
Locking.check mutex
|
169
|
+
@mutex = mutex
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
This causes a CheckFailed exception to be thrown:
|
174
|
+
obj.mutex = Object.new
|
175
|
+
|
176
|
+
This would not raise an exception:
|
177
|
+
obj.mutex = MemoryMutex.new
|
178
|
+
|
179
|
+
And neither would this
|
180
|
+
|
181
|
+
obj.mutex = Mutex.new # => #<Mutex:0xb799a4f0 @locked=false, @waiting=[]>
|
182
|
+
|
183
|
+
because coincidentally this is true
|
184
|
+
|
185
|
+
Mutex.conform_to? Locking # => true
|
186
|
+
|
187
|
+
and thus Locking.check doesn't throw an exception. See the
|
188
|
+
examples/locking.rb file for code.
|
189
|
+
|
190
|
+
==== Preconditions and Postconditions
|
191
|
+
|
192
|
+
You can add additional runtime checks for method arguments and results by
|
193
|
+
specifying pre- and postconditions. Here is the classical stack example, that
|
194
|
+
shows how:
|
195
|
+
|
196
|
+
StackProtocol = Protocol do
|
197
|
+
def push(x)
|
198
|
+
postcondition { top === x }
|
199
|
+
postcondition { result === myself }
|
200
|
+
end
|
201
|
+
|
202
|
+
def top() end
|
203
|
+
|
204
|
+
def size() end
|
205
|
+
|
206
|
+
def empty?()
|
207
|
+
postcondition { size === 0 ? result : !result }
|
208
|
+
end
|
209
|
+
|
210
|
+
def pop()
|
211
|
+
s = size
|
212
|
+
precondition { not empty? }
|
213
|
+
postcondition { size === s - 1 }
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
Defining protocols and checking against conformance doesn't get in the way of
|
218
|
+
Ruby's duck typing, but you can still use protocols to define, document, and
|
219
|
+
check implementations that you expect from client code.
|
220
|
+
|
221
|
+
==== Error modes in Protocols
|
222
|
+
|
223
|
+
You can set different error modes for your protocols. By default the mode is
|
224
|
+
set to :error, and a failed protocol conformance check raises a CheckError (a
|
225
|
+
marker module) exception. Alternatively you can set the error mode to
|
226
|
+
:warning with:
|
227
|
+
|
228
|
+
Foo = Protocol do
|
229
|
+
check_failure :warning
|
230
|
+
end
|
231
|
+
|
232
|
+
during Protocol definition or later
|
233
|
+
|
234
|
+
Foo.check_failure :warning
|
235
|
+
|
236
|
+
In :warning mode no execptions are raised, only a warning is printed to
|
237
|
+
STDERR. If you set the error mode via Protocol::ProtocolModule#check_failure
|
238
|
+
to :none, nothing will happen on conformance check failures.
|
data/lib/protocol.rb
CHANGED
@@ -1,248 +1,7 @@
|
|
1
|
-
|
2
|
-
# vim: set et sw=2 ts=2:
|
3
|
-
# :startdoc:
|
1
|
+
require 'protocol/version'
|
4
2
|
require 'parse_tree'
|
5
3
|
require 'sexp_processor'
|
6
|
-
|
7
|
-
# = protocol.rb - Method Protocol Specifications in Ruby
|
8
|
-
#
|
9
|
-
# == Author
|
10
|
-
#
|
11
|
-
# Florian Frank mailto:flori@ping.de
|
12
|
-
#
|
13
|
-
# == License
|
14
|
-
#
|
15
|
-
# This is free software; you can redistribute it and/or modify it under the
|
16
|
-
# terms of the GNU General Public License Version 2 as published by the Free
|
17
|
-
# Software Foundation: www.gnu.org/copyleft/gpl.html
|
18
|
-
#
|
19
|
-
# == Download
|
20
|
-
#
|
21
|
-
# The latest version of <b>protocol</b> can be found at
|
22
|
-
#
|
23
|
-
# * http://rubyforge.org/frs/?group_id=4778
|
24
|
-
#
|
25
|
-
# The homepage of this library is located at
|
26
|
-
#
|
27
|
-
# * http://protocol.rubyforge.org
|
28
|
-
#
|
29
|
-
# == Description
|
30
|
-
#
|
31
|
-
# This library offers an implementation of protocols against which you can
|
32
|
-
# check the conformity of your classes or instances of your classes. They are a
|
33
|
-
# bit like Java Interfaces, but as mixin modules they can also contain already
|
34
|
-
# implemented methods. Additionally you can define preconditions/postconditions
|
35
|
-
# for methods specified in a protocol.
|
36
|
-
#
|
37
|
-
# == Usage
|
38
|
-
#
|
39
|
-
# This defines a protocol named +Enumerating+:
|
40
|
-
#
|
41
|
-
# Enumerating = Protocol do
|
42
|
-
# # Iterate over each element of this Enumerating class and pass it to the
|
43
|
-
# # +block+.
|
44
|
-
# def each(&block) end
|
45
|
-
#
|
46
|
-
# include Enumerable
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
# Every class, that conforms to this protocol, has to implement the understood
|
50
|
-
# messages (+each+ in this example - with no ordinary arguments and a block
|
51
|
-
# argument). The following would be an equivalent protocol definition:
|
52
|
-
#
|
53
|
-
# Enumerating = Protocol do
|
54
|
-
# # Iterate over each element of this Enumerating class and pass it to the
|
55
|
-
# # +block+.
|
56
|
-
# understand :each, 0, true
|
57
|
-
#
|
58
|
-
# include Enumerable
|
59
|
-
# end
|
60
|
-
#
|
61
|
-
# An example of a conforming class is the class +Ary+:
|
62
|
-
# class Ary
|
63
|
-
# def initialize
|
64
|
-
# @ary = [1, 2, 3]
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
# def each(&block)
|
68
|
-
# @ary.each(&block)
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
# conform_to Enumerating
|
72
|
-
# end
|
73
|
-
#
|
74
|
-
# The last line (this command being the last line of the class definition is
|
75
|
-
# important!) of class +Ary+ <tt>conform_to Enumerating</tt> checks the
|
76
|
-
# conformance of +Ary+ to the +Enumerating+ protocol. If the +each+ method were
|
77
|
-
# not implemented in +Ary+ a CheckFailed exception would have been thrown,
|
78
|
-
# containing all the offending CheckError instances.
|
79
|
-
#
|
80
|
-
# It also mixes in all the methods that were included in protocol +Enumerating+
|
81
|
-
# (+Enumerable+'s instance methods). More examples of this can be seen in the
|
82
|
-
# examples sub directory of the source distribution of this library in file
|
83
|
-
# examples/enumerating.rb.
|
84
|
-
#
|
85
|
-
# === Template Method Pattern
|
86
|
-
#
|
87
|
-
# It's also possible to mix protocol specification and behaviour implementation
|
88
|
-
# like this:
|
89
|
-
#
|
90
|
-
# Locking = Protocol do
|
91
|
-
# specification # not necessary, because Protocol defaults to specification
|
92
|
-
# # mode already
|
93
|
-
#
|
94
|
-
# def lock() end
|
95
|
-
#
|
96
|
-
# def unlock() end
|
97
|
-
#
|
98
|
-
# implementation
|
99
|
-
#
|
100
|
-
# def synchronize
|
101
|
-
# lock
|
102
|
-
# begin
|
103
|
-
# yield
|
104
|
-
# ensure
|
105
|
-
# unlock
|
106
|
-
# end
|
107
|
-
# end
|
108
|
-
# end
|
109
|
-
#
|
110
|
-
# This specifies a Locking protocol against which several class implementations
|
111
|
-
# can be checked against for conformance. Here's a FileMutex implementation:
|
112
|
-
#
|
113
|
-
# class FileMutex
|
114
|
-
# def initialize
|
115
|
-
# @tempfile = Tempfile.new 'file-mutex'
|
116
|
-
# end
|
117
|
-
#
|
118
|
-
# def path
|
119
|
-
# @tempfile.path
|
120
|
-
# end
|
121
|
-
#
|
122
|
-
# def lock
|
123
|
-
# puts "Locking '#{path}'."
|
124
|
-
# @tempfile.flock File::LOCK_EX
|
125
|
-
# end
|
126
|
-
#
|
127
|
-
# def unlock
|
128
|
-
# puts "Unlocking '#{path}'."
|
129
|
-
# @tempfile.flock File::LOCK_UN
|
130
|
-
# end
|
131
|
-
#
|
132
|
-
# conform_to Locking
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# The Locking#synchronize method is a template method (see
|
136
|
-
# http://en.wikipedia.org/wiki/Template_method_pattern), that uses the
|
137
|
-
# implemtented methods, to make block based locking possbile:
|
138
|
-
#
|
139
|
-
# mutex = FileMutex.new
|
140
|
-
# mutex.synchronize do
|
141
|
-
# puts "Synchronized with '#{file.path}'."
|
142
|
-
# end
|
143
|
-
#
|
144
|
-
# Now it's easy to swap the implementation to a memory based mutex
|
145
|
-
# implementation instead:
|
146
|
-
#
|
147
|
-
# class MemoryMutex
|
148
|
-
# def initialize
|
149
|
-
# @mutex = Mutex.new
|
150
|
-
# end
|
151
|
-
#
|
152
|
-
# def lock
|
153
|
-
# @mutex.lock
|
154
|
-
# end
|
155
|
-
#
|
156
|
-
# def unlock
|
157
|
-
# @mutex.unlock
|
158
|
-
# end
|
159
|
-
#
|
160
|
-
# conform_to Locking # actually Mutex itself would conform as well ;)
|
161
|
-
# end
|
162
|
-
#
|
163
|
-
# To check an +object+ for conformity to the Locking protocol call
|
164
|
-
# Locking.check +object+ and rescue a CheckFailed. Here's an example class
|
165
|
-
#
|
166
|
-
# class MyClass
|
167
|
-
# def initialize
|
168
|
-
# @mutex = FileMutex.new
|
169
|
-
# end
|
170
|
-
#
|
171
|
-
# attr_reader :mutex
|
172
|
-
#
|
173
|
-
# def mutex=(mutex)
|
174
|
-
# Locking.check mutex
|
175
|
-
# @mutex = mutex
|
176
|
-
# end
|
177
|
-
# end
|
178
|
-
#
|
179
|
-
# This causes a CheckFailed exception to be thrown:
|
180
|
-
# obj.mutex = Object.new
|
181
|
-
#
|
182
|
-
# This would not raise an exception:
|
183
|
-
# obj.mutex = MemoryMutex.new
|
184
|
-
#
|
185
|
-
# And neither would this
|
186
|
-
#
|
187
|
-
# obj.mutex = Mutex.new # => #<Mutex:0xb799a4f0 @locked=false, @waiting=[]>
|
188
|
-
#
|
189
|
-
# because coincidentally this is true
|
190
|
-
#
|
191
|
-
# Mutex.conform_to? Locking # => true
|
192
|
-
#
|
193
|
-
# and thus Locking.check doesn't throw an exception. See the
|
194
|
-
# examples/locking.rb file for code.
|
195
|
-
#
|
196
|
-
# === Preconditions and Postconditions
|
197
|
-
#
|
198
|
-
# You can add additional runtime checks for method arguments and results by
|
199
|
-
# specifying pre- and postconditions. Here is the classical stack example, that
|
200
|
-
# shows how:
|
201
|
-
#
|
202
|
-
# StackProtocol = Protocol do
|
203
|
-
# def push(x)
|
204
|
-
# postcondition { top == x }
|
205
|
-
# postcondition { result == myself }
|
206
|
-
# end
|
207
|
-
#
|
208
|
-
# def top() end
|
209
|
-
#
|
210
|
-
# def size() end
|
211
|
-
#
|
212
|
-
# def empty?()
|
213
|
-
# postcondition { size == 0 ? result : !result }
|
214
|
-
# end
|
215
|
-
#
|
216
|
-
# def pop()
|
217
|
-
# s = size
|
218
|
-
# precondition { not empty? }
|
219
|
-
# postcondition { size == s - 1 }
|
220
|
-
# end
|
221
|
-
# end
|
222
|
-
#
|
223
|
-
# Defining protocols and checking against conformance doesn't get in the way of
|
224
|
-
# Ruby's duck typing, but you can still use protocols to define, document, and
|
225
|
-
# check implementations that you expect from client code.
|
226
|
-
#
|
227
|
-
# === Error modes in Protocols
|
228
|
-
#
|
229
|
-
# You can set different error modes for your protocols. By default the mode is
|
230
|
-
# set to :error, and a failed protocol conformance check raises a CheckError (a
|
231
|
-
# marker module) exception. Alternatively you can set the error mode to
|
232
|
-
# :warning with:
|
233
|
-
#
|
234
|
-
# Foo = Protocol do
|
235
|
-
# check_failure :warning
|
236
|
-
# end
|
237
|
-
#
|
238
|
-
# during Protocol definition or later
|
239
|
-
#
|
240
|
-
# Foo.check_failure :warning
|
241
|
-
#
|
242
|
-
# In :warning mode no execptions are raised, only a warning is printed to
|
243
|
-
# STDERR. If you set the error mode via Protocol::ProtocolModule#check_failure
|
244
|
-
# to :none, nothing will happen on conformance check failures.
|
245
|
-
#
|
4
|
+
|
246
5
|
module Protocol
|
247
6
|
class ::Object
|
248
7
|
# Returns true if this object conforms to +protocol+, otherwise false.
|
data/make_doc.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# vim: set et sw=2 ts=2:
|
3
3
|
|
4
|
-
require 'rbconfig'
|
5
|
-
|
6
|
-
bindir = Config::CONFIG['bindir']
|
7
4
|
$outdir = 'doc/'
|
8
5
|
puts "Creating documentation in '#$outdir'."
|
9
|
-
system "
|
6
|
+
system "rdoc --main=doc-main.txt -o #$outdir doc-main.txt lib/protocol.rb"
|
data/protocol.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = 'protocol'
|
4
|
+
s.version = '0.8.2'
|
5
|
+
s.files = ["CHANGES", "COPYING", "Rakefile", "VERSION", "doc-main.txt", "examples", "examples/comparing.rb", "examples/enumerating.rb", "examples/game.rb", "examples/hello_world_patternitis.rb", "examples/indexing.rb", "examples/locking.rb", "examples/queue.rb", "examples/stack.rb", "install.rb", "lib", "lib/protocol", "lib/protocol.rb", "lib/protocol/core.rb", "lib/protocol/version.rb", "make_doc.rb", "protocol.gemspec", "tests", "tests/test_protocol.rb"]
|
6
|
+
s.summary = 'Method Protocols for Ruby Classes'
|
7
|
+
s.description = <<EOT
|
8
|
+
This library offers an implementation of protocols against which you can check
|
9
|
+
the conformity of your classes or instances of your classes. They are a bit
|
10
|
+
like Java Interfaces, but as mixin modules they can also contain already
|
11
|
+
implemented methods. Additionaly you can define preconditions/postconditions
|
12
|
+
for methods specified in a protocol.
|
13
|
+
EOT
|
14
|
+
|
15
|
+
s.require_path = 'lib'
|
16
|
+
s.add_dependency 'ParseTree', '~> 3.0'
|
17
|
+
|
18
|
+
s.has_rdoc = true
|
19
|
+
s.rdoc_options << '--main' << 'doc-main.txt'
|
20
|
+
s.extra_rdoc_files << 'doc-main.txt'
|
21
|
+
s.test_files << 'tests/test_protocol.rb'
|
22
|
+
|
23
|
+
s.author = "Florian Frank"
|
24
|
+
s.email = "flori@ping.de"
|
25
|
+
s.homepage = "http://protocol.rubyforge.org"
|
26
|
+
s.rubyforge_project = "protocol"
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-07-28 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: "
|
23
|
+
version: "3.0"
|
24
24
|
version:
|
25
25
|
description: This library offers an implementation of protocols against which you can check the conformity of your classes or instances of your classes. They are a bit like Java Interfaces, but as mixin modules they can also contain already implemented methods. Additionaly you can define preconditions/postconditions for methods specified in a protocol.
|
26
26
|
email: flori@ping.de
|
@@ -28,37 +28,39 @@ executables: []
|
|
28
28
|
|
29
29
|
extensions: []
|
30
30
|
|
31
|
-
extra_rdoc_files:
|
32
|
-
|
31
|
+
extra_rdoc_files:
|
32
|
+
- doc-main.txt
|
33
33
|
files:
|
34
|
-
-
|
34
|
+
- CHANGES
|
35
|
+
- COPYING
|
36
|
+
- Rakefile
|
37
|
+
- VERSION
|
38
|
+
- doc-main.txt
|
35
39
|
- examples
|
40
|
+
- examples/comparing.rb
|
41
|
+
- examples/enumerating.rb
|
42
|
+
- examples/game.rb
|
43
|
+
- examples/hello_world_patternitis.rb
|
36
44
|
- examples/indexing.rb
|
37
45
|
- examples/locking.rb
|
38
46
|
- examples/queue.rb
|
39
47
|
- examples/stack.rb
|
40
|
-
-
|
41
|
-
- examples/game.rb
|
42
|
-
- examples/comparing.rb
|
43
|
-
- examples/hello_world_patternitis.rb
|
44
|
-
- Rakefile
|
48
|
+
- install.rb
|
45
49
|
- lib
|
46
50
|
- lib/protocol
|
47
|
-
- lib/protocol/core.rb
|
48
51
|
- lib/protocol.rb
|
49
|
-
-
|
52
|
+
- lib/protocol/core.rb
|
53
|
+
- lib/protocol/version.rb
|
50
54
|
- make_doc.rb
|
55
|
+
- protocol.gemspec
|
51
56
|
- tests
|
52
57
|
- tests/test_protocol.rb
|
53
|
-
- CHANGES
|
54
|
-
- COPYING
|
55
58
|
has_rdoc: true
|
56
59
|
homepage: http://protocol.rubyforge.org
|
57
60
|
post_install_message:
|
58
61
|
rdoc_options:
|
59
|
-
- --
|
60
|
-
-
|
61
|
-
- -S
|
62
|
+
- --main
|
63
|
+
- doc-main.txt
|
62
64
|
require_paths:
|
63
65
|
- lib
|
64
66
|
required_ruby_version: !ruby/object:Gem::Requirement
|