ToolParade 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -0
- data/README +130 -0
- data/Rakefile +49 -0
- data/bin/toolparade +49 -0
- data/config/default.yml +16 -0
- data/lib/toolparade.rb +199 -0
- data/test/test_toolparade.rb +32 -0
- metadata +59 -0
data/CHANGELOG
ADDED
data/README
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
<b>Tool parade scans your system for Ruby Gems and Rails plugins and uploads the result to a central server</b>
|
2
|
+
|
3
|
+
This data is used for analysis on Working With Rails to generate
|
4
|
+
public charts of the most active plugins and gems.
|
5
|
+
You have full control over how and what data is submitted
|
6
|
+
|
7
|
+
Project Home page: http://toolparade.rubyforge.org (pending)
|
8
|
+
|
9
|
+
==Why do this?
|
10
|
+
|
11
|
+
* Share your installed gems/plugins with others. Get ideas of what
|
12
|
+
libraries you might want to use based on others credentials.
|
13
|
+
|
14
|
+
* Ensure that the authors of the plugin/gems get the credit they deserve.
|
15
|
+
* Gem builders / plugin authors - see how many developers use your gem, which version etc.
|
16
|
+
|
17
|
+
* Lowers the barrier for people to report what libraries they are using. It is
|
18
|
+
potentially more informative than pure download stats.
|
19
|
+
|
20
|
+
* Allows the system to make intelligent recommendations of plugins you may
|
21
|
+
also be interested in / alternatives. (in the future)
|
22
|
+
|
23
|
+
|
24
|
+
==Usage
|
25
|
+
|
26
|
+
Run this on your development machine only. It's always best to set it to where you
|
27
|
+
develop your Rails application. Scanning for plugins may take a very long time
|
28
|
+
if you have a large number projects.
|
29
|
+
|
30
|
+
|
31
|
+
Standard operation:
|
32
|
+
toolparade
|
33
|
+
|
34
|
+
Help
|
35
|
+
toolparade help
|
36
|
+
|
37
|
+
Setup
|
38
|
+
toolparade setup
|
39
|
+
|
40
|
+
Config (views the config)
|
41
|
+
toolparade config
|
42
|
+
|
43
|
+
Debug
|
44
|
+
toolparade debug
|
45
|
+
|
46
|
+
== Tips
|
47
|
+
|
48
|
+
Lets say you are working on a super top secret library and you don't want
|
49
|
+
this to be published.
|
50
|
+
Just add it to the ignore section in your toolparade.yml config (usually
|
51
|
+
located in your home directory):
|
52
|
+
|
53
|
+
|
54
|
+
Example:
|
55
|
+
|
56
|
+
|
57
|
+
ignore:
|
58
|
+
gems: my_private_gem,CVS
|
59
|
+
plugins: my_secret_project
|
60
|
+
|
61
|
+
|
62
|
+
If you know you don't really use a plugin / gem also feel free to use
|
63
|
+
ignore list.
|
64
|
+
|
65
|
+
|
66
|
+
==Limitations
|
67
|
+
|
68
|
+
Removal of a gem or plugin is not currently reflected.
|
69
|
+
You need to remove it using the web based interface if desired.
|
70
|
+
|
71
|
+
This is true in the case of ignore filters if the gem/plugin to ignore has
|
72
|
+
already been registered in a previous scan.
|
73
|
+
|
74
|
+
Of course just because the plugin / gem is installed on your system is doesn't
|
75
|
+
mean you are using it all the time if at all. Currently this tool doesn't
|
76
|
+
make allowances for distinguishing this matter.
|
77
|
+
There is however plenty of scope to improve the algorithms and scanning techniques
|
78
|
+
in place. Feel free to drop me a line with suggestions.
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
==History and credits
|
84
|
+
|
85
|
+
For some time I've been toying with the idea of incorporating some kind
|
86
|
+
of plugin/gem stats functionality into Working With Rails.
|
87
|
+
I had a feature branch I've been developing since January that did a basic scan
|
88
|
+
of plugins (albeit crudely). I also had suggestions from other members
|
89
|
+
of the community to do something similar so this spurred me on.
|
90
|
+
|
91
|
+
However I hadn't previously released this for fear of diluting the current people based
|
92
|
+
focus of WWR. I'm not looking to turn it into a replacement plugin /gem directory
|
93
|
+
as we already have places for that.
|
94
|
+
|
95
|
+
Some folks to thank:
|
96
|
+
|
97
|
+
Johannes de Jong - Shows us your gems! suggestion
|
98
|
+
http://workingwithrails.com/person/7426-johannes-de-jong
|
99
|
+
|
100
|
+
and Mike Clark (for starting the topic)
|
101
|
+
http://clarkware.com/cgi/blosxom/2007/02/10#GemSurvey
|
102
|
+
|
103
|
+
Jeremy Kemper (Rails core team) - gem stats idea (pending further implementation)
|
104
|
+
http://workingwithrails.com/person/5323-jeremy-kemper
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
== Suggestions / Improvements
|
109
|
+
|
110
|
+
This kind of thing ultimately only works if people use it. So it's up
|
111
|
+
to you give it a try and spread the word.
|
112
|
+
|
113
|
+
Feel free to drop me a mail: mtsbtt @ googlemail.com
|
114
|
+
or submit patches.
|
115
|
+
|
116
|
+
I'm always open to suggestions and quick to implement when I get time.
|
117
|
+
|
118
|
+
|
119
|
+
==About the Author
|
120
|
+
|
121
|
+
Martin Sadler currently works for DSC a web consulting, hosting, web development
|
122
|
+
and design firm based in London, UK.
|
123
|
+
|
124
|
+
He runs a blog at:
|
125
|
+
* http://www.beyondthetype.com
|
126
|
+
|
127
|
+
and also kick started and maintains the Working With Rails community site:
|
128
|
+
* http://www.workingwithrails.com
|
129
|
+
|
130
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
Gem::manage_gems
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
PKG_FILES = FileList[
|
7
|
+
"Rakefile", "README","CHANGELOG",
|
8
|
+
"config/**/*",
|
9
|
+
"test/**/*",
|
10
|
+
"lib/**/*.rb",
|
11
|
+
"bin/**/*"
|
12
|
+
]
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.name = "ToolParade"
|
16
|
+
s.version = "0.0.2"
|
17
|
+
s.author = "Martin Sadler"
|
18
|
+
s.email = "mtsbtt@googlemail.com"
|
19
|
+
s.homepage = "http://beyondthetype.com/"
|
20
|
+
s.platform = Gem::Platform::RUBY
|
21
|
+
s.summary = "Get your tools out for parade"
|
22
|
+
s.files = PKG_FILES
|
23
|
+
s.require_path = "lib"
|
24
|
+
s.autorequire = "name"
|
25
|
+
s.test_files = FileList["{test}/**/*test.rb"].to_a
|
26
|
+
s.has_rdoc = true
|
27
|
+
s.extra_rdoc_files = ["README"]
|
28
|
+
s.executables = ['toolparade']
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
# Genereate the RDoc documentation
|
33
|
+
Rake::RDocTask.new { |rdoc|
|
34
|
+
rdoc.rdoc_dir = 'doc'
|
35
|
+
rdoc.title = "Tool Parade"
|
36
|
+
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
37
|
+
rdoc.rdoc_files.include('README')
|
38
|
+
rdoc.rdoc_files.include(Dir.glob("lib/**/*.rb") )
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
43
|
+
pkg.need_tar = true
|
44
|
+
end
|
45
|
+
|
46
|
+
task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
|
47
|
+
puts "generated latest version"
|
48
|
+
end
|
49
|
+
|
data/bin/toolparade
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
3
|
+
|
4
|
+
require 'toolparade'
|
5
|
+
|
6
|
+
PROGRAM = File::basename $0
|
7
|
+
mode = ARGV.shift
|
8
|
+
@debug = false
|
9
|
+
|
10
|
+
puts "Ruby and Rails Tool Parade"
|
11
|
+
puts "=-=-=-=-=-=-=-=-=-=-=-=-=-"
|
12
|
+
puts "\"#{PROGRAM} help\" for help"
|
13
|
+
|
14
|
+
case mode
|
15
|
+
when %r/help/
|
16
|
+
puts File.open(File.expand_path(File.dirname(__FILE__) + "/../README")).read
|
17
|
+
exit
|
18
|
+
when %r/setup/
|
19
|
+
ToolParade.setup
|
20
|
+
exit
|
21
|
+
when %r/config/
|
22
|
+
@tp = ToolParade.new
|
23
|
+
puts "Reading config located in #{ToolParade::CONFIG}"
|
24
|
+
puts @tp.config.to_yaml
|
25
|
+
exit
|
26
|
+
when %r/debug/
|
27
|
+
@debug = true
|
28
|
+
end
|
29
|
+
|
30
|
+
@tp = ToolParade.new
|
31
|
+
p @tp.config if @debug
|
32
|
+
|
33
|
+
puts "Scanning system for: "
|
34
|
+
print "Gems... "
|
35
|
+
@tp.scan_for_gems
|
36
|
+
p @tp.gemslist if @debug
|
37
|
+
puts 'Done'
|
38
|
+
puts "Plugins.. (this may take a while) "
|
39
|
+
@tp.scan_for_plugins
|
40
|
+
p @tp.pluginslist if @debug
|
41
|
+
puts "Finished"
|
42
|
+
|
43
|
+
@tp.view_scan
|
44
|
+
|
45
|
+
@tp.get_login_credentials
|
46
|
+
puts "Please wait. Authenticating and uploading...."
|
47
|
+
@tp.upload
|
48
|
+
puts "The result of your upload can be viewed at http://#{@tp.domain} from your profile page."
|
49
|
+
puts "Thank you for using Tool Parade"
|
data/config/default.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
upload:
|
2
|
+
domain: workingwithrails.com
|
3
|
+
username:
|
4
|
+
password:
|
5
|
+
|
6
|
+
paths:
|
7
|
+
plugins: ~/dev;~/sandbox
|
8
|
+
|
9
|
+
transmit:
|
10
|
+
gem_version_numbers: true
|
11
|
+
plugin_numbers: true
|
12
|
+
|
13
|
+
# Regex's allowed e.g. prefix_*
|
14
|
+
ignore:
|
15
|
+
gems: my_private_gem,CVS
|
16
|
+
plugins: my_secret_project
|
data/lib/toolparade.rb
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
def Kernel.is_windows?
|
7
|
+
processor, platform, *rest = RUBY_PLATFORM.split("-")
|
8
|
+
platform == 'mswin32'
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# See README for full documentation
|
13
|
+
#
|
14
|
+
#TODO: Room for some refactoring, perhaps use of exceptions in places (make it easier to catch and test desired behaviours)
|
15
|
+
class ToolParade
|
16
|
+
# :stopdoc:
|
17
|
+
VERSION = "0.0.1"
|
18
|
+
HOME = ENV["HOME"] || ENV["HOMEPATH"] || File::expand_path("~")
|
19
|
+
CONFIG = File::join HOME, ".toolparade.yml"
|
20
|
+
DEFAULT_CONFIG = File.expand_path("#{__FILE__}/../../config/default.yml")
|
21
|
+
|
22
|
+
# :startdoc:
|
23
|
+
attr_accessor :config
|
24
|
+
attr_reader :pluginslist
|
25
|
+
attr_reader :plugin_descriptions
|
26
|
+
|
27
|
+
attr_reader :gemslist
|
28
|
+
|
29
|
+
attr_reader :username
|
30
|
+
attr_reader :password
|
31
|
+
attr_reader :domain
|
32
|
+
|
33
|
+
def initialize(options = {})
|
34
|
+
return if options[:skip]
|
35
|
+
|
36
|
+
begin
|
37
|
+
@config = YAML.load_file(CONFIG)
|
38
|
+
rescue Errno::ENOENT
|
39
|
+
puts "No configuration file detected. Entering first time setup."
|
40
|
+
puts
|
41
|
+
setup
|
42
|
+
end
|
43
|
+
@username = @config['upload']['username']
|
44
|
+
@password = @config['upload']['password']
|
45
|
+
@domain = @config['upload']['domain']
|
46
|
+
@plugin_descriptions = {}
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.setup
|
51
|
+
new(:skip => true).setup
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup
|
55
|
+
puts "Enter the path where you develop your Rails applications."
|
56
|
+
puts "Separated by ; if there is more than one e.g. ~/dev;~/sandbox"
|
57
|
+
print "> Rails plugin scan path (#{HOME}): "
|
58
|
+
path = gets.chomp!
|
59
|
+
path = path == '' ? HOME : path
|
60
|
+
@config = YAML.load_file(DEFAULT_CONFIG)
|
61
|
+
@config['paths']['plugins'] = path
|
62
|
+
begin
|
63
|
+
open(CONFIG, "w") { |f| f.write @config.to_yaml }
|
64
|
+
rescue Errno::ENOENT
|
65
|
+
puts "Unable to open #{CONFIG} for writing."
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
puts "SETUP COMPLETE. Configuration stored in: #{CONFIG}"
|
69
|
+
puts
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def scan_for_gems
|
74
|
+
@gemslist = Kernel.is_windows? ? `cmd /c gem list` : `gem list`
|
75
|
+
@gemslist = "#{@gemslist.grep(/^[a-zA-Z]/)}\n"
|
76
|
+
remove_bracketed_info!(@gemlist) unless @config['transmit']['gem_version_numbers']
|
77
|
+
apply_ignore_filters!(@gemslist)
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def scan_for_plugins
|
82
|
+
|
83
|
+
|
84
|
+
scores = Hash.new(0)
|
85
|
+
for path in @config['paths']['plugins'].split(';')
|
86
|
+
scanpath = File.expand_path(path.to_s.strip)
|
87
|
+
if FileTest.exist?(scanpath)
|
88
|
+
|
89
|
+
Dir["#{scanpath}/**/vendor/plugins/**"].each{|f|
|
90
|
+
scores[File.basename(f)] += 1
|
91
|
+
readme = File.expand_path("#{f}/README")
|
92
|
+
if FileTest.exist?(readme)
|
93
|
+
@plugin_descriptions[File.basename(f)] ||= File.open(readme).read
|
94
|
+
end
|
95
|
+
}
|
96
|
+
else
|
97
|
+
puts "Warning / Notice: Plugin scan path: #{path} cannot be read"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
@pluginslist = scores.collect{|name,score| "#{name} (#{score})"}.join("\n")+"\n"
|
101
|
+
|
102
|
+
remove_bracketed_info!(@pluginslist) unless @config['transmit']['plugin_numbers']
|
103
|
+
apply_ignore_filters!(@pluginslist)
|
104
|
+
end
|
105
|
+
|
106
|
+
def view_scan
|
107
|
+
print "Would you like to review the list of plugins and gems details that will be uploaded before continuing? (Y/N): "
|
108
|
+
return unless gets =~ /y/i
|
109
|
+
print_gem_and_plugin_info
|
110
|
+
|
111
|
+
puts "If you wish filter out certain results you may do so now by editing #{CONFIG}"
|
112
|
+
puts ""
|
113
|
+
|
114
|
+
ok = false
|
115
|
+
|
116
|
+
while !ok
|
117
|
+
|
118
|
+
print "If you have modified the configuration file hit yes for your changes to take effect (Y/N): "
|
119
|
+
|
120
|
+
|
121
|
+
if gets =~ /y/i
|
122
|
+
@config = YAML.load_file(CONFIG)
|
123
|
+
remove_bracketed_info!(@pluginslist) unless @config['transmit']['plugin_numbers']
|
124
|
+
apply_ignore_filters!(@pluginslist)
|
125
|
+
remove_bracketed_info!(@gemlist) unless @config['transmit']['gem_version_numbers']
|
126
|
+
apply_ignore_filters!(@gemslist)
|
127
|
+
|
128
|
+
end
|
129
|
+
print_gem_and_plugin_info
|
130
|
+
puts "Displayed are the results that will be now uploaded."
|
131
|
+
puts "You may go back and edit the configuration file some more or..."
|
132
|
+
print "If you are happy with the results hit yes. (Y/N:)"
|
133
|
+
ok = true if gets =~ /y/i
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def print_gem_and_plugin_info
|
138
|
+
puts "Gems Found"
|
139
|
+
puts "---------------------------------------"
|
140
|
+
puts @gemslist
|
141
|
+
puts "Plugins Found"
|
142
|
+
puts "---------------------------------------"
|
143
|
+
puts @pluginslist.split("\n").sort
|
144
|
+
end
|
145
|
+
|
146
|
+
def get_login_credentials
|
147
|
+
return if "#{@username}".strip.chomp != '' && "#{@password}".strip.chomp !=''
|
148
|
+
|
149
|
+
puts "Please login to Working With Rails to continue upload"
|
150
|
+
print "> Username: "
|
151
|
+
@username = gets.chomp!
|
152
|
+
print "> Password: "
|
153
|
+
@password = get_password
|
154
|
+
puts ""
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
def upload
|
159
|
+
res = Net::HTTP.post_form(URI.parse("http://#{@domain}/rubygems/upload"),
|
160
|
+
{'login'=>@username, 'password'=>@password, 'list' => @gemslist})
|
161
|
+
puts "Gem upload response: #{res.body}"
|
162
|
+
|
163
|
+
|
164
|
+
post_fields = {'login'=>@username, 'password'=>@password, 'list' => @pluginslist}
|
165
|
+
@plugin_descriptions.each{|name, description| post_fields["readmes[#{name}]"] = description}
|
166
|
+
|
167
|
+
res = Net::HTTP.post_form(URI.parse("http://#{@domain}/railsplugins/upload"),
|
168
|
+
post_fields)
|
169
|
+
puts "Plugin upload response: #{res.body}"
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def get_password
|
176
|
+
if Kernel.is_windows?
|
177
|
+
return gets.chomp!
|
178
|
+
else
|
179
|
+
# on a non-windows box we can hide input for the password
|
180
|
+
`stty -echo`
|
181
|
+
begin
|
182
|
+
out = STDIN.gets.chomp
|
183
|
+
ensure
|
184
|
+
`stty echo`
|
185
|
+
end
|
186
|
+
return out
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
def remove_bracketed_info!(string)
|
193
|
+
string.gsub!(/\([^\)]+\)/,'')
|
194
|
+
end
|
195
|
+
|
196
|
+
def apply_ignore_filters!(string)
|
197
|
+
string.gsub!(/#{config['ignore']['plugins'].split(',').collect{|i| "^#{i.strip}.*\n"}.join('|')}/,'')
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'lib/toolparade'
|
3
|
+
|
4
|
+
|
5
|
+
class TestToolParade < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@tp = ToolParade.new
|
9
|
+
@tp.config['paths']['plugins'] = "#{File.expand_path(File.dirname(__FILE__))}/fixtures"
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_plugin_path_scan
|
13
|
+
@tp.scan_for_plugins
|
14
|
+
assert_equal "acts_as_a (1)\nacts_as_b (1)\nacts_as_c (1)\n", @tp.pluginslist
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_ignore_filters_for_plugin
|
18
|
+
@tp.config['ignore']['plugins'] = "acts_as_b,acts_as_c\n"
|
19
|
+
@tp.scan_for_plugins
|
20
|
+
assert_equal "acts_as_a (1)\n", @tp.pluginslist
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_filter_version_numbers
|
25
|
+
@tp.config['transmit']['gem_version_numbers'] = false
|
26
|
+
gemslist = "gem a (1.0)\ngem b (2.0)\ngem c (2.1,2.01)\n"
|
27
|
+
@tp.send('remove_bracketed_info!',gemslist)
|
28
|
+
assert_equal "gem a \ngem b \ngem c \n", gemslist
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: ToolParade
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2007-07-19 00:00:00 +01:00
|
8
|
+
summary: Get your tools out for parade
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: mtsbtt@googlemail.com
|
12
|
+
homepage: http://beyondthetype.com/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: name
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Martin Sadler
|
31
|
+
files:
|
32
|
+
- Rakefile
|
33
|
+
- README
|
34
|
+
- CHANGELOG
|
35
|
+
- config/default.yml
|
36
|
+
- test/fixtures
|
37
|
+
- test/fixtures/vendor
|
38
|
+
- test/fixtures/vendor/plugins
|
39
|
+
- test/fixtures/vendor/plugins/acts_as_a
|
40
|
+
- test/fixtures/vendor/plugins/acts_as_b
|
41
|
+
- test/fixtures/vendor/plugins/acts_as_c
|
42
|
+
- test/fixtures/vendor/plugins/acts_as_c/not_shown
|
43
|
+
- test/test_toolparade.rb
|
44
|
+
- lib/toolparade.rb
|
45
|
+
- bin/toolparade
|
46
|
+
test_files: []
|
47
|
+
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
extra_rdoc_files:
|
51
|
+
- README
|
52
|
+
executables:
|
53
|
+
- toolparade
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
dependencies: []
|
59
|
+
|