dynaload 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY ADDED
@@ -0,0 +1,11 @@
1
+ ---
2
+ 0.2.1:
3
+ - the verisioned and non-versioned files in lib were out of sync. this just
4
+ fixes that
5
+ 0.2.0:
6
+ - massively simplified the code to the core set of functionality i've found
7
+ most useful.
8
+ 0.1.1:
9
+ - efficiency tweak. thanks akonsu <akonsu@gmail.com>
10
+ 0.1.0:
11
+ - added ability to export objects
data/README ADDED
@@ -0,0 +1,133 @@
1
+ URIS
2
+ http://raa.ruby-lang.org/project/dynaload/
3
+ http://www.codeforpeople.com/lib/ruby/dynaload/
4
+
5
+ NAME
6
+ dynaload.rb
7
+
8
+ DESCRIPTION
9
+ a simple toolset to make dynamic loading of classes and modules easier
10
+
11
+ imagine you have many files containing the following kinds of class
12
+ definitions
13
+
14
+ class ClassName
15
+ def method
16
+ end
17
+ end
18
+
19
+ you'd like to be able to dynamically load the file defining a class,
20
+ instantiate the class(es) defined in it, and and run ClassName#method on an
21
+ instance WITHOUT knowing beforhand which class will be loaded. dyanload
22
+ solves this problem. classes wishing to be dyanloaded do the following
23
+
24
+ ----------------
25
+ file: 1.rb
26
+ ----------------
27
+ require 'dynaload'
28
+
29
+ class ClassOne
30
+ def answer
31
+ 42
32
+ end
33
+ end
34
+
35
+ Dynaload::export ClassOne, 'answer' => true
36
+
37
+ ----------------
38
+ file: 2.rb
39
+ ----------------
40
+ require 'dynaload'
41
+
42
+ class ClassTwo
43
+ def answer
44
+ 42
45
+ end
46
+ end
47
+
48
+ Dynaload::export ClassTwo, 'answer' => true
49
+
50
+ the options hash ('answer' => true) may contain anything deemed useful and is
51
+ entirely dedicated for user data
52
+
53
+ now both files can be dynaloaded, the classes instantiated, and methods called
54
+ with
55
+
56
+ require 'dynaload'
57
+
58
+ %w( 1.rb 2.rb ).each do |file|
59
+ loaded = Dynaload::dynaload file
60
+
61
+ klasses = loaded.select{|klass, attributes| attributes['answer'] == true}
62
+
63
+ klasses.each do |klass, attributes|
64
+ object = klass::new
65
+ p object.answer
66
+ end
67
+ end
68
+
69
+ any class or module defined in a file can be exported and is then available
70
+ via the Dynaload interface. for instance:
71
+
72
+ class C
73
+ module M
74
+ class B
75
+ Dynaload::export B
76
+ end
77
+ end
78
+ end
79
+ Dynaload::export C
80
+
81
+ is valid and exports only the classes C and B - not C::M.
82
+
83
+ the concept works best with modules as the exported quantities and loading
84
+ within an anonymous wrapper module (the default) to protect the namespace.
85
+ eg.
86
+
87
+ ----------------
88
+ file: 1.rb
89
+ ----------------
90
+
91
+ require 'dynaload'
92
+
93
+ module FooJob
94
+ def run
95
+ ...
96
+ end
97
+ end
98
+
99
+ Dynaload::export FooJob
100
+
101
+ ----------------
102
+ file: 2.rb
103
+ ----------------
104
+
105
+ require 'dynaload'
106
+
107
+ module BarJob
108
+ def run
109
+ ...
110
+ end
111
+ end
112
+
113
+ Dynaload::export BarJob
114
+
115
+ loading is done (by default) in an anonymous module so neither FooJob or
116
+ BarJob is introduced into the caller's namespace:
117
+
118
+ require 'dynaload'
119
+
120
+ loaded = Dynaload::dynaload('1.rb') | Dynaload::dynaload('2.rb')
121
+
122
+ modules = loaded.modules
123
+
124
+ # here neither FooJob or BarJob are polluting namespace
125
+
126
+
127
+
128
+ SAMPLES/DOCS
129
+ see samples/*
130
+
131
+
132
+ CAVEATS
133
+ this software is experimental and quite simple
@@ -0,0 +1,23 @@
1
+ lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
2
+
3
+ require 'rubygems'
4
+
5
+ Gem::Specification::new do |spec|
6
+ spec.name = lib
7
+ spec.version = version
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.summary = lib
10
+
11
+ spec.files = Dir::glob "**/**"
12
+ spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
13
+
14
+ spec.require_path = "lib"
15
+ spec.autorequire = lib
16
+
17
+ spec.has_rdoc = File::exist? "doc"
18
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
19
+
20
+ spec.author = "Ara T. Howard"
21
+ spec.email = "ara.t.howard@noaa.gov"
22
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
23
+ end
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if f =~ %r/\.lnk/
40
+ path.push f
41
+ dir |= [File.dirname(f)]
42
+ end
43
+ for f in dir
44
+ next if f == "."
45
+ next if f == "CVS"
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ for f in path
49
+ next if (/\~$/ =~ f)
50
+ next if (/^\./ =~ File.basename(f))
51
+ unless bin
52
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
+ else
54
+ from = File.join(srcdir, f)
55
+ to = File.join(destdir, f)
56
+ shebangify(from) do |sf|
57
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
58
+ $deferr.printf "chmod %04o %s\n", mode, to
59
+ File::install(sf, to, mode, false)
60
+ end
61
+ end
62
+ end
63
+ #}}}
64
+ end
65
+ def shebangify f
66
+ #{{{
67
+ open(f) do |fd|
68
+ buf = fd.read 42
69
+ if buf =~ %r/^\s*#\s*!.*ruby/o
70
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
+ begin
72
+ fd.rewind
73
+ ftmp.puts "#!#{ $ruby }"
74
+ while((buf = fd.read(8192)))
75
+ ftmp.write buf
76
+ end
77
+ ftmp.close
78
+ yield ftmp.path
79
+ ensure
80
+ ftmp.close!
81
+ end
82
+ else
83
+ yield f
84
+ end
85
+ end
86
+ #}}}
87
+ end
88
+ def ARGV.switch
89
+ #{{{
90
+ return nil if self.empty?
91
+ arg = self.shift
92
+ return nil if arg == '--'
93
+ if arg =~ /^-(.)(.*)/
94
+ return arg if $1 == '-'
95
+ raise 'unknown switch "-"' if $2.index('-')
96
+ self.unshift "-#{$2}" if $2.size > 0
97
+ "-#{$1}"
98
+ else
99
+ self.unshift arg
100
+ nil
101
+ end
102
+ #}}}
103
+ end
104
+ def ARGV.req_arg
105
+ #{{{
106
+ self.shift || raise('missing argument')
107
+ #}}}
108
+ end
109
+ def linkify d, linked = []
110
+ #--{{{
111
+ if test ?d, d
112
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
+ versioned.each do |v|
114
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
+ lnk = nil
116
+ begin
117
+ if test ?l, dst
118
+ lnk = "#{ dst }.lnk"
119
+ puts "#{ dst } -> #{ lnk }"
120
+ File::rename dst, lnk
121
+ end
122
+ unless test ?e, dst
123
+ puts "#{ src } -> #{ dst }"
124
+ File::copy src, dst
125
+ linked << dst
126
+ end
127
+ ensure
128
+ if lnk
129
+ at_exit do
130
+ puts "#{ lnk } -> #{ dst }"
131
+ File::rename lnk, dst
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ linked
138
+ #--}}}
139
+ end
140
+
141
+
142
+ #
143
+ # main program
144
+ #
145
+
146
+ libdir = $site_libdir
147
+ bindir = $bindir
148
+ no_linkify = false
149
+ linked = nil
150
+ help = false
151
+
152
+ usage = <<-usage
153
+ #{ File::basename $0 }
154
+ -d, --destdir <destdir>
155
+ -l, --libdir <libdir>
156
+ -b, --bindir <bindir>
157
+ -r, --ruby <ruby>
158
+ -n, --no_linkify
159
+ -s, --sudo
160
+ -h, --help
161
+ usage
162
+
163
+ begin
164
+ while switch = ARGV.switch
165
+ case switch
166
+ when '-d', '--destdir'
167
+ libdir = ARGV.req_arg
168
+ when '-l', '--libdir'
169
+ libdir = ARGV.req_arg
170
+ when '-b', '--bindir'
171
+ bindir = ARGV.req_arg
172
+ when '-r', '--ruby'
173
+ $ruby = ARGV.req_arg
174
+ when '-n', '--no_linkify'
175
+ no_linkify = true
176
+ when '-s', '--sudo'
177
+ sudo = 'sudo'
178
+ when '-h', '--help'
179
+ help = true
180
+ else
181
+ raise "unknown switch #{switch.dump}"
182
+ end
183
+ end
184
+ rescue
185
+ STDERR.puts $!.to_s
186
+ STDERR.puts usage
187
+ exit 1
188
+ end
189
+
190
+ if help
191
+ STDOUT.puts usage
192
+ exit
193
+ end
194
+
195
+ unless no_linkify
196
+ linked = linkify('lib') + linkify('bin')
197
+ end
198
+
199
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
200
+
201
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
202
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
203
+
204
+ if linked
205
+ linked.each{|path| File::rm_f path}
206
+ end
@@ -0,0 +1,67 @@
1
+ module Dynaload
2
+ VERSION = '0.2.0'
3
+
4
+ require "sync"
5
+
6
+ extend Sync_m
7
+
8
+ class ExportError < ::StandardError; end
9
+
10
+ class Exported < ::Hash
11
+ THINGS = %w( classes modules objects )
12
+ def initialize *a, &b
13
+ super
14
+ THINGS.each{|thing| self[thing] = []}
15
+ end
16
+ def method_missing m, *a, &b
17
+ self["#{ m }"] || super
18
+ end
19
+ def empty?
20
+ THINGS.map{|thing| self[thing].empty?}.all?
21
+ end
22
+ def clear!
23
+ THINGS.each{|thing| self[thing].clear}
24
+ self
25
+ end
26
+ def export thing, attributes
27
+ case thing
28
+ when Class
29
+ (self['classes'] << [thing, attributes]).uniq!
30
+ when Module
31
+ (self['modules'] << [thing, attributes]).uniq!
32
+ else
33
+ (self['objects'] << [thing, attributes]).uniq!
34
+ end
35
+ self
36
+ end
37
+ def dup
38
+ THINGS.inject({}){|h,t| h[t] = self[t].dup}
39
+ end
40
+ end
41
+
42
+ class << self
43
+ def exported
44
+ synchronize{ @exported ||= Exported::new }
45
+ end
46
+
47
+ def export thing, attributes = {}
48
+ synchronize{ exported.export thing, attributes }
49
+ end
50
+
51
+ def dynaload path, opts = {"wrap" => true}
52
+ ret = nil
53
+ synchronize do
54
+ begin
55
+ @exported = Exported::new
56
+ ::Kernel::load(path, opts["wrap"] || opts[:wrap])
57
+ raise ExportError, "no dynamic exports from <#{ path }>!" if
58
+ @exported.nil? or @exported.empty?
59
+ ret = @exported
60
+ ensure
61
+ @exported = nil
62
+ end
63
+ end
64
+ ret
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ $:.unshift '../lib' and $:.unshift './lib'
2
+
3
+ require "dynaload"
4
+
5
+ module M
6
+ C = 4
7
+ module N
8
+ C = 2
9
+ end
10
+ class A
11
+ def run
12
+ 4
13
+ end
14
+ class B
15
+ def run
16
+ 2
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ Dynaload::export M,
23
+ "description" => "the M module"
24
+
25
+ Dynaload::export M::N,
26
+ "description" => "the M::N module"
27
+
28
+ Dynaload::export M::A,
29
+ "description" => "the M::A class",
30
+ "runnable" => true
31
+
32
+ Dynaload::export M::A::B,
33
+ "description" => "the M::A::B class",
34
+ "runnable" => true,
35
+ "these can be" => "any attributes you like!"
@@ -0,0 +1,48 @@
1
+ $:.unshift '../lib' and $:.unshift './lib'
2
+
3
+ require "yaml"
4
+ require "dynaload"
5
+
6
+ #
7
+ # load loaded.rb
8
+ #
9
+ dirname, basename = File::split __FILE__
10
+ loaded_rb = File::join dirname, "loaded.rb"
11
+ loaded = Dynaload::dynaload loaded_rb, "wrap" => false
12
+
13
+ #
14
+ # examine loaded modules, their constants, and descriptions
15
+ #
16
+
17
+ report = {}
18
+ loaded.modules.each do |m, attributes|
19
+ name = m.to_s
20
+ report[name] = {}
21
+ report[name]["constants"] = {}
22
+ report[name]["attributes"] = {}
23
+
24
+ m.constants.each do |const|
25
+ value = m.const_get const
26
+ report[name]["constants"][const] = value unless
27
+ Class === value or Module === value
28
+ end
29
+
30
+ attributes.each do |k,v|
31
+ report[name]["attributes"][k] = v
32
+ end
33
+ end
34
+ y report
35
+
36
+ #
37
+ # find loaded classes that are runnable and run them
38
+ #
39
+ runnables =
40
+ loaded.classes.select{|c,attributes| attributes["runnable"]}
41
+
42
+ report = {}
43
+ runnables.each do |c,attributes|
44
+ name = c.name
45
+ report[name] = {}
46
+ report[name]["run"] = c::new.run
47
+ end
48
+ y report
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: dynaload
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.0
7
- date: 2005-12-12 00:00:00 -07:00
6
+ version: 0.2.1
7
+ date: 2007-10-04 00:00:00 -06:00
8
8
  summary: dynaload
