deprecated 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/deprecated.rb +226 -0
- data/test/deprecated.rb +42 -0
- metadata +46 -0
data/lib/deprecated.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
#
|
2
|
+
# Deprecate - handle deprecating and executing deprecated code
|
3
|
+
#
|
4
|
+
# Version:: 1.0.0
|
5
|
+
# Author:: Erik Hollensbe
|
6
|
+
# License:: BSD
|
7
|
+
# Copyright:: Copyright (c) 2006 Erik Hollensbe
|
8
|
+
# Contact:: erik@hollensbe.org
|
9
|
+
#
|
10
|
+
# Deprecate is intended to ease the programmer's control over
|
11
|
+
# deprecating and handling deprecated code.
|
12
|
+
#
|
13
|
+
# Usage is simple:
|
14
|
+
#
|
15
|
+
# # require 'rubygems' if need be
|
16
|
+
# require 'deprecate'
|
17
|
+
#
|
18
|
+
# class Foo
|
19
|
+
# private
|
20
|
+
# # rename the original function and make it private
|
21
|
+
# def _monkey
|
22
|
+
# do stuff...
|
23
|
+
# end
|
24
|
+
# public
|
25
|
+
# # deprecate the function, this will create a 'monkey' method
|
26
|
+
# # that will call the deprecate warnings
|
27
|
+
# deprecate :monkey, :_monkey
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# The 'deprecate' call is injected into the 'Module' class at
|
31
|
+
# require-time. This allows all classes that are newly-created to
|
32
|
+
# access the 'deprecate' functionality.
|
33
|
+
#
|
34
|
+
# The call itself takes a list of symbols. Each pair is first the name
|
35
|
+
# of the original function, the second the name of the current,
|
36
|
+
# renamed function. Both are represented as symbols.
|
37
|
+
#
|
38
|
+
# Ex:
|
39
|
+
#
|
40
|
+
# # foo subroutine is generated to call _foo, and notify the user
|
41
|
+
# # when called.
|
42
|
+
# deprecate :foo, :_foo
|
43
|
+
#
|
44
|
+
# You can define as many symbols as you like on one line as
|
45
|
+
# deprecated, but for obvious reasons the length of the list must be
|
46
|
+
# even. In the case that it isn't, the 'deprecate' call will throw an
|
47
|
+
# exception of type 'DeprecatedError'.
|
48
|
+
#
|
49
|
+
# If you prefer to have more sugar in your syntax, the call
|
50
|
+
# understands arrays:
|
51
|
+
#
|
52
|
+
# deprecate [:foo, :_foo], [:bar, :_bar]
|
53
|
+
#
|
54
|
+
# And of course, you can make the call multiple times.
|
55
|
+
#
|
56
|
+
# Methods deprecated default to 'public'. This is due to a limitation
|
57
|
+
# in how Ruby handles permission definition. If you're aware of a
|
58
|
+
# workaround to this problem, please let me know.
|
59
|
+
#
|
60
|
+
# You can however change this by providing an optional leading
|
61
|
+
# parameter to the 'deprecate' call:
|
62
|
+
#
|
63
|
+
# * :public - set the created method to be public
|
64
|
+
# * :protected - set the created method to be protected
|
65
|
+
# * :private - set the created method to be private
|
66
|
+
#
|
67
|
+
# Note: It's highly recommended that you make your original methods
|
68
|
+
# private so that they cannot be accessed by outside code.
|
69
|
+
#
|
70
|
+
# Deprecate.set_action can change the default action (which is a
|
71
|
+
# warning printed to stderr) if you prefer. This is ideal for code
|
72
|
+
# sweeps where deprecated calls have to be removed. Please see the
|
73
|
+
# documentation for this method to get an idea of the options that are
|
74
|
+
# available.
|
75
|
+
#
|
76
|
+
#--
|
77
|
+
#
|
78
|
+
# The compilation of software known as deprecate.rb is distributed under the
|
79
|
+
# following terms:
|
80
|
+
# Copyright (C) 2005-2006 Erik Hollensbe. All rights reserved.
|
81
|
+
#
|
82
|
+
# Redistribution and use in source form, with or without
|
83
|
+
# modification, are permitted provided that the following conditions
|
84
|
+
# are met:
|
85
|
+
#
|
86
|
+
# 1. Redistributions of source code must retain the above copyright
|
87
|
+
# notice, this list of conditions and the following disclaimer:
|
88
|
+
#
|
89
|
+
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
90
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
91
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
92
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
93
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
94
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
95
|
+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
96
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
97
|
+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
98
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
99
|
+
# SUCH DAMAGE.
|
100
|
+
#
|
101
|
+
#++
|
102
|
+
|
103
|
+
module Deprecate
|
104
|
+
|
105
|
+
CALLER_REGEX = /\`([^\']+)/
|
106
|
+
|
107
|
+
#
|
108
|
+
# set_action defines the action that will be taken when code marked
|
109
|
+
# deprecated is encountered. There are several stock options:
|
110
|
+
#
|
111
|
+
# * :warn -- print a warning message to stderr (default)
|
112
|
+
# * :die -- warn and then terminate the program with error level -1
|
113
|
+
# * :throw -- throw a DeprecatedError with the message
|
114
|
+
#
|
115
|
+
# If a proc is passed instead, it will execute that instead. This
|
116
|
+
# procedure is passed a single argument, which is the name (NOT the
|
117
|
+
# symbol) of the method in Class#meth syntax that was called. This
|
118
|
+
# does not interrupt the calling process (unless you do so
|
119
|
+
# yourself).
|
120
|
+
#
|
121
|
+
# The second argument is the message provided to warnings and throw
|
122
|
+
# errors and so on. This message is a sprintf-like formatted string
|
123
|
+
# that takes one argument, which is the Class#meth name as a string.
|
124
|
+
# This message is not used when you define your own procedure.
|
125
|
+
#
|
126
|
+
# Note: ALL code that is marked deprecated will behave in the manner
|
127
|
+
# that was set at the last call to set_action.
|
128
|
+
#
|
129
|
+
# Ex:
|
130
|
+
#
|
131
|
+
# # throws with the error message saying: "FIXME: Class#meth"
|
132
|
+
# Deprecate.set_action(:throw, "FIXME: %s")
|
133
|
+
#
|
134
|
+
# # emails your boss everytime you run deprecated code
|
135
|
+
# Deprecate.set_action proc do |msg|
|
136
|
+
# f = IO.popen('mail boss@company -s "Joe still hasn't fixed %s"' % msg, 'w')
|
137
|
+
# f.puts("Sorry, I still haven't fixed %s, please stop making me go to meetings.\n" % msg)
|
138
|
+
# f.close
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
|
142
|
+
@@action = nil
|
143
|
+
|
144
|
+
def Deprecate.action
|
145
|
+
return @@action
|
146
|
+
end
|
147
|
+
|
148
|
+
def Deprecate.set_action(action, message="%s is deprecated.")
|
149
|
+
if action.kind_of? Proc
|
150
|
+
@@action = action
|
151
|
+
return
|
152
|
+
end
|
153
|
+
|
154
|
+
case action
|
155
|
+
when :warn
|
156
|
+
@@action = proc do |msg|
|
157
|
+
warn(message % msg)
|
158
|
+
end
|
159
|
+
when :die
|
160
|
+
@@action = proc do |msg|
|
161
|
+
warn(message % msg)
|
162
|
+
exit(-1)
|
163
|
+
end
|
164
|
+
when :throw
|
165
|
+
@@action = proc do |msg|
|
166
|
+
raise DeprecatedError.new(message % msg)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
#
|
173
|
+
# This is the class of the errors that the 'Deprecate' module will
|
174
|
+
# throw if the action type is set to ':throw'.
|
175
|
+
#
|
176
|
+
# See Deprecate.set_action for more information.
|
177
|
+
#
|
178
|
+
class DeprecatedError < Exception
|
179
|
+
attr_reader :message
|
180
|
+
def initialize(msg=nil)
|
181
|
+
@message = msg
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Start - inject the 'deprecated' method into the 'Module' class and
|
187
|
+
# set the default action to warn.
|
188
|
+
#
|
189
|
+
|
190
|
+
Module.send(:define_method, :deprecate,
|
191
|
+
proc do |*args|
|
192
|
+
args.flatten!
|
193
|
+
if args.length
|
194
|
+
|
195
|
+
permission = :public
|
196
|
+
|
197
|
+
if args.length % 2 != 0
|
198
|
+
permission = args.shift
|
199
|
+
end
|
200
|
+
|
201
|
+
while args.length > 0
|
202
|
+
syms = args.slice! 0, 2
|
203
|
+
|
204
|
+
if syms.include? nil
|
205
|
+
raise DeprecatedError.new("Invalid number of arguments passed to 'deprecated' function")
|
206
|
+
end
|
207
|
+
|
208
|
+
define_method(syms[0]) do |*sendparams|
|
209
|
+
Deprecate.action.call(self.class.to_s + '#' + syms[0].to_s)
|
210
|
+
self.send(syms[1], *sendparams)
|
211
|
+
end
|
212
|
+
|
213
|
+
case permission
|
214
|
+
when :public
|
215
|
+
public(syms[0])
|
216
|
+
when :protected
|
217
|
+
protected(syms[0])
|
218
|
+
when :private
|
219
|
+
private(syms[0])
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end)
|
225
|
+
|
226
|
+
Deprecate.set_action(:warn)
|
data/test/deprecated.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'lib/deprecate.rb'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
# this class is used to test the deprecate functionality
|
7
|
+
class DummyClass
|
8
|
+
deprecate :monkey, :_monkey
|
9
|
+
|
10
|
+
def _monkey
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
# we want exceptions for testing here.
|
17
|
+
Deprecate.set_action(:throw)
|
18
|
+
|
19
|
+
class DeprecateTest < Test::Unit::TestCase
|
20
|
+
def set_action_builder
|
21
|
+
d = DummyClass.new
|
22
|
+
test = true
|
23
|
+
begin
|
24
|
+
d.monkey
|
25
|
+
test = false
|
26
|
+
rescue DeprecatedError => e
|
27
|
+
test = e.message == "DummyClass#monkey is deprecated."
|
28
|
+
end
|
29
|
+
|
30
|
+
return test
|
31
|
+
end
|
32
|
+
|
33
|
+
# this inadvertently tests the deprecate functionality as well...
|
34
|
+
def test_set_action
|
35
|
+
|
36
|
+
assert(set_action_builder, "Deprecate.set_action message/:throw test")
|
37
|
+
|
38
|
+
Deprecate.set_action(proc { |msg| raise DeprecatedError.new("#{msg} is deprecated.") })
|
39
|
+
|
40
|
+
assert(set_action_builder, "Deprecate.set_action custom proc test")
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: deprecated
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2006-02-15 00:00:00 -08:00
|
8
|
+
summary: An easy way to handle deprecating and conditionally running deprecated code
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: erik@hollensbe.org
|
12
|
+
homepage:
|
13
|
+
rubyforge_project: deprecated
|
14
|
+
description:
|
15
|
+
autorequire: deprecated
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Erik Hollensbe
|
30
|
+
files:
|
31
|
+
- lib/deprecated.rb
|
32
|
+
- test/deprecated.rb
|
33
|
+
test_files:
|
34
|
+
- test/deprecated.rb
|
35
|
+
rdoc_options: []
|
36
|
+
|
37
|
+
extra_rdoc_files: []
|
38
|
+
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
requirements: []
|
44
|
+
|
45
|
+
dependencies: []
|
46
|
+
|