anise 0.4.0 → 0.5.0
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/.ruby +41 -0
- data/APACHE2.txt +204 -0
- data/COPYING.rdoc +17 -0
- data/HISTORY.rdoc +37 -0
- data/{README → README.rdoc} +31 -15
- data/VERSION +1 -1
- data/lib/anise.rb +37 -15
- data/lib/anise.yml +41 -0
- data/lib/anise/annotation.rb +94 -108
- data/lib/anise/annotator.rb +42 -46
- data/lib/anise/attribute.rb +58 -107
- data/lib/anise/module.rb +19 -0
- data/{spec/01_annotations.rd → qed/01_annotations.qed} +1 -0
- data/{spec/04_callbacks.rd → qed/02_annotation_added.rdoc} +1 -1
- data/qed/03_attributes.rdoc +16 -0
- data/qed/04_annotator.rdoc +49 -0
- data/qed/applique/ae.rb +1 -0
- data/qed/toplevel/01_annotations.qed +30 -0
- data/qed/toplevel/03_attributes.rdoc +20 -0
- data/test/test_anise.rb +4 -6
- data/test/test_anise_toplevel.rb +4 -6
- data/test/test_annotator.rb +3 -5
- data/test/test_annotator_toplevel.rb +3 -5
- data/test/test_attribute.rb +1 -1
- data/test/test_attribute_toplevel.rb +2 -2
- metadata +78 -67
- data/COPYING +0 -166
- data/HISTORY +0 -22
- data/MANIFEST +0 -35
- data/RELEASE +0 -13
- data/meta/abstract +0 -1
- data/meta/authors +0 -1
- data/meta/contact +0 -1
- data/meta/created +0 -1
- data/meta/homepage +0 -1
- data/meta/license +0 -1
- data/meta/require +0 -1
- data/meta/summary +0 -1
data/lib/anise.yml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
---
|
2
|
+
spec_version: 1.0.0
|
3
|
+
replaces: []
|
4
|
+
|
5
|
+
loadpath:
|
6
|
+
- lib
|
7
|
+
name: anise
|
8
|
+
repositories: {}
|
9
|
+
|
10
|
+
conflicts: []
|
11
|
+
|
12
|
+
engine_check: []
|
13
|
+
|
14
|
+
title: Anise
|
15
|
+
contact: trans <transfire@gmail.com>
|
16
|
+
resources:
|
17
|
+
code: http://github.com/rubyworks/anise
|
18
|
+
mail: http://groups.google.com/group/rubyworks-mailinglist
|
19
|
+
home: http://rubyworks.github.com/anise
|
20
|
+
maintainers: []
|
21
|
+
|
22
|
+
requires:
|
23
|
+
- group:
|
24
|
+
- test
|
25
|
+
name: qed
|
26
|
+
version: 0+
|
27
|
+
- group:
|
28
|
+
- build
|
29
|
+
name: syckle
|
30
|
+
version: 0+
|
31
|
+
manifest: MANIFEST
|
32
|
+
version: 0.5.0
|
33
|
+
licenses:
|
34
|
+
- Apache 2.0
|
35
|
+
copyright: Copyright (c) 2008 Thomas Sawyer
|
36
|
+
authors:
|
37
|
+
- Thomas Sawyer
|
38
|
+
organization: Rubyworks
|
39
|
+
description: Anise is an Annotation System for the Ruby programming language. Unlike most other annotations systems it is not a comment-based or macro-based system that sits over-and-above the rest of the code. Rather, Anise is a dynamic annotations system operating at runtime.
|
40
|
+
summary: Dynamic Annotation System
|
41
|
+
created: "2008-02-21"
|
data/lib/anise/annotation.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
module Anise
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# They are simply data. But you can put them to use. For instance
|
10
|
-
# an attribute validator might check for an annotation called
|
11
|
-
# :valid and test against it.
|
3
|
+
# The Annotate module is the core of the Anise system. It provides the
|
4
|
+
# framework for annotating class or module related objects, typically
|
5
|
+
# symbols representing methods, with arbitrary metadata. These annotations
|
6
|
+
# do not do anything in themselves. They are simply data. But they can be
|
7
|
+
# put to good use. For instance an attribute validator might check for an
|
8
|
+
# annotation called :valid and test against it.
|
12
9
|
#
|
13
10
|
# == Synopsis
|
14
11
|
#
|
@@ -48,12 +45,12 @@ module Anise
|
|
48
45
|
# Or, we could even annotate the class itself.
|
49
46
|
#
|
50
47
|
# class X
|
51
|
-
# include Anise::
|
48
|
+
# include Anise::Annotate
|
52
49
|
#
|
53
50
|
# ann self, :valid => lambda{ |x| x.is_a?(Enumerable) }
|
54
51
|
# end
|
55
52
|
#
|
56
|
-
#
|
53
|
+
# Although annotations are arbitrary they are tied to the class or
|
57
54
|
# module they are defined against.
|
58
55
|
#
|
59
56
|
#--
|
@@ -66,125 +63,114 @@ module Anise
|
|
66
63
|
#
|
67
64
|
# TODO: The ann(x).name notation is kind of nice. Would like to add that
|
68
65
|
# back-in if reasonable. This would require @annotations to be an
|
69
|
-
# OpenHash or OpenObject rather than just a Hash.
|
66
|
+
# OpenHash or OpenObject rather than just a Hash though.
|
70
67
|
#++
|
71
68
|
module Annotation
|
72
69
|
|
70
|
+
#
|
71
|
+
|
73
72
|
def self.append_features(base)
|
74
|
-
|
75
|
-
|
76
|
-
elsif base == ::Module
|
77
|
-
unless ::Module < Annotation
|
78
|
-
super
|
79
|
-
end
|
80
|
-
else
|
81
|
-
base.extend self
|
82
|
-
end
|
73
|
+
base.extend ClassMethods
|
74
|
+
super(base)
|
83
75
|
end
|
84
76
|
|
85
|
-
#
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
77
|
+
# Anise::Annotations Domain Language.
|
78
|
+
|
79
|
+
module ClassMethods
|
80
|
+
|
81
|
+
# Lookup an annotation. Unlike +annotations[ref]+
|
82
|
+
# this provides a complete annotation <i>heritage</i>,
|
83
|
+
# pulling annotations of the same reference name
|
84
|
+
# from ancestor classes and modules.
|
85
|
+
|
86
|
+
def annotation(ref=nil)
|
87
|
+
return(@annotations ||= {}) if ref.nil?
|
88
|
+
|
89
|
+
ref = ref.to_sym
|
90
|
+
ann = {}
|
91
|
+
ancestors.reverse_each do |anc|
|
92
|
+
next unless anc < Annotation
|
93
|
+
if h = anc.annotations[ref]
|
94
|
+
ann.merge!(h)
|
95
|
+
end
|
100
96
|
end
|
97
|
+
return ann
|
101
98
|
end
|
102
|
-
return ann
|
103
|
-
#ancs = ancestors.select{ |a| a.is_a?(Annotations) }
|
104
|
-
#ancs.inject({}) do |memo, ancestor|
|
105
|
-
# ancestor.annotations[ref] ||= {}
|
106
|
-
# ancestor.annotations[ref].merge(memo)
|
107
|
-
#end
|
108
|
-
end
|
109
99
|
|
110
|
-
|
111
|
-
alias_method :annotations, :annotation
|
100
|
+
# Plural alias for #annotation.
|
112
101
|
|
113
|
-
|
114
|
-
#
|
115
|
-
#def annotations
|
116
|
-
# #$annotations[self]
|
117
|
-
# @annotations ||= {}
|
118
|
-
#end
|
102
|
+
alias_method :annotations, :annotation
|
119
103
|
|
120
|
-
|
121
|
-
#
|
122
|
-
def ann(ref, keys_or_class=nil, keys=nil)
|
123
|
-
return annotation(ref) unless keys_or_class or keys
|
124
|
-
|
125
|
-
if Class === keys_or_class
|
126
|
-
keys ||= {}
|
127
|
-
keys[:class] = keys_or_class
|
128
|
-
else
|
129
|
-
keys = keys_or_class
|
130
|
-
end
|
104
|
+
# Set or read annotations.
|
131
105
|
|
132
|
-
|
133
|
-
ref
|
134
|
-
keys = keys.inject({}){ |h,(k,v)| h[k.to_sym] = v; h} #rekey
|
135
|
-
annotations[ref] ||= {}
|
136
|
-
annotations[ref].update(keys)
|
137
|
-
# callback
|
138
|
-
annotation_added(ref)
|
139
|
-
else
|
140
|
-
key = keys.to_sym
|
141
|
-
annotation(ref)[key]
|
142
|
-
end
|
143
|
-
end
|
106
|
+
def ann(ref, keys_or_class=nil, keys=nil)
|
107
|
+
return annotation(ref) unless keys_or_class or keys
|
144
108
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
unless keys_or_class or keys
|
152
|
-
return annotations[ref] ||= {}
|
153
|
-
end
|
109
|
+
if Class === keys_or_class
|
110
|
+
keys ||= {}
|
111
|
+
keys[:class] = keys_or_class
|
112
|
+
else
|
113
|
+
keys = keys_or_class
|
114
|
+
end
|
154
115
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
116
|
+
if Hash === keys
|
117
|
+
ref = ref.to_sym
|
118
|
+
keys = keys.inject({}){ |h,(k,v)| h[k.to_sym] = v; h} #rekey
|
119
|
+
annotations[ref] ||= {}
|
120
|
+
annotations[ref].update(keys)
|
121
|
+
# callback
|
122
|
+
annotation_added(ref) #if method_defined?(:annotation_added)
|
123
|
+
else
|
124
|
+
key = keys.to_sym
|
125
|
+
annotation(ref)[key]
|
126
|
+
end
|
160
127
|
end
|
161
128
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
#
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
129
|
+
# To change an annotation's value in place for a given class or module
|
130
|
+
# it first must be duplicated, otherwise the change may effect annotations
|
131
|
+
# in the class or module's ancestors.
|
132
|
+
|
133
|
+
def ann!(ref, keys_or_class=nil, keys=nil)
|
134
|
+
#return annotation(ref) unless keys_or_class or keys
|
135
|
+
unless keys_or_class or keys
|
136
|
+
return annotations[ref] ||= {}
|
137
|
+
end
|
138
|
+
|
139
|
+
if Class === keys_or_class
|
140
|
+
keys ||= {}
|
141
|
+
keys[:class] = keys_or_class
|
142
|
+
else
|
143
|
+
keys = keys_or_class
|
144
|
+
end
|
145
|
+
|
146
|
+
if Hash === keys
|
147
|
+
ref = ref.to_sym
|
148
|
+
keys = keys.inject({}){ |h,(k,v)| h[k.to_sym] = v; h} #rekey
|
149
|
+
annotations[ref] ||= {}
|
150
|
+
annotations[ref].update(keys)
|
151
|
+
# callback
|
152
|
+
annotation_added(ref) #if method_defined?(:annotation_added)
|
153
|
+
else
|
154
|
+
key = keys.to_sym
|
155
|
+
annotations[ref] ||= {}
|
156
|
+
begin
|
157
|
+
annotations[ref][key] = annotation(ref)[key].dup
|
158
|
+
rescue TypeError
|
159
|
+
annotations[ref][key] = annotation(ref)[key]
|
160
|
+
end
|
176
161
|
end
|
177
162
|
end
|
178
|
-
end
|
179
163
|
|
180
|
-
|
181
|
-
|
182
|
-
|
164
|
+
# Callback method. This method is called for each new annotation.
|
165
|
+
|
166
|
+
def annotation_added(name)
|
167
|
+
super if defined?(super)
|
168
|
+
end
|
169
|
+
|
183
170
|
end
|
184
171
|
|
185
172
|
end
|
186
173
|
|
187
174
|
end
|
188
175
|
|
189
|
-
# 2006-11-07
|
190
|
-
# Copyright (c) 2005, 2008 TigerOps
|
176
|
+
# Copyright (c) 2006-11-07 Thomas Sawyer
|
data/lib/anise/annotator.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
module Anise
|
2
|
-
require 'anise/annotation
|
2
|
+
require 'anise/annotation'
|
3
3
|
|
4
4
|
# = Annotator
|
5
5
|
#
|
6
|
-
# Annotator allows for the creation of
|
7
|
-
#
|
6
|
+
# The Annotator module allows for the creation of <i>method annotations</i>
|
7
|
+
# which attach to the next method defined.
|
8
|
+
#
|
9
|
+
# This idiom of annotator-before-definition was popularized by
|
10
|
+
# Rake's desc/task pair. The Annotator module makes it very easy
|
11
|
+
# to add similar capabilites to any program.
|
8
12
|
#
|
9
13
|
# require 'anise/annotator'
|
10
14
|
#
|
@@ -22,66 +26,58 @@ module Anise
|
|
22
26
|
#
|
23
27
|
# X.ann(:see, :doc) #=> "See what I mean?"
|
24
28
|
#
|
25
|
-
#
|
26
|
-
# Rake's desc/task pair. Annotator makes it very easy to add
|
27
|
-
# similar capabilites to any program.
|
28
|
-
#
|
29
|
-
# The library uses the #method_added callback, so be sure to
|
29
|
+
# Note that the library uses the #method_added callback, so be sure to
|
30
30
|
# respect good practices of calling +super+ if you need to override
|
31
31
|
# this method while using Annotator.
|
32
32
|
#
|
33
|
-
|
33
|
+
#--
|
34
|
+
# TODO: Allow annotators to be inherited via module mixins.
|
34
35
|
#
|
36
|
+
# TODO: Ensure thread-safety of <code>@_pending_annotations</code> variable.
|
37
|
+
#++
|
35
38
|
module Annotator
|
36
39
|
|
40
|
+
#
|
37
41
|
def self.append_features(base)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
@pending_annotations = []
|
53
|
-
#super if defined?(super)
|
54
|
-
end
|
42
|
+
Annotation.append_features(base) #unless base.is_a?(Annotation)
|
43
|
+
base.extend ClassMethods
|
44
|
+
super(base)
|
45
|
+
end
|
46
|
+
|
47
|
+
module ClassMethods
|
48
|
+
|
49
|
+
# Define an annotator.
|
50
|
+
def annotator(name, &block)
|
51
|
+
(class << self; self; end).module_eval do
|
52
|
+
define_method(name) do |*args|
|
53
|
+
@_pending_annotations ||= []
|
54
|
+
@_pending_annotations << [name, args, block]
|
55
55
|
end
|
56
|
-
super
|
57
56
|
end
|
58
|
-
else
|
59
|
-
base.extend Annotation #unless base.is_a?(Annotation)
|
60
|
-
base.extend self
|
61
57
|
end
|
62
|
-
end
|
63
58
|
|
64
|
-
|
65
|
-
(
|
66
|
-
|
67
|
-
|
68
|
-
|
59
|
+
# When a method is added, run all pending annotations.
|
60
|
+
def method_added(sym)
|
61
|
+
@_pending_annotations ||= []
|
62
|
+
@_pending_annotations.each do |name, args, block|
|
63
|
+
if block
|
64
|
+
block.call(sym, *args)
|
65
|
+
else
|
66
|
+
if args.size == 1
|
67
|
+
ann(sym, name=>args.first)
|
68
|
+
else
|
69
|
+
ann(sym, name=>args)
|
70
|
+
end
|
71
|
+
end
|
69
72
|
end
|
73
|
+
@_pending_annotations = []
|
74
|
+
super if defined?(super)
|
70
75
|
end
|
71
|
-
end
|
72
76
|
|
73
|
-
def method_added(sym)
|
74
|
-
@pending_annotations ||= []
|
75
|
-
@pending_annotations.each do |name, args|
|
76
|
-
ann sym, name => args
|
77
|
-
end
|
78
|
-
@pending_annotations = []
|
79
|
-
super if defined?(super)
|
80
77
|
end
|
81
78
|
|
82
79
|
end
|
83
80
|
|
84
81
|
end
|
85
82
|
|
86
|
-
# Copyright (c) 2005,
|
87
|
-
|
83
|
+
# Copyright (c) 2005,2011 Thomas Sawyer
|
data/lib/anise/attribute.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
#require 'facets/inheritor' # remove dependency
|
2
|
-
|
3
1
|
module Anise
|
2
|
+
#require 'facets/inheritor' # removed dependency
|
4
3
|
require 'anise/annotation'
|
4
|
+
require 'anise/module'
|
5
5
|
|
6
6
|
# = Annotated Attributes
|
7
7
|
#
|
@@ -22,35 +22,20 @@ module Anise
|
|
22
22
|
# See annotation.rb for more information.
|
23
23
|
#
|
24
24
|
# NOTE: This library was designed to be backward compatible with
|
25
|
-
#
|
25
|
+
# the standard versions of the same methods.
|
26
26
|
#
|
27
27
|
module Attribute
|
28
28
|
|
29
|
+
#
|
29
30
|
def self.append_features(base)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
annotatable_attribute_method_for_module(:attr)
|
39
|
-
annotatable_attribute_method_for_module(:attr_reader)
|
40
|
-
annotatable_attribute_method_for_module(:attr_writer)
|
41
|
-
annotatable_attribute_method_for_module(:attr_accessor)
|
42
|
-
annotatable_attribute_method_for_module(:attr_setter) if defined?(attr_setter)
|
43
|
-
end
|
44
|
-
else
|
45
|
-
base.extend Annotation
|
46
|
-
base.extend Attribute
|
47
|
-
base = (class << base; self; end)
|
48
|
-
#inheritor :instance_attributes, [], :|
|
49
|
-
annotatable_attribute_method(base, :attr)
|
50
|
-
annotatable_attribute_method(base, :attr_reader)
|
51
|
-
annotatable_attribute_method(base, :attr_writer)
|
52
|
-
annotatable_attribute_method(base, :attr_accessor)
|
53
|
-
annotatable_attribute_method(base, :attr_setter) if defined?(attr_setter)
|
31
|
+
super(base)
|
32
|
+
Annotation.append_features(base)
|
33
|
+
base.extend ClassMethods #Attribute
|
34
|
+
|
35
|
+
#inheritor :instance_attributes, [], :|
|
36
|
+
base_class = (class << base; self; end)
|
37
|
+
base_class.attribute_methods.each do |attr_method|
|
38
|
+
annotatable_attribute_method(base_class, attr_method)
|
54
39
|
end
|
55
40
|
end
|
56
41
|
|
@@ -90,99 +75,65 @@ module Anise
|
|
90
75
|
end
|
91
76
|
end
|
92
77
|
|
93
|
-
#
|
94
|
-
|
95
|
-
::Module.module_eval do
|
96
|
-
alias_method "__#{attr_method_name}", attr_method_name
|
97
|
-
|
98
|
-
define_method(attr_method_name) do |*args|
|
99
|
-
|
100
|
-
args.flatten!
|
101
|
-
|
102
|
-
harg={}; while args.last.is_a?(Hash)
|
103
|
-
harg.update(args.pop)
|
104
|
-
end
|
105
|
-
|
106
|
-
raise ArgumentError if args.empty? and harg.empty?
|
107
|
-
|
108
|
-
if args.empty? # hash mode
|
109
|
-
harg.each { |a,h| __send__(attr_method_name,a,h) }
|
110
|
-
else
|
111
|
-
klass = harg[:class] = args.pop if args.last.is_a?(Class)
|
112
|
-
|
113
|
-
__send__("__#{attr_method_name}", *args)
|
114
|
-
|
115
|
-
args.each{|a| ann(a.to_sym,harg)}
|
116
|
-
|
117
|
-
instance_attributes!.concat(args) #merge!
|
118
|
-
|
119
|
-
# Use this callback to customize for your needs.
|
120
|
-
if respond_to?(:attr_callback)
|
121
|
-
attr_callback(self, args, harg)
|
122
|
-
end
|
78
|
+
# Anise::Attributes Doman Language.
|
79
|
+
module ClassMethods
|
123
80
|
|
124
|
-
|
125
|
-
|
81
|
+
# Instance attributes, including inherited attributes.
|
82
|
+
def instance_attributes
|
83
|
+
a = []
|
84
|
+
ancestors.each do |anc|
|
85
|
+
next unless anc < Attribute
|
86
|
+
if x = anc.instance_attributes!
|
87
|
+
a |= x
|
126
88
|
end
|
127
89
|
end
|
90
|
+
return a
|
128
91
|
end
|
129
|
-
end
|
130
92
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
ancestors.each do |anc|
|
135
|
-
next unless anc.is_a?(Attribute)
|
136
|
-
if x = anc.instance_attributes!
|
137
|
-
a |= x
|
138
|
-
end
|
93
|
+
# Local instance attributes.
|
94
|
+
def instance_attributes!
|
95
|
+
@instance_attributes ||= []
|
139
96
|
end
|
140
|
-
return a
|
141
|
-
end
|
142
97
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
#
|
159
|
-
def classified_attributes
|
160
|
-
instance_attributes.find_all do |a|
|
161
|
-
self.ann(a, :class)
|
98
|
+
# Return list of attributes that have a :class annotation.
|
99
|
+
#
|
100
|
+
# class MyClass
|
101
|
+
# attr_accessor :test
|
102
|
+
# attr_accessor :name, String, :doc => 'Hello'
|
103
|
+
# attr_accessor :age, Fixnum
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# MyClass.instance_attributes # => [:test, :name, :age, :body]
|
107
|
+
# MyClass.classified_attributes # => [:name, :age]
|
108
|
+
#
|
109
|
+
def classified_attributes
|
110
|
+
instance_attributes.find_all do |a|
|
111
|
+
self.ann(a, :class)
|
112
|
+
end
|
162
113
|
end
|
163
|
-
end
|
164
114
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
115
|
+
# This define a simple adjustment to #attr to allow it to handle the boolean argument and
|
116
|
+
# to be able to accept attributes. It's backward compatible and is not needed for Ruby 1.9
|
117
|
+
# which gets rid of the secondary argument.
|
118
|
+
#
|
119
|
+
def attr(*args)
|
120
|
+
args.flatten!
|
121
|
+
case args.last
|
122
|
+
when TrueClass
|
123
|
+
args.pop
|
124
|
+
attr_accessor(*args)
|
125
|
+
when FalseClass, NilClass
|
126
|
+
args.pop
|
127
|
+
attr_reader(*args)
|
128
|
+
else
|
129
|
+
attr_reader(*args)
|
130
|
+
end
|
180
131
|
end
|
132
|
+
|
181
133
|
end
|
182
134
|
|
183
135
|
end
|
184
136
|
|
185
137
|
end
|
186
138
|
|
187
|
-
# Copyright (c) 2005, 2008
|
188
|
-
|
139
|
+
# Copyright (c) 2005, 2008 Thomas Sawyer
|