9
9
  require_paths:
10
- - lib
10
+ - lib
11
11
  email: ara.t.howard@noaa.gov
12
12
  homepage: http://codeforpeople.com/lib/ruby/dynaload/
13
13
  rubyforge_project:
@@ -18,23 +18,38 @@ bindir: bin
18
18
  has_rdoc: false
19
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
20
20
  requirements:
21
- -
22
- - ">"
23
- - !ruby/object:Gem::Version
24
- version: 0.0.0
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
25
24
  version:
26
25
  platform: ruby
27
26
  signing_key:
28
27
  cert_chain:
28
+ post_install_message:
29
29
  authors:
30
- - Ara T. Howard
30
+ - Ara T. Howard
31
31
  files:
32
- - lib/dynaload-0.2.0.rb
33
- - lib/dynaload.rb
32
+ - lib
33
+ - lib/dynaload.rb
34
+ - lib/dynaload-0.2.1.rb
35
+ - README
36
+ - install.rb
37
+ - sample
38
+ - sample/loader.rb
39
+ - sample/loaded.rb
40
+ - gemspec.rb
41
+ - HISTORY
34
42
  test_files: []
43
+
35
44
  rdoc_options: []
45
+
36
46
  extra_rdoc_files: []
47
+
37
48
  executables: []
