comp_tree 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,11 @@
1
1
 
2
2
  = CompTree ChangeLog
3
3
 
4
+ == Version 0.7.2
5
+
6
+ * check for number of threads < 1
7
+ * new benchmarks indicate previous algorithm was faster after all
8
+
4
9
  == Version 0.7.1
5
10
 
6
11
  * rename README to README.rdoc for github display
data/README.rdoc CHANGED
@@ -1,5 +1,11 @@
1
1
 
2
- = CompTree -- Parallel Computation Tree
2
+ = CompTree
3
+
4
+ * http://comptree.rubyforge.org
5
+
6
+ == Summary
7
+
8
+ Automatic parallelism and lazy evaluation.
3
9
 
4
10
  == Synopsis
5
11
 
@@ -36,15 +42,24 @@
36
42
  # => 63
37
43
  end
38
44
 
39
- == Notes
45
+ == Install
46
+
47
+ % gem install comp_tree
48
+
49
+ Or for the (non-gem) .tgz package,
50
+
51
+ % ruby install.rb [--uninstall]
52
+
53
+ == Description
54
+
55
+ A computation tree for pure functional programming in Ruby.
40
56
 
41
57
  The user should have a basic understanding of <em>functional
42
58
  programming</em> (see for example
43
59
  http://en.wikipedia.org/wiki/Functional_programming) and the meaning
44
60
  of <em>side effects</em>.
45
61
 
46
- CompTree requires the user to adopt a functional style. Every
47
- function you define must explicitly depend on the data it uses.
62
+ Every function you define must explicitly depend on the data it uses.
48
63
 
49
64
  #
50
65
  # BAD example: depending on state -- offset not listed as a parameter
@@ -76,14 +91,6 @@ Note however it is OK affect a state as long as <em>no other function
76
91
  depends on that state</em>. This is the principle under which
77
92
  +comp_tree+ parallelizes Rake tasks (http://drake.rubyforge.org).
78
93
 
79
- == Install
80
-
81
- % gem install comp_tree
82
-
83
- Or for the (non-gem) .tgz package,
84
-
85
- % ruby install.rb [--uninstall]
86
-
87
94
  == Links
88
95
 
89
96
  * Download: http://rubyforge.org/frs/?group_id=6917
data/Rakefile CHANGED
@@ -1,3 +1,8 @@
1
+ $LOAD_PATH.unshift "devel"
1
2
 
2
- # rakelib generates tasks
3
+ require 'jumpstart'
3
4
 
5
+ Jumpstart.new('comp_tree') do |s|
6
+ s.developer('James M. Lawrence', 'quixoticsycophant@gmail.com')
7
+ s.rubyforge_user = "quix"
8
+ end
@@ -0,0 +1,580 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'rubygems'
4
+ require 'ostruct'
5
+ require 'rbconfig'
6
+
7
+ require 'rake/gempackagetask'
8
+ require 'rake/contrib/sshpublisher'
9
+ require 'rake/clean'
10
+
11
+ require 'rdoc/rdoc'
12
+
13
+ require "jumpstart/ruby"
14
+ require "jumpstart/lazy_attribute"
15
+ require "jumpstart/simple_installer"
16
+
17
+ class Jumpstart
18
+ include LazyAttribute
19
+
20
+ def not_provided(param)
21
+ raise "#{self.class}##{param} not provided"
22
+ end
23
+
24
+ def must_define(*params)
25
+ params.each { |param|
26
+ attribute param do
27
+ not_provided(param)
28
+ end
29
+ }
30
+ end
31
+
32
+ def initialize(project_name)
33
+ must_define :authors, :email
34
+
35
+ attribute :name do
36
+ project_name
37
+ end
38
+
39
+ attribute :version do
40
+ str = "VERSION"
41
+ begin
42
+ require name
43
+ if mod = Object.const_get(to_camel_case(name))
44
+ if mod.constants.include? str
45
+ mod.const_get str
46
+ else
47
+ raise
48
+ end
49
+ else
50
+ raise
51
+ end
52
+ rescue Exception
53
+ "0.0.0"
54
+ end
55
+ end
56
+
57
+ attribute :rubyforge_name do
58
+ name.gsub('_', '')
59
+ end
60
+
61
+ attribute :rubyforge_user do
62
+ email.first[%r!^.*(?=@)!]
63
+ end
64
+
65
+ attribute :readme_file do
66
+ "README.rdoc"
67
+ end
68
+
69
+ attribute :history_file do
70
+ "CHANGES.rdoc"
71
+ end
72
+
73
+ attribute :doc_dir do
74
+ "documentation"
75
+ end
76
+
77
+ attribute :spec_files do
78
+ Dir["spec/*_{spec,example}.rb"]
79
+ end
80
+
81
+ attribute :test_files do
82
+ Dir["test/test_*.rb"]
83
+ end
84
+
85
+ attribute :rcov_dir do
86
+ "coverage"
87
+ end
88
+
89
+ attribute :spec_output do
90
+ "spec.html"
91
+ end
92
+
93
+ %w[gem tgz].map { |ext|
94
+ attribute ext.to_sym do
95
+ "pkg/#{name}-#{version}.#{ext}"
96
+ end
97
+ }
98
+
99
+ attribute :rcov_options do
100
+ # workaround for the default rspec task
101
+ Dir["*"].select { |f| File.directory? f }.inject(Array.new) { |acc, dir|
102
+ if dir == "lib"
103
+ acc
104
+ else
105
+ acc + ["--exclude", dir + "/"]
106
+ end
107
+ } + ["--text-report"]
108
+ end
109
+
110
+ attribute :readme_file do
111
+ "README.rdoc"
112
+ end
113
+
114
+ attribute :files do
115
+ `git ls-files`.split("\n")
116
+ end
117
+
118
+ attribute :rdoc_files do
119
+ Dir["lib/**/*.rb"]
120
+ end
121
+
122
+ attribute :extra_rdoc_files do
123
+ [readme_file]
124
+ end
125
+
126
+ attribute :rdoc_options do
127
+ [
128
+ "--main",
129
+ readme_file,
130
+ "--title",
131
+ "#{name}: #{summary}",
132
+ ] + (files - rdoc_files).inject(Array.new) { |acc, file|
133
+ acc + ["--exclude", file]
134
+ }
135
+ end
136
+
137
+ attribute :browser do
138
+ if Config::CONFIG["host"] =~ %r!darwin!
139
+ app = %w[Firefox Safari].map { |t|
140
+ "/Applications/#{t}.app"
141
+ }.select { |t|
142
+ File.exist? t
143
+ }.first
144
+ if app
145
+ ["open", app]
146
+ else
147
+ not_provided(:browser)
148
+ end
149
+ else
150
+ "firefox"
151
+ end
152
+ end
153
+
154
+ attribute :gemspec do
155
+ Gem::Specification.new { |g|
156
+ g.has_rdoc = true
157
+ %w[
158
+ name
159
+ authors
160
+ email
161
+ summary
162
+ version
163
+ description
164
+ files
165
+ extra_rdoc_files
166
+ rdoc_options
167
+ ].each { |param|
168
+ value = send(param) and (
169
+ g.send("#{param}=", value)
170
+ )
171
+ }
172
+
173
+ if rubyforge_name
174
+ g.rubyforge_project = rubyforge_name
175
+ end
176
+
177
+ if url
178
+ g.homepage = url
179
+ end
180
+ }
181
+ end
182
+
183
+ attribute :readme_contents do
184
+ File.read(readme_file)
185
+ end
186
+
187
+ attribute :sections do
188
+ begin
189
+ pairs = Hash[*readme_contents.split(%r!^== (\w+).*?$!)[1..-1]].map {
190
+ |section, contents|
191
+ [section.downcase, contents.strip]
192
+ }
193
+ Hash[*pairs.flatten]
194
+ rescue
195
+ nil
196
+ end
197
+ end
198
+
199
+ attribute :description_section do
200
+ "description"
201
+ end
202
+
203
+ attribute :summary_section do
204
+ "summary"
205
+ end
206
+
207
+ attribute :description_sentences do
208
+ 1
209
+ end
210
+
211
+ attribute :summary_sentences do
212
+ 1
213
+ end
214
+
215
+ [:summary, :description].each { |section|
216
+ attribute section do
217
+ begin
218
+ sections[send("#{section}_section")].
219
+ gsub("\n", " ").
220
+ split(%r!\.\s*!m).
221
+ first(send("#{section}_sentences")).
222
+ join(". ") << "."
223
+ rescue
224
+ if section == :description
225
+ summary
226
+ end
227
+ end
228
+ end
229
+ }
230
+
231
+ attribute :url do
232
+ begin
233
+ readme_contents.match(%r!^\* (\S+)!)[1]
234
+ rescue
235
+ "http://#{rubyforge_name}.rubyforge.org"
236
+ end
237
+ end
238
+
239
+ yield self
240
+
241
+ self.class.instance_methods(false).select { |t|
242
+ t.to_s =~ %r!\Adefine_!
243
+ }.each { |method_name|
244
+ send(method_name)
245
+ }
246
+ end
247
+
248
+ def developer(name, email)
249
+ self.authors rescue self.authors = []
250
+ self.email rescue self.email = []
251
+ self.authors << name
252
+ self.email << email
253
+ end
254
+
255
+ def author=(name)
256
+ self.authors = [name]
257
+ end
258
+
259
+ def define_clean
260
+ task :clean do
261
+ Rake::Task[:clobber].invoke
262
+ end
263
+ end
264
+
265
+ def define_package
266
+ task :package => :clean
267
+ Rake::GemPackageTask.new(gemspec) { |t|
268
+ t.need_tar = true
269
+ }
270
+ end
271
+
272
+ def define_spec
273
+ unless spec_files.empty?
274
+ require 'spec/rake/spectask'
275
+
276
+ desc "run specs"
277
+ Spec::Rake::SpecTask.new('spec') do |t|
278
+ t.spec_files = spec_files
279
+ end
280
+
281
+ desc "run specs with text output"
282
+ Spec::Rake::SpecTask.new('text_spec') do |t|
283
+ t.spec_files = spec_files
284
+ t.spec_opts = ['-fs']
285
+ end
286
+
287
+ desc "run specs with html output"
288
+ Spec::Rake::SpecTask.new('full_spec') do |t|
289
+ t.spec_files = spec_files
290
+ t.rcov = true
291
+ t.rcov_opts = rcov_options
292
+ t.spec_opts = ["-fh:#{spec_output}"]
293
+ end
294
+
295
+ desc "run full_spec then open browser"
296
+ task :show_spec => :full_spec do
297
+ open_browser(spec_output, rcov_dir + "/index.html")
298
+ end
299
+
300
+ desc "run specs individually"
301
+ task :spec_deps do
302
+ run_ruby_on_each(*spec_files)
303
+ end
304
+
305
+ task :prerelease => :spec_deps
306
+ task :default => :spec
307
+
308
+ CLEAN.include spec_output
309
+ end
310
+ end
311
+
312
+ def define_test
313
+ unless test_files.empty?
314
+ desc "run tests"
315
+ task :test do
316
+ test_files.each { |file|
317
+ require file
318
+ }
319
+ end
320
+
321
+ desc "run tests with rcov"
322
+ task :full_test do
323
+ verbose(false) {
324
+ sh("rcov", "-o", rcov_dir, "--text-report",
325
+ *(test_files + rcov_options)
326
+ )
327
+ }
328
+ end
329
+
330
+ desc "run full_test then open browser"
331
+ task :show_test => :full_test do
332
+ open_browser(rcov_dir + "/index.html")
333
+ end
334
+
335
+ desc "run tests individually"
336
+ task :test_deps do
337
+ run_ruby_on_each(*test_files)
338
+ end
339
+
340
+ task :prerelease => :test_deps
341
+ task :default => :test
342
+
343
+ CLEAN.include rcov_dir
344
+ end
345
+ end
346
+
347
+ def define_doc
348
+ desc "run rdoc"
349
+ task :doc => :clean_doc do
350
+ args = (
351
+ gemspec.rdoc_options +
352
+ gemspec.require_paths.clone +
353
+ gemspec.extra_rdoc_files +
354
+ ["-o", doc_dir]
355
+ ).flatten.map { |t| t.to_s }
356
+ RDoc::RDoc.new.document args
357
+ end
358
+
359
+ task :clean_doc do
360
+ # normally rm_rf, but mimic rake/clean output
361
+ rm_r(doc_dir) rescue nil
362
+ end
363
+
364
+ desc "run rdoc then open browser"
365
+ task :show_doc => :doc do
366
+ open_browser(doc_dir + "/index.html")
367
+ end
368
+
369
+ task :rdoc => :doc
370
+ task :clean => :clean_doc
371
+ end
372
+
373
+ def define_publish
374
+ desc "upload docs"
375
+ task :publish => [:clean_doc, :doc] do
376
+ Rake::SshDirPublisher.new(
377
+ "#{rubyforge_user}@rubyforge.org",
378
+ "/var/www/gforge-projects/#{rubyforge_name}",
379
+ doc_dir
380
+ ).upload
381
+ end
382
+ end
383
+
384
+ def define_install
385
+ desc "direct install (no gem)"
386
+ task :install do
387
+ SimpleInstaller.new.run([])
388
+ end
389
+
390
+ desc "direct uninstall (no gem)"
391
+ task :uninstall do
392
+ SimpleInstaller.new.run(["--uninstall"])
393
+ end
394
+ end
395
+
396
+ def define_debug
397
+ runner = Class.new do
398
+ def comment_src_dst(on)
399
+ on ? ["", "#"] : ["#", ""]
400
+ end
401
+
402
+ def comment_regions(on, contents, start)
403
+ src, dst = comment_src_dst(on)
404
+ contents.gsub(%r!^(\s+)#{src}#{start}.*?^\1#{src}(\}|end)!m) { |chunk|
405
+ indent = $1
406
+ chunk.gsub(%r!^#{indent}#{src}!, "#{indent}#{dst}")
407
+ }
408
+ end
409
+
410
+ def comment_lines(on, contents, start)
411
+ src, dst = comment_src_dst(on)
412
+ contents.gsub(%r!^(\s*)#{src}#{start}!) {
413
+ $1 + dst + start
414
+ }
415
+ end
416
+
417
+ def debug_info(enable)
418
+ Find.find("lib", "test") { |path|
419
+ if path =~ %r!\.rb\Z!
420
+ replace_file(path) { |contents|
421
+ result = comment_regions(!enable, contents, "debug")
422
+ comment_lines(!enable, result, "trace")
423
+ }
424
+ end
425
+ }
426
+ end
427
+ end
428
+
429
+ desc "enable debug and trace calls"
430
+ task :debug_on do
431
+ runner.new.debug_info(true)
432
+ end
433
+
434
+ desc "disable debug and trace calls"
435
+ task :debug_off do
436
+ runner.new.debug_info(false)
437
+ end
438
+ end
439
+
440
+ def define_columns
441
+ desc "check for columns > 80"
442
+ task :check_columns do
443
+ Dir["**/*.rb"].each { |file|
444
+ File.read(file).scan(%r!^.{81}!) { |match|
445
+ unless match =~ %r!http://!
446
+ raise "#{file} greater than 80 columns: #{match}"
447
+ end
448
+ }
449
+ }
450
+ end
451
+ task :prerelease => :check_columns
452
+ end
453
+
454
+ def define_comments
455
+ task :comments do
456
+ file = "comments.txt"
457
+ write_file(file) {
458
+ Array.new.tap { |result|
459
+ (["Rakefile"] + Dir["**/*.{rb,rake}"]).each { |file|
460
+ File.read(file).scan(%r!\#[^\{].*$!) { |match|
461
+ result << match
462
+ }
463
+ }
464
+ }.join("\n")
465
+ }
466
+ CLEAN.include file
467
+ end
468
+ end
469
+
470
+ def define_check_directory
471
+ task :check_directory do
472
+ unless `git status` =~ %r!nothing to commit \(working directory clean\)!
473
+ raise "Directory not clean"
474
+ end
475
+ end
476
+ end
477
+
478
+ def define_ping
479
+ task :ping do
480
+ %w[github.com rubyforge.org].each { |server|
481
+ cmd = "ping " + (
482
+ if Config::CONFIG["host"] =~ %r!darwin!
483
+ "-c2 #{server}"
484
+ else
485
+ "#{server} 2 2"
486
+ end
487
+ )
488
+ unless `#{cmd}` =~ %r!0% packet loss!
489
+ raise "No ping for #{server}"
490
+ end
491
+ }
492
+ end
493
+ end
494
+
495
+ def git(*args)
496
+ sh("git", *args)
497
+ end
498
+
499
+ def rubyforge(command, file)
500
+ sh(
501
+ "rubyforge",
502
+ command,
503
+ rubyforge_name,
504
+ rubyforge_name,
505
+ version.to_s,
506
+ file
507
+ )
508
+ end
509
+
510
+ def define_release
511
+ task :prerelease => [:clean, :check_directory, :ping]
512
+
513
+ task :finish_release do
514
+ gem_md5, tgz_md5 = [gem, tgz].map { |file|
515
+ "#{file}.md5".tap { |md5|
516
+ sh("md5sum #{file} > #{md5}")
517
+ }
518
+ }
519
+
520
+ rubyforge("add_release", gem)
521
+ [gem_md5, tgz, tgz_md5].each { |file|
522
+ rubyforge("add_file", file)
523
+ }
524
+
525
+ git("tag", "#{name}-" + version.to_s)
526
+ git(*%w(push --tags origin master))
527
+ end
528
+
529
+ task :release => [:prerelease, :package, :publish, :finish_release]
530
+ end
531
+
532
+ def define_debug_gem
533
+ task :debug_gem do
534
+ puts gemspec.to_ruby
535
+ end
536
+ end
537
+
538
+ def open_browser(*files)
539
+ sh(*([browser].flatten + files))
540
+ end
541
+
542
+ def replace_file(file)
543
+ old_contents = File.read(file)
544
+ yield(old_contents).tap { |new_contents|
545
+ if old_contents != new_contents
546
+ File.open(file, "wb") { |output|
547
+ output.print(new_contents)
548
+ }
549
+ end
550
+ }
551
+ end
552
+
553
+ def write_file(file)
554
+ yield.tap { |contents|
555
+ File.open(file, "wb") { |out|
556
+ out.print(contents)
557
+ }
558
+ }
559
+ end
560
+
561
+ def run_ruby_on_each(*files)
562
+ files.each { |file|
563
+ Ruby.run_or_raise("-w", file)
564
+ }
565
+ end
566
+
567
+ def to_camel_case(str)
568
+ str.split('_').map { |t| t.capitalize }.join
569
+ end
570
+
571
+ unless respond_to? :tap
572
+ class Object
573
+ def tap
574
+ yield self
575
+ self
576
+ end
577
+ end
578
+ end
579
+ end
580
+