clafamatt 1.0.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.
@@ -0,0 +1,269 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe Clafamatt::MacroModule do
4
+ before :each do
5
+ @class = Clafamatt::MacroModule
6
+ end
7
+
8
+ specify { @class.should be_a_kind_of(Module) }
9
+
10
+ describe "given a class to decorate" do
11
+ before :each do
12
+ @decorated_class = Class.new
13
+ @decorated_class_singleton = class << @decorated_class; self; end
14
+ @it = @class.find_or_create_for(@decorated_class)
15
+ end
16
+
17
+ it "should know its decorated class" do
18
+ @it.decorated_class.should equal(@decorated_class)
19
+ end
20
+
21
+ it "should be a singleton ancestor of its decorated class" do
22
+ @decorated_class_singleton.ancestors.should include(@it)
23
+ end
24
+
25
+ it "should match another MacroModule decorating the same class" do
26
+ @it.should == @class.new(@decorated_class)
27
+ end
28
+
29
+ it "should only decorate a given class once" do
30
+ macro_module = @class.find_or_create_for(@decorated_class)
31
+ macro_module.should equal(@it)
32
+ end
33
+ end
34
+
35
+ describe "decorating a child of a decorated class" do
36
+ before :each do
37
+ @parent_class = Class.new
38
+ @child_class = Class.new(@parent_class)
39
+ @parent_class_singleton = class << @parent_class; self; end
40
+ @child_class_singleton = class << @child_class; self; end
41
+ @parent_macro_module = @class.find_or_create_for(@parent_class)
42
+ @it = @class.find_or_create_for(@child_class)
43
+ end
44
+
45
+ it "should decorate the child with a new macro module" do
46
+ @it.should_not equal(@parent_macro_module)
47
+ end
48
+
49
+ it "should decorate the child with itself" do
50
+ @child_class_singleton.ancestors.should include(@it)
51
+ end
52
+
53
+ it "should decorate the child with the parent macro module" do
54
+ @child_class_singleton.ancestors.should include(@parent_macro_module)
55
+ end
56
+ end
57
+
58
+ describe "decorating a module" do
59
+ before :each do
60
+ @decorated_module = Module.new
61
+ @module_singleton = class << @decorated_module; self; end
62
+ @it = @class.find_or_create_for(@decorated_module)
63
+ end
64
+
65
+ it "should be one of the module's singleton ancestors" do
66
+ @module_singleton.ancestors.should include(@it)
67
+ end
68
+ end
69
+
70
+ describe "decorating a module included in a class" do
71
+ before :each do
72
+ @decorated_module = decorated_module = Module.new
73
+ @module_singleton = class << @decorated_module; self; end
74
+ @it = @class.find_or_create_for(@decorated_module)
75
+ @host_class = Class.new do
76
+ include decorated_module
77
+ end
78
+ @host_class_singleton = class << @host_class; self; end
79
+ @host_class_macro_module = @class.find_or_create_for(@host_class)
80
+ end
81
+
82
+ it "should be one of the class's singleton ancestors" do
83
+ @host_class_singleton.ancestors.should include(@it)
84
+ end
85
+
86
+ it "should not be the class's own macro module" do
87
+ @host_class_macro_module.should_not equal(@it)
88
+ end
89
+ end
90
+
91
+ describe "decorating a child class whose parent includes a decorated module" do
92
+ before :each do
93
+ @decorated_module = decorated_module = Module.new
94
+ @module_singleton = class << @decorated_module; self; end
95
+ @module_macro_module = @class.find_or_create_for(@decorated_module)
96
+ @host_class = Class.new do
97
+ include decorated_module
98
+ end
99
+ @host_class_singleton = class << @host_class; self; end
100
+ @host_class_macro_module = @class.find_or_create_for(@host_class)
101
+ @child_class = Class.new(@host_class)
102
+ @it = @class.find_or_create_for(@child_class)
103
+ @child_class_singleton = class << @child_class; self; end
104
+ @child_class_singleton_ancestors = @child_class_singleton.ancestors
105
+ end
106
+
107
+ it "should decorate the child with its own macro module" do
108
+ @it.should_not equal(@module_macro_module)
109
+ @it.should_not equal(@host_class_macro_module)
110
+ end
111
+
112
+ it "should decorate the child in the expected order" do
113
+ @child_class_singleton_ancestors.index(@it).should == 0
114
+ @child_class_singleton_ancestors.index(@host_class_macro_module).
115
+ should == 1
116
+ @child_class_singleton_ancestors.index(@module_macro_module).
117
+ should == 2
118
+ end
119
+ end
120
+ end
121
+
122
+ describe "Class Family Attributes:" do
123
+ before :each do
124
+ @shared = shared = Module.new do
125
+ include Clafamatt::Macros
126
+ def self.name; "Shared"; end
127
+ class_family_reader :mro # Module Read-Only
128
+ class_family_writer :mwo # Module Write-Only
129
+ class_family_accessor :mrw # Module Read/Write
130
+ end
131
+
132
+ @parent = Class.new do
133
+ include shared
134
+ def self.name; "Parent"; end
135
+ class_family_reader :ro1, :ro2 # Read-Only
136
+ class_family_writer :wo1, :wo2 # Write-Only
137
+ class_family_accessor :rw1, :rw2 # Read/Write
138
+ end
139
+
140
+ @child = Class.new(@parent) do
141
+ def self.name; "Child"; end
142
+ class_family_reader :cro # Child Read-Only
143
+ class_family_writer :cwo # Child Write-Only
144
+ class_family_accessor :crw # Child Read/Write
145
+ end
146
+ end
147
+
148
+ describe "a module with CFAs" do
149
+ before :each do
150
+ end
151
+
152
+ it "should have reader methods for all readable attributes" do
153
+ @shared.methods.should include("mro", "mrw")
154
+ end
155
+ it "should not have reader methods for write-only attributes" do
156
+ @shared.methods.should_not include("mwo")
157
+ end
158
+ it "should have writer methods for writable attributes" do
159
+ @shared.methods.should include("mwo=", "mrw=")
160
+ end
161
+ it "should not have writer methods for read-only attributes" do
162
+ @shared.methods.should_not include("mro=")
163
+ end
164
+
165
+ it "should default readable attributes to nil" do
166
+ @shared.mrw.should be_nil
167
+ @shared.mro.should be_nil
168
+ end
169
+
170
+ it "should be able to write to writable attributes" do
171
+ @shared.mrw = "klaatu"
172
+ @shared.mrw.should == "klaatu"
173
+ @shared.mwo = "nikto"
174
+ @shared.instance_variable_get(:@mwo).should == "nikto"
175
+ end
176
+
177
+ it "should be able to read readable attributes" do
178
+ @shared.instance_variable_set(:@mro, "klaatu")
179
+ @shared.mro.should == "klaatu"
180
+ @shared.instance_variable_set(:@mrw, "nikto")
181
+ @shared.mrw.should == "nikto"
182
+ end
183
+
184
+ end
185
+ describe "defined in a class" do
186
+ before :each do
187
+ end
188
+
189
+ it "should be able to write to included writable attributes" do
190
+ @parent.mrw = "klaatu"
191
+ @parent.mrw.should == "klaatu"
192
+ @parent.mwo = "nikto"
193
+ @parent.instance_variable_get(:@mwo).should == "nikto"
194
+ end
195
+
196
+ it "should not interfere with values in included module" do
197
+ @shared.mrw = "barada"
198
+ @parent.mrw = "klaatu"
199
+ @shared.mrw.should == "barada"
200
+ @parent.mrw.should == "klaatu"
201
+ end
202
+
203
+ it "should be able to read included readable attributes" do
204
+ @parent.instance_variable_set(:@mro, "klaatu")
205
+ @parent.mro.should == "klaatu"
206
+ @parent.instance_variable_set(:@mrw, "nikto")
207
+ @parent.mrw.should == "nikto"
208
+ end
209
+
210
+ it "should be able to read the class readable attributes" do
211
+ @parent.instance_variable_set(:@ro1, "oompah")
212
+ @parent.instance_variable_set(:@ro2, "loompah")
213
+ @parent.instance_variable_set(:@rw1, "doopidy")
214
+ @parent.instance_variable_set(:@rw2, "doo")
215
+ @parent.ro1.should == "oompah"
216
+ @parent.ro2.should == "loompah"
217
+ @parent.rw1.should == "doopidy"
218
+ @parent.rw2.should == "doo"
219
+ end
220
+
221
+ it "should be able to write the class writable attributes" do
222
+ @parent.wo1 = "oompah"
223
+ @parent.wo2 = "loompah"
224
+ @parent.rw1 = "doopidy"
225
+ @parent.rw2 = "doo"
226
+ @parent.instance_variable_get(:@wo1).should == "oompah"
227
+ @parent.instance_variable_get(:@wo2).should == "loompah"
228
+ @parent.instance_variable_get(:@rw1).should == "doopidy"
229
+ @parent.instance_variable_get(:@rw2).should == "doo"
230
+ end
231
+ end
232
+ describe "defined in a child class" do
233
+ it "should be able to read and write module-defined attributes" do
234
+ @child.mrw = "klaatu"
235
+ @child.mrw.should == "klaatu"
236
+ @shared.mrw.should be_nil
237
+ end
238
+ it "should be able to read and write parent-defined attributes" do
239
+ @child.rw1 = "barada"
240
+ @child.rw1.should == "barada"
241
+ @parent.rw1.should be_nil
242
+ end
243
+ it "should be able to read and write child-defined attributes" do
244
+ @child.crw = "nikto"
245
+ @child.crw.should == "nikto"
246
+ end
247
+ it "should not define child attributes on parent or module" do
248
+ lambda do
249
+ @shared.crw = "foo"
250
+ end.should raise_error(NoMethodError)
251
+ lambda do
252
+ @parent.crw = "foo"
253
+ end.should raise_error(NoMethodError)
254
+ end
255
+
256
+ it "should inherit values from module-defined attributes" do
257
+ @shared.mrw = "foo"
258
+ @parent.mrw.should == "foo"
259
+ @child.mrw.should == "foo"
260
+ end
261
+
262
+ it "should inherit values from parent-defined attributes" do
263
+ @parent.rw1 = "bar"
264
+ @child.rw1.should == "bar"
265
+ end
266
+ end
267
+ end
268
+
269
+ # EOF
@@ -0,0 +1,16 @@
1
+
2
+ require File.expand_path(
3
+ File.join(File.dirname(__FILE__), %w[.. lib clafamatt]))
4
+
5
+ Spec::Runner.configure do |config|
6
+ # == Mock Framework
7
+ #
8
+ # RSpec uses it's own mocking framework by default. If you prefer to
9
+ # use mocha, flexmock or RR, uncomment the appropriate line:
10
+ #
11
+ # config.mock_with :mocha
12
+ # config.mock_with :flexmock
13
+ # config.mock_with :rr
14
+ end
15
+
16
+ # EOF
@@ -0,0 +1,80 @@
1
+
2
+ begin
3
+ require 'bones/smtp_tls'
4
+ rescue LoadError
5
+ require 'net/smtp'
6
+ end
7
+ require 'time'
8
+
9
+ namespace :ann do
10
+
11
+ # A prerequisites task that all other tasks depend upon
12
+ task :prereqs
13
+
14
+ file PROJ.ann.file do
15
+ ann = PROJ.ann
16
+ puts "Generating #{ann.file}"
17
+ File.open(ann.file,'w') do |fd|
18
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
19
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
20
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
21
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
22
+ fd.puts
23
+ fd.puts("== DESCRIPTION")
24
+ fd.puts
25
+ fd.puts(PROJ.description)
26
+ fd.puts
27
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
28
+ fd.puts
29
+ ann.paragraphs.each do |p|
30
+ fd.puts "== #{p.upcase}"
31
+ fd.puts
32
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
33
+ fd.puts
34
+ end
35
+ fd.puts ann.text if ann.text
36
+ end
37
+ end
38
+
39
+ desc "Create an announcement file"
40
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
41
+
42
+ desc "Send an email announcement"
43
+ task :email => ['ann:prereqs', PROJ.ann.file] do
44
+ ann = PROJ.ann
45
+ from = ann.email[:from] || PROJ.email
46
+ to = Array(ann.email[:to])
47
+
48
+ ### build a mail header for RFC 822
49
+ rfc822msg = "From: #{from}\n"
50
+ rfc822msg << "To: #{to.join(',')}\n"
51
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
52
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
53
+ rfc822msg << "\n"
54
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
55
+ rfc822msg << "Message-Id: "
56
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
57
+ rfc822msg << File.read(ann.file)
58
+
59
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
60
+ ann.email[key]
61
+ end
62
+
63
+ params[3] = PROJ.email if params[3].nil?
64
+
65
+ if params[4].nil?
66
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
67
+ params[4] = STDIN.gets.chomp
68
+ end
69
+
70
+ ### send email
71
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
72
+ end
73
+ end # namespace :ann
74
+
75
+ desc 'Alias to ann:announcement'
76
+ task :ann => 'ann:announcement'
77
+
78
+ CLOBBER << PROJ.ann.file
79
+
80
+ # EOF
@@ -0,0 +1,20 @@
1
+
2
+ if HAVE_BONES
3
+
4
+ namespace :bones do
5
+
6
+ desc 'Show the PROJ open struct'
7
+ task :debug do |t|
8
+ atr = if t.application.top_level_tasks.length == 2
9
+ t.application.top_level_tasks.pop
10
+ end
11
+
12
+ if atr then Bones::Debug.show_attr(PROJ, atr)
13
+ else Bones::Debug.show PROJ end
14
+ end
15
+
16
+ end # namespace :bones
17
+
18
+ end # HAVE_BONES
19
+
20
+ # EOF
@@ -0,0 +1,192 @@
1
+
2
+ require 'find'
3
+ require 'rake/packagetask'
4
+ require 'rubygems/user_interaction'
5
+ require 'rubygems/builder'
6
+
7
+ module Bones
8
+ class GemPackageTask < Rake::PackageTask
9
+ # Ruby GEM spec containing the metadata for this package. The
10
+ # name, version and package_files are automatically determined
11
+ # from the GEM spec and don't need to be explicitly provided.
12
+ #
13
+ attr_accessor :gem_spec
14
+
15
+ # Tasks from the Bones gem directory
16
+ attr_reader :bones_files
17
+
18
+ # Create a GEM Package task library. Automatically define the gem
19
+ # if a block is given. If no block is supplied, then +define+
20
+ # needs to be called to define the task.
21
+ #
22
+ def initialize(gem_spec)
23
+ init(gem_spec)
24
+ yield self if block_given?
25
+ define if block_given?
26
+ end
27
+
28
+ # Initialization tasks without the "yield self" or define
29
+ # operations.
30
+ #
31
+ def init(gem)
32
+ super(gem.name, gem.version)
33
+ @gem_spec = gem
34
+ @package_files += gem_spec.files if gem_spec.files
35
+ @bones_files = []
36
+
37
+ local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
38
+ if !test(?e, local_setup)
39
+ Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
40
+ gem_spec.files = (gem_spec.files +
41
+ bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
42
+ end
43
+ end
44
+
45
+ # Create the Rake tasks and actions specified by this
46
+ # GemPackageTask. (+define+ is automatically called if a block is
47
+ # given to +new+).
48
+ #
49
+ def define
50
+ super
51
+ task :prereqs
52
+ task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
53
+ file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
54
+ when_writing("Creating GEM") {
55
+ chdir(package_dir_path) do
56
+ Gem::Builder.new(gem_spec).build
57
+ verbose(true) {
58
+ mv gem_file, "../#{gem_file}"
59
+ }
60
+ end
61
+ }
62
+ end
63
+
64
+ file package_dir_path => bones_files do
65
+ mkdir_p package_dir rescue nil
66
+ bones_files.each do |fn|
67
+ base_fn = File.join('tasks', File.basename(fn))
68
+ f = File.join(package_dir_path, base_fn)
69
+ fdir = File.dirname(f)
70
+ mkdir_p(fdir) if !File.exist?(fdir)
71
+ if File.directory?(fn)
72
+ mkdir_p(f)
73
+ else
74
+ raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
75
+ safe_ln(fn, f)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def gem_file
82
+ if @gem_spec.platform == Gem::Platform::RUBY
83
+ "#{package_name}.gem"
84
+ else
85
+ "#{package_name}-#{@gem_spec.platform}.gem"
86
+ end
87
+ end
88
+ end # class GemPackageTask
89
+ end # module Bones
90
+
91
+ namespace :gem do
92
+
93
+ PROJ.gem._spec = Gem::Specification.new do |s|
94
+ s.name = PROJ.name
95
+ s.version = PROJ.version
96
+ s.summary = PROJ.summary
97
+ s.authors = Array(PROJ.authors)
98
+ s.email = PROJ.email
99
+ s.homepage = Array(PROJ.url).first
100
+ s.rubyforge_project = PROJ.rubyforge.name
101
+
102
+ s.description = PROJ.description
103
+
104
+ PROJ.gem.dependencies.each do |dep|
105
+ s.add_dependency(*dep)
106
+ end
107
+
108
+ PROJ.gem.development_dependencies.each do |dep|
109
+ s.add_development_dependency(*dep)
110
+ end
111
+
112
+ s.files = PROJ.gem.files
113
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
114
+ s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
115
+
116
+ s.bindir = 'bin'
117
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
118
+ s.require_paths = dirs unless dirs.empty?
119
+
120
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
121
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
122
+ excl = Regexp.new(excl.join('|'))
123
+ rdoc_files = PROJ.gem.files.find_all do |fn|
124
+ case fn
125
+ when excl; false
126
+ when incl; true
127
+ else false end
128
+ end
129
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
130
+ s.extra_rdoc_files = rdoc_files
131
+ s.has_rdoc = true
132
+
133
+ if test ?f, PROJ.test.file
134
+ s.test_file = PROJ.test.file
135
+ else
136
+ s.test_files = PROJ.test.files.to_a
137
+ end
138
+
139
+ # Do any extra stuff the user wants
140
+ PROJ.gem.extras.each do |msg, val|
141
+ case val
142
+ when Proc
143
+ val.call(s.send(msg))
144
+ else
145
+ s.send "#{msg}=", val
146
+ end
147
+ end
148
+ end # Gem::Specification.new
149
+
150
+ Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
151
+ pkg.need_tar = PROJ.gem.need_tar
152
+ pkg.need_zip = PROJ.gem.need_zip
153
+ end
154
+
155
+ desc 'Show information about the gem'
156
+ task :debug => 'gem:prereqs' do
157
+ puts PROJ.gem._spec.to_ruby
158
+ end
159
+
160
+ desc 'Install the gem'
161
+ task :install => [:clobber, 'gem:package'] do
162
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
163
+
164
+ # use this version of the command for rubygems > 1.0.0
165
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
166
+ end
167
+
168
+ desc 'Uninstall the gem'
169
+ task :uninstall do
170
+ installed_list = Gem.source_index.find_name(PROJ.name)
171
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
172
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
173
+ end
174
+ end
175
+
176
+ desc 'Reinstall the gem'
177
+ task :reinstall => [:uninstall, :install]
178
+
179
+ desc 'Cleanup the gem'
180
+ task :cleanup do
181
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
182
+ end
183
+ end # namespace :gem
184
+
185
+
186
+ desc 'Alias to gem:package'
187
+ task :gem => 'gem:package'
188
+
189
+ task :clobber => 'gem:clobber_package'
190
+ remove_desc_for_task 'gem:clobber_package'
191
+
192
+ # EOF