dynaload 0.2.0 → 0.2.1

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/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