49
+
38
50
  extensions: []
51
+
39
52
  requirements: []
40
- dependencies: []
53
+
54
+ dependencies: []
55
+
@@ -1,81 +0,0 @@
1
- module Dynaload
2
- VERSION = '0.2.0'
3
-
4
- class ExportError < ::StandardError; end
5
-
6
- class Exported < ::Hash
7
- THINGS = %w( classes modules objects )
8
- def initialize(*a, &b)
9
- super
10
- THINGS.each{|thing| self[thing] = []}
11
- end
12
- def method_missing(m,*a,&b)
13
- self[m] || self["#{ m }"] || super
14
- end
15
- def empty?
16
- THINGS.map{|thing| self[thing].empty?}.all?
17
- end
18
- def clear!
19
- THINGS.each{|thing| self[thing].clear}
20
- self
21
- end
22
- def
23
- case thing
24
- when Class
25
- dyna_exported.classes << [thing, attributes]
26
- when Module
27
- dyna_exported.modules << [thing, attributes]
28
- else
29
- dyna_exported.objects << [thing, attributes]
30
- end
31
- end
32
-
33
- module Dynaloadable
34
- module ClassMethods
35
- def dyna_exported
36
- ::Dynaload::exported ||= ::Dynaload::Exported::new
37
- end
38
- def dyna_export *args
39
- things, attribute_hashes = args.partition{|arg| not Hash === arg}
40
- raise ArgumentError, "nothing given to dyna_export!" if things.empty?
41
- attributes = attribute_hashes.inject({}){|h,ah| h.update ah}
42
- things.each do |thing|
43
- case thing
44
- when Class
45
- dyna_exported.classes << [thing, attributes]
46
- when Module
47
- dyna_exported.modules << [thing, attributes]
48
- else
49
- dyna_exported.objects << [thing, attributes]
50
- end
51
- end
52
- dyna_exported.classes.uniq!
53
- dyna_exported.modules.uniq!
54
- dyna_exported.objects.uniq!
55
- dyna_exported
56
- end
57
- alias_method "export", "dyna_export"
58
- alias_method "exported", "dyna_exported"
59
- end
60
- module InstanceMethods; end
61
- extend ClassMethods
62
- def self::included other
63
- other.extend ClassMethods
64
- other.module_eval{ include InstanceMethods }
65
- end
66
- end
67
-
68
- class Dynaloader
69
- def dynaload path
70
- ::Kernel::load path, true
71
- raise ExportError, "no dynamic exports from <#{ path }>!" if Dynaload::exported.empty?
72
- Dynaload::exported
73
- end
74
- end
75
-
76
- include Dynaloadable
77
-
78
- def self::dynaload(*a, &b)
79
- (@dynaloader ||= Dynaloader::new).dynaload(*a, &b)
80
- end
81
- end