1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* eval.c (set_trace_func): add rb_secure(4) to prevent adding

tracing function.

* lib/delegate.rb: document update from James Edward Gray II
  <james@grayproductions.net>.  [ruby-core:05942]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9317 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2005-09-26 13:59:47 +00:00
parent 54ca4e2269
commit 81b728c243
5 changed files with 332 additions and 46 deletions

View file

@ -1,3 +1,8 @@
Mon Sep 26 22:32:13 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (set_trace_func): add rb_secure(4) to prevent adding
tracing function.
Sun Sep 25 12:05:10 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* bin/erb: typo fixed.
@ -37,6 +42,11 @@ Sat Sep 24 08:38:07 2005 Minero Aoki <aamine@loveruby.net>
* test/fileutils/test_verbose.rb: new file.
Sat Sep 24 02:40:20 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
* lib/delegate.rb: document update from James Edward Gray II
<james@grayproductions.net>. [ruby-core:05942]
Thu Sep 22 23:36:24 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/mkmf.rb (find_executable0): default path if environment is not

1
eval.c
View file

@ -2545,6 +2545,7 @@ set_trace_func(obj, trace)
{
rb_event_hook_t *hook;
rb_secure(4);
if (NIL_P(trace)) {
trace_func = 0;
rb_remove_event_hook(call_trace_func);

View file

@ -13,6 +13,8 @@ cgi.rb
cgi
complex.rb
date.rb
delegate.rb
erb.rb
English.rb
fileutils.rb
find.rb

View file

@ -1,23 +1,125 @@
# Delegation class that delegates even methods defined in super class,
# which can not be covered with normal method_missing hack.
#
# Delegator is the abstract delegation class. Need to redefine
# `__getobj__' method in the subclass. SimpleDelegator is the
# concrete subclass for simple delegation.
# = delegate -- Support for the Delegation Pattern
#
# Usage:
# foo = Object.new
# foo2 = SimpleDelegator.new(foo)
# foo.hash == foo2.hash # => false
# Documentation by James Edward Gray II and Gavin Sinclair
#
# Foo = DelegateClass(Array)
# == Introduction
#
# class ExtArray<DelegateClass(Array)
# ...
# end
# This library provides three different ways to delegate method calls to an
# object. The easiest to use is SimpleDelegator. Pass an object to the
# constructor and all methods supported by the object will be delegated. This
# object can be changed later.
#
# Going a step further, the top level DelegateClass method allows you to easily
# setup delegation through class inheritance. This is considerably more
# flexible and thus probably the most common use for this library.
#
# Finally, if you need full control over the delegation scheme, you can inherit
# from the abstract class Delegator and customize as needed. (If you find
# yourself needing this control, have a look at _forwardable_, also in the
# standard library. It may suit your needs better.)
#
# == Notes
#
# Be advised, RDoc will not detect delegated methods.
#
# <b>delegate.rb provides full-class delegation via the
# DelegateClass() method. For single-method delegation via
# def_delegator(), see forwardable.rb.</b>
#
# == Examples
#
# === SimpleDelegator
#
# Here's a simple example that takes advantage of the fact that
# SimpleDelegator's delegation object can be changed at any time.
#
# class Stats
# def initialize
# @source = SimpleDelegator.new([])
# end
#
# def stats( records )
# @source.__setobj__(records)
#
# "Elements: #{@source.size}\n" +
# " Non-Nil: #{@source.compact.size}\n" +
# " Unique: #{@source.uniq.size}\n"
# end
# end
#
# s = Stats.new
# puts s.stats(%w{James Edward Gray II})
# puts
# puts s.stats([1, 2, 3, nil, 4, 5, 1, 2])
#
# <i>Prints:</i>
#
# Elements: 4
# Non-Nil: 4
# Unique: 4
#
# Elements: 8
# Non-Nil: 7
# Unique: 6
#
# === DelegateClass()
#
# Here's a sample of use from <i>tempfile.rb</i>.
#
# A _Tempfile_ object is really just a _File_ object with a few special rules
# about storage location and/or when the File should be deleted. That makes for
# an almost textbook perfect example of how to use delegation.
#
# class Tempfile < DelegateClass(File)
# # constant and class member data initialization...
#
# def initialize(basename, tmpdir=Dir::tmpdir)
# # build up file path/name in var tmpname...
#
# @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
#
# # ...
#
# super(@tmpfile)
#
# # below this point, all methods of File are supported...
# end
#
# # ...
# end
#
# === Delegator
#
# SimpleDelegator's implementation serves as a nice example here.
#
# class SimpleDelegator < Delegator
# def initialize(obj)
# super # pass obj to Delegator constructor, required
# @_sd_obj = obj # store obj for future use
# end
#
# def __getobj__
# @_sd_obj # return object we are delegating to, required
# end
#
# def __setobj__(obj)
# @_sd_obj = obj # change delegation object, a feature we're providing
# end
#
# # ...
# end
#
# Delegator is an abstract class used to build delegator pattern objects from
# subclasses. Subclasses should redefine \_\_getobj\_\_. For a concrete
# implementation, see SimpleDelegator.
#
class Delegator
#
# Pass in the _obj_ to delegate method calls to. All methods supported by
# _obj_ will be delegated to.
#
def initialize(obj)
preserved = ::Kernel.public_instance_methods(false)
preserved -= ["to_s","to_a","inspect","==","=~","==="]
@ -49,6 +151,7 @@ class Delegator
end
alias initialize_methods initialize
# Handles the magic of delegation through \_\_getobj\_\_.
def method_missing(m, *args)
target = self.__getobj__
unless target.respond_to?(m)
@ -57,23 +160,39 @@ class Delegator
target.__send__(m, *args)
end
#
# Checks for a method provided by this the delegate object by fowarding the
# call through \_\_getobj\_\_.
#
def respond_to?(m)
return true if super
return self.__getobj__.respond_to?(m)
end
#
# This method must be overridden by subclasses and should return the object
# method calls are being delegated to.
#
def __getobj__
raise NotImplementedError, "need to define `__getobj__'"
end
# Serialization support for the object returned by \_\_getobj\_\_.
def marshal_dump
__getobj__
end
# Reinitializes delegation from a serialized object.
def marshal_load(obj)
initialize_methods(obj)
end
end
#
# A concrete implementation of Delegator, this class provides the means to
# delegate all supported method calls to the object passed into the constructor
# and even to change the object being delegated to at a later time with
# \_\_setobj\_\_ .
#
class SimpleDelegator<Delegator
def initialize(obj)
@ -81,29 +200,57 @@ class SimpleDelegator<Delegator
@_sd_obj = obj
end
# Returns the current object method calls are being delegated to.
def __getobj__
@_sd_obj
end
#
# Changes the delegate object to _obj_.
#
# It's important to note that this does *not* cause SimpleDelegator's methods
# to change. Because of this, you probably only want to change delegation
# to objects of the same type as the original delegate.
#
# Here's an example of changing the delegation object.
#
# names = SimpleDelegator.new(%w{James Edward Gray II})
# puts names[1] # => Edward
# names.__setobj__(%w{Gavin Sinclair})
# puts names[1] # => Sinclair
#
def __setobj__(obj)
raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
@_sd_obj = obj
end
# Clone support for the object returned by \_\_getobj\_\_.
def clone
super
__setobj__(__getobj__.clone)
end
# Duplication support for the object returned by \_\_getobj\_\_.
def dup(obj)
super
__setobj__(__getobj__.dup)
end
end
# :stopdoc:
# backward compatibility ^_^;;;
Delegater = Delegator
SimpleDelegater = SimpleDelegator
# :startdoc:
#
# The primary interface to this library. Use to setup delegation when defining
# your class.
#
# class MyClass < DelegateClass( ClassToDelegateTo ) # Step 1
# def initiaize
# super(obj_of_ClassToDelegateTo) # Step 2
# end
# end
#
def DelegateClass(superclass)
klass = Class.new
@ -111,31 +258,31 @@ def DelegateClass(superclass)
methods -= ::Kernel.public_instance_methods(false)
methods |= ["to_s","to_a","inspect","==","=~","==="]
klass.module_eval {
def initialize(obj)
def initialize(obj) # :nodoc:
@_dc_obj = obj
end
def method_missing(m, *args)
def method_missing(m, *args) # :nodoc:
unless @_dc_obj.respond_to?(m)
super(m, *args)
end
@_dc_obj.__send__(m, *args)
end
def respond_to?(m)
def respond_to?(m) # :nodoc:
return true if super
return @_dc_obj.respond_to?(m)
end
def __getobj__
def __getobj__ # :nodoc:
@_dc_obj
end
def __setobj__(obj)
def __setobj__(obj) # :nodoc:
raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
@_dc_obj = obj
end
def clone
def clone # :nodoc:
super
__setobj__(__getobj__.clone)
end
def dup
def dup # :nodoc:
super
__setobj__(__getobj__.dup)
end
@ -159,6 +306,8 @@ def DelegateClass(superclass)
return klass
end
# :enddoc:
if __FILE__ == $0
class ExtArray<DelegateClass(Array)
def initialize()

View file

@ -1,45 +1,145 @@
# = forwardable - Support for the Delegation Pattern
#
# forwardable.rb -
# $Release Version: 1.1$
# $Revision$
# $Date$
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
# original definition by delegator.rb
# --
# Usage:
# $Release Version: 1.1$
# $Revision$
# $Date$
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
#
# class Foo
# Documentation by James Edward Gray II and Gavin Sinclair
#
# == Introduction
#
# This library allows you delegate method calls to an object, on a method by
# method basis. You can use Forwardable to setup this delegation at the class
# level, or SingleForwardable to handle it at the object level.
#
# == Notes
#
# Be advised, RDoc will not detect delegated methods.
#
# <b>forwardable.rb provides single-method delegation via the
# def_delegator() and def_delegators() methods. For full-class
# delegation via DelegateClass(), see delegate.rb.</b>
#
# == Examples
#
# === Forwardable
#
# Forwardable makes building a new class based on existing work, with a proper
# interface, almost trivial. We want to rely on what has come before obviously,
# but with delegation we can take just the methods we need and even rename them
# as appropriate. In many cases this is preferable to inheritance, which gives
# us the entire old interface, even if much of it isn't needed.
#
# class Queue
# extend Forwardable
#
# def_delegators("@out", "printf", "print")
# def_delegators(:@in, :gets)
# def_delegator(:@contents, :[], "content_at")
#
# def initialize
# @q = [ ] # prepare delegate object
# end
#
# # setup prefered interface, enq() and deq()...
# def_delegator :@q, :push, :enq
# def_delegator :@q, :shift, :deq
#
# # support some general Array methods that fit Queues well
# def_delegators :@q, :clear, :first, :push, :shift, :size
# end
# f = Foo.new
# f.printf ...
# f.gets
# f.content_at(1)
#
# q = Queue.new
# q.enq 1, 2, 3, 4, 5
# q.push 6
#
# q.shift # => 1
# while q.size > 0
# puts q.deq
# end
#
# q.enq "Ruby", "Perl", "Python"
# puts q.first
# q.clear
# puts q.first
#
# g = Goo.new
# g.extend SingleForwardable
# g.def_delegator("@out", :puts)
# g.puts ...
# <i>Prints:</i>
#
# 2
# 3
# 4
# 5
# 6
# Ruby
# nil
#
# === SingleForwardable
#
# printer = String.new
# printer.extend SingleForwardable # prepare object for delegation
# printer.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
# printer.puts "Howdy!"
#
# <i>Prints:</i>
#
# Howdy!
#
# The Forwardable module provides delegation of specified
# methods to a designated object, using the methods #def_delegator
# and #def_delegators.
#
# For example, say you have a class RecordCollection which
# contains an array <tt>@records</tt>. You could provide the lookup method
# #record_number(), which simply calls #[] on the <tt>@records</tt>
# array, like this:
#
# class RecordCollection
# extends Forwardable
# def_delegator :@records, :[], :record_number
# end
#
# Further, if you wish to provide the methods #size, #<<, and #map,
# all of which delegate to @records, this is how you can do it:
#
# class RecordCollection
# # extends Forwardable, but we did that above
# def_delegators :@records, :size, :<<, :map
# end
#
# Also see the example at forwardable.rb.
#
module Forwardable
@debug = nil
class<<self
# force Forwardable to show up in stack backtraces of delegated methods
attr_accessor :debug
end
#
# Shortcut for defining multiple delegator methods, but with no
# provision for using a different name. The following two code
# samples have the same effect:
#
# def_delegators :@records, :size, :<<, :map
#
# def_delegator :@records, :size
# def_delegator :@records, :<<
# def_delegator :@records, :map
#
# See the examples at Forwardable and forwardable.rb.
#
def def_instance_delegators(accessor, *methods)
for method in methods
def_instance_delegator(accessor, method)
end
end
#
# Defines a method _method_ which delegates to _obj_ (i.e. it calls
# the method of the same name in _obj_). If _new_name_ is
# provided, it is used as the name for the delegate method.
#
# See the examples at Forwardable and forwardable.rb.
#
def def_instance_delegator(accessor, method, ali = method)
accessor = accessor.id2name if accessor.kind_of?(Integer)
method = method.id2name if method.kind_of?(Integer)
@ -61,13 +161,41 @@ module Forwardable
alias def_delegator def_instance_delegator
end
#
# The SingleForwardable module provides delegation of specified
# methods to a designated object, using the methods #def_delegator
# and #def_delegators. This module is similar to Forwardable, but it works on
# objects themselves, instead of their defining classes.
#
# Also see the example at forwardable.rb.
#
module SingleForwardable
#
# Shortcut for defining multiple delegator methods, but with no
# provision for using a different name. The following two code
# samples have the same effect:
#
# single_forwardable.def_delegators :@records, :size, :<<, :map
#
# single_forwardable.def_delegator :@records, :size
# single_forwardable.def_delegator :@records, :<<
# single_forwardable.def_delegator :@records, :map
#
# See the example at forwardable.rb.
#
def def_singleton_delegators(accessor, *methods)
for method in methods
def_singleton_delegator(accessor, method)
end
end
#
# Defines a method _method_ which delegates to _obj_ (i.e. it calls
# the method of the same name in _obj_). If _new_name_ is
# provided, it is used as the name for the delegate method.
#
# See the example at forwardable.rb.
#
def def_singleton_delegator(accessor, method, ali = method)
accessor = accessor.id2name if accessor.kind_of?(Integer)
method = method.id2name if method.kind_of?(Integer)
@ -88,7 +216,3 @@ module SingleForwardable
alias def_delegators def_singleton_delegators
alias def_delegator def_singleton_delegator
end