plugin-loader 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/plugin/format/command.rb +35 -0
- data/lib/plugin/format/data.rb +32 -0
- data/lib/plugin/format/dbus.rb +67 -0
- data/lib/plugin/format/ruby.rb +48 -0
- data/lib/plugin/format/script.rb +35 -0
- data/lib/plugin/format.rb +68 -0
- data/lib/plugin/loader.rb +130 -0
- metadata +92 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
# command.rb
|
2
|
+
#
|
3
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
18
|
+
# MA 02110-1301, USA.
|
19
|
+
#
|
20
|
+
#The command format takes '$' to be a command, executes it, and
|
21
|
+
#returns an array of lines of standard output.
|
22
|
+
# {
|
23
|
+
# "format" => "command",
|
24
|
+
# "$" => "COMMAND"
|
25
|
+
# }
|
26
|
+
require 'plugin/format'
|
27
|
+
|
28
|
+
#Depends: libescape-ruby
|
29
|
+
require 'escape'
|
30
|
+
|
31
|
+
Plugin::Format.add 'command' do |exec, args, opts|
|
32
|
+
IO.popen Escape.shell_command([exec.to_s, *args]).to_s do |handle|
|
33
|
+
return handle.read.split("\n")
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# data.rb
|
2
|
+
#
|
3
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
18
|
+
# MA 02110-1301, USA.
|
19
|
+
#
|
20
|
+
#data is a very simple plugin format that just returns the data structure
|
21
|
+
#referred to by the '$' key in the plugin metadata file:
|
22
|
+
# {
|
23
|
+
# "format" : "data",
|
24
|
+
# "$" : ...
|
25
|
+
# }
|
26
|
+
#The data can be any type supported by JSON, including number, string, array,
|
27
|
+
#hash(object) and boolean.
|
28
|
+
require 'plugin/format'
|
29
|
+
|
30
|
+
Plugin::Format.add 'data' do |exec, args, opts|
|
31
|
+
exec
|
32
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# dbus.rb
|
2
|
+
#
|
3
|
+
# Defines a plugin format that works by connecting to a dbus service.
|
4
|
+
#
|
5
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation; either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
20
|
+
# MA 02110-1301, USA.
|
21
|
+
#
|
22
|
+
#
|
23
|
+
#A plugin in dbus format has a general metadata file format of:
|
24
|
+
# {
|
25
|
+
# 'format' : 'dbus',
|
26
|
+
# '$' : [service, object, interface, method]
|
27
|
+
# }
|
28
|
+
#For example:
|
29
|
+
# {
|
30
|
+
# "format" : "dbus",
|
31
|
+
# "$" : [
|
32
|
+
# "org.gnome.Rhythmbox",
|
33
|
+
# "/org/gnome/Rhythmbox/Player",
|
34
|
+
# "org.gnome.Rhythmbox.Player",
|
35
|
+
# "getPlayingUri"
|
36
|
+
# ]
|
37
|
+
# }
|
38
|
+
#describes a plugin that gets the current playing song in Rhythmbox.
|
39
|
+
#
|
40
|
+
#The dbus format uses the dbus session bus.
|
41
|
+
#It only works with dbus services that can be introspected (which is almost all of them).
|
42
|
+
require 'plugin/format'
|
43
|
+
|
44
|
+
#Depends: libdbus-ruby
|
45
|
+
require 'dbus'
|
46
|
+
|
47
|
+
module Plugin
|
48
|
+
|
49
|
+
Format.add 'dbus' do |exec, args, opts|
|
50
|
+
service = exec[0]
|
51
|
+
object = exec[1]
|
52
|
+
iface = exec[2]
|
53
|
+
method = exec[3]
|
54
|
+
|
55
|
+
obj = DBus::SessionBus.
|
56
|
+
instance.
|
57
|
+
service(service).
|
58
|
+
object(object)
|
59
|
+
|
60
|
+
obj.introspect
|
61
|
+
|
62
|
+
obj[iface].
|
63
|
+
method(method).
|
64
|
+
call(*args)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# ruby.rb
|
2
|
+
#
|
3
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
18
|
+
# MA 02110-1301, USA.
|
19
|
+
#
|
20
|
+
#The ruby format allows plugins to be written in ruby.
|
21
|
+
#The '$' key refers to the ruby file that should be loaded.
|
22
|
+
#The metadata file has the following format:
|
23
|
+
# {
|
24
|
+
# "format" : "ruby",
|
25
|
+
# "$" : "ruby_lib"
|
26
|
+
# }
|
27
|
+
#The ruby file should look something like:
|
28
|
+
# Plugin.new do |*args|
|
29
|
+
# #some code
|
30
|
+
# end
|
31
|
+
require 'plugin/format'
|
32
|
+
|
33
|
+
module Plugin
|
34
|
+
|
35
|
+
_ruby_plugin = lambda do |*args|
|
36
|
+
args
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.new &b
|
40
|
+
_ruby_plugin = b
|
41
|
+
end
|
42
|
+
|
43
|
+
Format.add 'ruby' do |exec, args, opts|
|
44
|
+
load exec
|
45
|
+
_ruby_plugin.call *args
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# script.rb
|
2
|
+
#
|
3
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
18
|
+
# MA 02110-1301, USA.
|
19
|
+
#
|
20
|
+
#The script format takes '$' to be an executable in the @script_dir folder.
|
21
|
+
#The script is executed and an array of lines of standard output is returned.
|
22
|
+
# {
|
23
|
+
# "format" => "command",
|
24
|
+
# "$" => "COMMAND"
|
25
|
+
# }
|
26
|
+
require 'plugin/format'
|
27
|
+
|
28
|
+
#Depends: libescape-ruby
|
29
|
+
require 'escape'
|
30
|
+
|
31
|
+
Plugin::Format.add 'script' do |exec, args, opts|
|
32
|
+
IO.popen Escape.shell_command(["#{opts[:dir] || '/usr/bin'}/#{exec}", *args]).to_s do |handle|
|
33
|
+
return handle.read.split("\n")
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# format.rb
|
2
|
+
#
|
3
|
+
# Defines a class allowing new plugin formats to be added.
|
4
|
+
#
|
5
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation; either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
20
|
+
# MA 02110-1301, USA.
|
21
|
+
|
22
|
+
|
23
|
+
module Plugin
|
24
|
+
|
25
|
+
#An instance of this class represents a plugin format.
|
26
|
+
class Format
|
27
|
+
@@formats = {}
|
28
|
+
#To create a new annonymous plugin format:
|
29
|
+
# Plugin::Format.new do |exec, args, opts|
|
30
|
+
# ...
|
31
|
+
# return return_data
|
32
|
+
# end
|
33
|
+
#Argument 'exec' provides the data in the '$' key of the plugin metadata file.
|
34
|
+
#Argument 'args' is an array of arguments passed to this format by a Plugin::Loader instance when its run method is called.
|
35
|
+
#Argument 'opts' is a hash of options from Plugin::Loader that may be required by a plugin format. At present opts conatins the following keys:
|
36
|
+
# :plugin_dir
|
37
|
+
# :data_dir
|
38
|
+
# :script_dir
|
39
|
+
#These are the same as the options given when the Plugin::Loader was initialized.
|
40
|
+
#
|
41
|
+
#Plugin::Format.add should be used to create a new plugin format because the format is given a name.
|
42
|
+
def initialize &b
|
43
|
+
@block = b
|
44
|
+
end
|
45
|
+
#Creates a lambda function from the exec value and opts hash.
|
46
|
+
#When the lambda function is called, its arguments become 'args' and
|
47
|
+
#the block given at initialize is executed.
|
48
|
+
def new exec, opts={}
|
49
|
+
lambda do |*args|
|
50
|
+
@block.call exec, args, opts
|
51
|
+
end
|
52
|
+
end
|
53
|
+
#Creates a named plugin format using the same rules as Plugin::Format.new:
|
54
|
+
# Plugin::Format.add "name" do |exec, args, opts|
|
55
|
+
# ...
|
56
|
+
# return return_data
|
57
|
+
# end
|
58
|
+
def self.add name, &b
|
59
|
+
@@formats[name] = self.new &b
|
60
|
+
end
|
61
|
+
#Returns the format called 'name':
|
62
|
+
# Plugin::Format['name']
|
63
|
+
def self.[] name
|
64
|
+
@@formats[name]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# loader.rb
|
2
|
+
#
|
3
|
+
# Provides a class for loading plugins into a program.
|
4
|
+
#
|
5
|
+
# Copyright 2010 David Green <david4dev@gmail.com>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation; either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
20
|
+
# MA 02110-1301, USA.
|
21
|
+
require 'plugin/format'
|
22
|
+
|
23
|
+
#Depends: libjson-ruby
|
24
|
+
require 'json'
|
25
|
+
|
26
|
+
module Plugin
|
27
|
+
|
28
|
+
#Using an instance of this class, you can control what plugins are
|
29
|
+
#loaded into your program.
|
30
|
+
class Loader
|
31
|
+
#OPTIONS:
|
32
|
+
#
|
33
|
+
# :allowed_formats => [...] #optional; default is an array of all available plugin formats
|
34
|
+
#- Defines an array of names (strings) of formats that plugins for this instance can be written in.
|
35
|
+
#
|
36
|
+
# :data_dir => '/usr/share/appname' #required
|
37
|
+
#- Defines the directory in which the data for this instance is stored in the file system.
|
38
|
+
#
|
39
|
+
# :plugin_dir => '' #optional; default is "#{@data_dir}/plugins"
|
40
|
+
#- Defines the directory in which the plugin metadata files are stored
|
41
|
+
#
|
42
|
+
# :script_dir => '' #optional; default is "#{@data_dir}/scripts"
|
43
|
+
#- Defines the directory in which excecutables (potentially used by plugins) are stored.
|
44
|
+
def initialize opts={}
|
45
|
+
@available_formats = $:.map do |path|
|
46
|
+
Dir.glob("#{path}/plugin/format/*.rb").map! do |rbfile|
|
47
|
+
File.basename(rbfile).sub!(/\.rb$/, '')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@available_formats.flatten!
|
51
|
+
@allowed_formats = opts[:allowed_formats] ? (opts[:allowed_formats] & available_formats) : available_formats
|
52
|
+
@allowed_formats.each do |fmt|
|
53
|
+
require "plugin/format/#{fmt}"
|
54
|
+
end
|
55
|
+
@data_dir = opts[:data_dir]
|
56
|
+
@plugin_dir = opts[:plugin_dir] || "#{@data_dir}/plugins"
|
57
|
+
@script_dir = opts[:script_dir] || "#{@data_dir}/scripts"
|
58
|
+
@plugins = {}
|
59
|
+
end
|
60
|
+
#Loads a plugin called 'name' of type 'type'.
|
61
|
+
#It does this by reading the metadata file: "#{@plugin_dir}/name.type".
|
62
|
+
#Plugin types should be considered namespaces for one or more plugins.
|
63
|
+
#Plugin names are the unique identification of a plugin within a particular type.
|
64
|
+
#Plugins are similar to functions - they are excecuted with arguments a value (which can be a complex data structure such as hash or array if needed).
|
65
|
+
#load does not excecute a plugin but it once loaded
|
66
|
+
#a plugin can be excecuted with the run method.
|
67
|
+
#
|
68
|
+
#The metadata files are in a JSON format:
|
69
|
+
# {
|
70
|
+
# "format" => "FORMAT_NAME",
|
71
|
+
# "$" => ...
|
72
|
+
# }
|
73
|
+
#The 'format' key is a string that defines the name of the format of the plugin. If load loads a plugin without the 'format' key, an exception is raised.
|
74
|
+
#If the format is not available or is not allowed (see: initailize), an exception is raised.
|
75
|
+
#See Plugin::Format for more details on plugin formats.
|
76
|
+
#The '$' key can be any data structure (most commonly a string) and is used by the format declaration to excecute a plugin. See the individual format declarations in plugin/format/*.rb for details of individual formats. If the '$' key is missing, an exception is raised.
|
77
|
+
def load name, type
|
78
|
+
File.open "#{@plugin_dir}/#{name}.#{type}" do |f|
|
79
|
+
data = JSON.parse(f.read)
|
80
|
+
unless data.has_key? '$'
|
81
|
+
raise "Plugin #{type} plugin '#{name}' has an invalid metadata file. It is missing the required '$' key!"
|
82
|
+
end
|
83
|
+
unless data.has_key? 'format'
|
84
|
+
raise "Plugin #{type} plugin '#{name}' has an invalid metadata file. It is missing the required 'format' key!"
|
85
|
+
end
|
86
|
+
unless @plugins.has_key? type
|
87
|
+
@plugins[type] = {}
|
88
|
+
end
|
89
|
+
format = Format[data['format']]
|
90
|
+
if format.nil?
|
91
|
+
raise "Plugin format #{data['format']} does not exist or is disabled!"
|
92
|
+
end
|
93
|
+
@plugins[type][name] = format.new data['$'],
|
94
|
+
:script_dir => @script_dir,
|
95
|
+
:data_dir => @data_dir,
|
96
|
+
:plugin_dir => @plugin_dir
|
97
|
+
end
|
98
|
+
end
|
99
|
+
#Unloads a plugin of name 'name' and type 'type'.
|
100
|
+
def unload name, type
|
101
|
+
@plugins[type].delete name
|
102
|
+
end
|
103
|
+
#Loads all plugins of type 'type'.
|
104
|
+
def load_type type
|
105
|
+
Dir.glob("#{@plugin_dir}/*.#{type}").each do |file|
|
106
|
+
self.load file
|
107
|
+
end
|
108
|
+
end
|
109
|
+
#Unloads all plugins of type 'type'.
|
110
|
+
def unload_type type
|
111
|
+
@plugins.delete type
|
112
|
+
end
|
113
|
+
#Loads all plugins.
|
114
|
+
def load_all
|
115
|
+
Dir.glob("#{@plugin_dir}/*").each do |file|
|
116
|
+
self.load file
|
117
|
+
end
|
118
|
+
end
|
119
|
+
#Unloads all plugins.
|
120
|
+
def unload_all
|
121
|
+
@plugins.clear
|
122
|
+
end
|
123
|
+
#Excecutes the plugin of type 'type' called 'name', passing in any other arguments.
|
124
|
+
#The return value of the plugin is returned.
|
125
|
+
def run name, type, *args
|
126
|
+
@plugins[type][name].call *args
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: plugin-loader
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Green
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-09-25 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dbus
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: escape
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: |-
|
46
|
+
plugin-loader can be used to extend a program written in ruby by using plugins.
|
47
|
+
Plugins can be written in ruby or can be external resources.
|
48
|
+
email: david4dev@gmail.com
|
49
|
+
executables: []
|
50
|
+
|
51
|
+
extensions: []
|
52
|
+
|
53
|
+
extra_rdoc_files: []
|
54
|
+
|
55
|
+
files:
|
56
|
+
- lib/plugin/format/dbus.rb
|
57
|
+
- lib/plugin/format/script.rb
|
58
|
+
- lib/plugin/format/ruby.rb
|
59
|
+
- lib/plugin/format/data.rb
|
60
|
+
- lib/plugin/format/command.rb
|
61
|
+
- lib/plugin/format.rb
|
62
|
+
- lib/plugin/loader.rb
|
63
|
+
has_rdoc: true
|
64
|
+
homepage: https://launchpad.net/libplugin-loader-ruby
|
65
|
+
licenses: []
|
66
|
+
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.8.1
|
77
|
+
version:
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.3.5
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Library for creating extensible ruby applications
|
91
|
+
test_files: []
|
92
|
+
|