rbbt-util 1.0.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.
@@ -0,0 +1,200 @@
1
+ require 'rbbt/util/cmd'
2
+ require 'rbbt/util/misc'
3
+ require 'rbbt/util/tmpfile'
4
+
5
+ require 'zlib'
6
+ require 'digest/md5'
7
+
8
+ module Open
9
+ class OpenURLError < StandardError; end
10
+ class OpenGzipError < StandardError; end
11
+
12
+ REMOTE_CACHEDIR = "/tmp/open_cache"
13
+ FileUtils.mkdir REMOTE_CACHEDIR unless File.exist? REMOTE_CACHEDIR
14
+
15
+ def self.cachedir=(cachedir)
16
+ REMOTE_CACHEDIR.replace cachedir
17
+ FileUtils.mkdir REMOTE_CACHEDIR unless File.exist? REMOTE_CACHEDIR
18
+ end
19
+
20
+ def self.cachedir
21
+ REMOTE_CACHEDIR
22
+ end
23
+
24
+ # Remote WGET
25
+ LAST_TIME = {}
26
+ def self.wait(lag, key = nil)
27
+ time = Time.now
28
+
29
+ if LAST_TIME[key] != nil && (time < LAST_TIME[key] + lag)
30
+ sleep (LAST_TIME[key] + lag) - time
31
+ end
32
+
33
+ LAST_TIME[key] = Time.now
34
+ end
35
+
36
+ def self.wget(url, options = {})
37
+ options = Misc.add_defaults options, "--user-agent=" => 'firefox', :pipe => true
38
+
39
+ wait(options[:nice], options[:nice_key]) if options[:nice]
40
+ options.delete(:nice)
41
+ options.delete(:nice_key)
42
+
43
+ pipe = options.delete(:pipe)
44
+ quiet = options.delete(:quiet)
45
+ options["--quiet"] = quiet if options["--quiet"].nil?
46
+
47
+ stderr = case
48
+ when options['stderr']
49
+ options['stderr']
50
+ when options['--quiet']
51
+ false
52
+ else
53
+ nil
54
+ end
55
+ begin
56
+ CMD.cmd("wget '#{ url }'", options.merge(
57
+ '-O' => '-',
58
+ :pipe => pipe,
59
+ :stderr => stderr
60
+ ))
61
+ rescue
62
+ STDERR.puts $!.backtrace.inspect
63
+ raise OpenURLError, "Error reading remote url: #{ url }.\n#{$!.message}"
64
+ end
65
+ end
66
+
67
+ # Cache
68
+
69
+ def self.in_cache(url, options = {})
70
+ digest = Digest::MD5.hexdigest(url)
71
+
72
+ filename = File.join(REMOTE_CACHEDIR, digest)
73
+ if File.exists? filename
74
+ return filename
75
+ else
76
+ nil
77
+ end
78
+ end
79
+
80
+ def self.add_cache(url, data, options = {})
81
+ digest = Digest::MD5.hexdigest(url)
82
+ Misc.sensiblewrite(File.join(REMOTE_CACHEDIR, digest), data)
83
+ end
84
+
85
+ # Grep
86
+
87
+ def self.grep(stream, grep)
88
+ case
89
+ when Array === grep
90
+ TmpFile.with_file(grep * "\n", false) do |f|
91
+ CMD.cmd("grep", "-F" => true, "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
92
+ end
93
+ else
94
+ CMD.cmd("grep '#{grep}' -", :in => stream, :pipe => true)
95
+ end
96
+ end
97
+
98
+ def self.file_open(file, grep)
99
+ if grep
100
+ grep(File.open(file), grep)
101
+ else
102
+ File.open(file)
103
+ end
104
+ end
105
+
106
+ # Decompression
107
+
108
+ def self.gunzip(stream)
109
+ if String === stream
110
+ Zlib::Inflate.inflate(stream)
111
+ else
112
+ CMD.cmd("gunzip", :pipe => true, :in => stream)
113
+ end
114
+ end
115
+
116
+ def self.unzip(stream)
117
+ TmpFile.with_file(stream.read) do |filename|
118
+ StringIO.new(CMD.cmd("unzip '{opt}' #{filename}", "-p" => true, :pipe => true).read)
119
+ end
120
+ end
121
+
122
+ # Questions
123
+
124
+ def self.remote?(file)
125
+ !! (file =~ /^(?:https?|ftp):\/\//)
126
+ end
127
+
128
+ def self.gzip?(file)
129
+ !! (file =~ /\.gz$/)
130
+ end
131
+
132
+ def self.zip?(file)
133
+ !! (file =~ /\.zip/)
134
+ end
135
+
136
+ # Open Read Write
137
+
138
+ def self.open(url, options = {})
139
+ options = Misc.add_defaults options, :noz => false
140
+
141
+ wget_options = options[:wget_options] || {}
142
+ wget_options[:nice] = options.delete(:nice)
143
+ wget_options[:nice_key] = options.delete(:nice_key)
144
+
145
+ io = case
146
+ when (not remote?(url))
147
+ file_open(url, options[:grep])
148
+ when options[:nocache]
149
+ wget(url, wget_options)
150
+ when in_cache(url)
151
+ file_open(in_cache(url), options[:grep])
152
+ else
153
+ io = wget(url, wget_options)
154
+ add_cache(url, io)
155
+ io.close
156
+ file_open(in_cache(url), options[:grep])
157
+ end
158
+ io = unzip(io) if zip? url and not options[:noz]
159
+ io = gunzip(io) if gzip? url and not options[:noz]
160
+
161
+ io
162
+ end
163
+
164
+ def self.read(file, options = {}, &block)
165
+ f = open(file, options)
166
+
167
+ if block_given?
168
+ while l = Misc.fixutf8(f.gets)
169
+ l = fixutf8(l) if l.respond_to?(:valid_encoding?) && ! l.valid_encoding?
170
+ yield l
171
+ end
172
+ else
173
+ Misc.fixutf8(f.read)
174
+ end
175
+ end
176
+
177
+ def self.write(file, content)
178
+ if String === content
179
+ File.open(file, 'w') do |f| f.write content end
180
+ else
181
+ File.open(file, 'w') do |f|
182
+ while l = content.gets
183
+ f.write l
184
+ end
185
+ end
186
+ content.close
187
+ end
188
+ end
189
+ end
190
+
191
+ if __FILE__ == $0
192
+ require 'benchmark'
193
+ require 'progress-monitor'
194
+
195
+ file = '/home/mvazquezg/rbbt/data/dbs/entrez/gene_info'
196
+ puts Benchmark.measure {
197
+ #Open.open(file).read.split(/\n/).each do |l| l end
198
+ Open.read(file) do |l| l end
199
+ }
200
+ end
@@ -0,0 +1,78 @@
1
+ require 'yaml'
2
+
3
+ module PKGConfig
4
+ class NoConfig < Exception; end
5
+ class NoVariables < Exception; end
6
+
7
+ class RootdirNotFoundError < StandardError; end
8
+
9
+ def self.rootdir_for_file(file = __FILE__)
10
+ dir = File.expand_path(File.dirname file)
11
+
12
+ while not File.exists?(File.join(dir, 'lib')) and dir != '/'
13
+ dir = File.dirname(dir)
14
+ end
15
+
16
+ if File.exists? File.join(dir, 'lib')
17
+ dir
18
+ else
19
+ raise RootdirNotFoundError
20
+ end
21
+ end
22
+
23
+ def self.get_caller_rootdir
24
+ caller.each do |line|
25
+ next if line =~ /\/pkg_config\.rb/
26
+ begin
27
+ return PKGConfig.rootdir_for_file(line)
28
+ rescue RootdirNotFoundError
29
+ end
30
+ end
31
+ raise RootdirNotFoundError
32
+ end
33
+
34
+
35
+ def self.extended(base)
36
+ base.module_eval{ @@rootdir = PKGConfig.get_caller_rootdir}
37
+ end
38
+
39
+ def rootdir
40
+ @@rootdir
41
+ end
42
+
43
+ def load_config(file, pkg_variables)
44
+ config = YAML.load_file(file)
45
+
46
+ pkg_variables.each do |variable|
47
+ self.send("#{variable}=", config[variable])
48
+ end
49
+ end
50
+
51
+ def load_cfg(pkg_variables, default = nil)
52
+ pkg_cfg_files = [ ENV['RBBT_CONFIG'] || "",
53
+ File.join(ENV["HOME"], '.' + self.to_s),
54
+ File.join('/etc/', '.' + self.to_s)]
55
+
56
+ pkg_variables.each do |variable|
57
+ self.class_eval %{
58
+ def self.#{variable}
59
+ @#{variable}
60
+ end
61
+ def self.#{variable}=(value)
62
+ @#{variable} = value
63
+ end
64
+ }
65
+ end
66
+
67
+ file = pkg_cfg_files.select{|file| File.exists? file}.first
68
+ if file.nil?
69
+ if default
70
+ file = pkg_cfg_files[1]
71
+ Open.write(file, default)
72
+ else
73
+ raise NoConfig, "No config file found. [#{pkg_cfg_files * ", "}]" if file.nil?
74
+ end
75
+ end
76
+ load_config file, pkg_variables
77
+ end
78
+ end
@@ -0,0 +1,110 @@
1
+ require 'rbbt/util/open'
2
+ require 'rbbt/util/tsv'
3
+ require 'rbbt/util/log'
4
+ require 'rake'
5
+
6
+ module PKGData
7
+ FILES = {} unless defined? FILES
8
+ class SharedirNotFoundError < StandardError; end
9
+
10
+ def self.sharedir_for_file(file = __FILE__)
11
+ dir = File.expand_path(File.dirname file)
12
+
13
+ while not File.exists?(File.join(dir, 'lib')) and dir != '/'
14
+ dir = File.dirname(dir)
15
+ end
16
+
17
+ if File.exists? File.join(dir, 'lib')
18
+ File.join(dir, 'share')
19
+ else
20
+ raise SharedirNotFoundError
21
+ end
22
+ end
23
+
24
+ def self.get_caller_sharedir
25
+ caller.each do |line|
26
+ next if line =~ /\/data_module\.rb/ or line =~ /\/pkg_data\.rb/
27
+ begin
28
+ return PKGData.sharedir_for_file(line)
29
+ rescue SharedirNotFoundError
30
+ end
31
+ end
32
+ raise SharedirNotFoundError
33
+ end
34
+
35
+ def run_rake(path, dir, task = nil)
36
+ rakefile = File.join(dir, 'Rakefile')
37
+ return nil unless File.exists? rakefile
38
+ if task.nil?
39
+ task ||= :default
40
+ else
41
+ task.sub!(/\/$/,'') if String === task
42
+ path = File.dirname(path)
43
+ end
44
+
45
+ load rakefile
46
+ old_dir = FileUtils.pwd
47
+ begin
48
+ FileUtils.mkdir_p path
49
+ FileUtils.chdir path
50
+ Rake::Task[task].invoke
51
+ Rake::Task[task].reenable
52
+ ensure
53
+ FileUtils.chdir old_dir
54
+ end
55
+ true
56
+ end
57
+
58
+ def get_datafile(file, path, get, sharedir)
59
+ Log.log "Getting data file '#{ file }' into '#{ path }'. Get: #{get.to_s}"
60
+
61
+ FileUtils.mkdir_p File.dirname(path) unless File.exists?(File.dirname(path))
62
+
63
+ case
64
+ when get.nil?
65
+ load File.join(sharedir, 'install', file)
66
+
67
+ when Proc === get
68
+ Open.write(path, get.call(file, path))
69
+
70
+ when TSV === get
71
+ Open.write(path, get.to_s)
72
+
73
+ when String === get
74
+ install_dir =File.expand_path(File.join(sharedir, 'install'))
75
+ rake_dir = File.join(install_dir, File.dirname(get), file)
76
+ rake_task = nil
77
+
78
+ until rake_dir == install_dir
79
+ return if run_rake(path, rake_dir, rake_task)
80
+ rake_task = File.join(File.basename(rake_dir), rake_task || "")
81
+ rake_dir = File.dirname(rake_dir)
82
+ end
83
+
84
+ if (File.exists?(File.join(sharedir, get)) and not File.directory?(File.join(sharedir, get)))
85
+ Open.write(path, Open.open(File.join(sharedir, get)))
86
+ else
87
+ Open.write(path, Open.open(get, :wget_options => {:pipe => true}, :nocache => true))
88
+ end
89
+ end
90
+ end
91
+
92
+ def add_datafiles(files = {})
93
+ files.each do |file, info|
94
+ subpath, get, sharedir = info
95
+
96
+ path = File.join(datadir, subpath.to_s, file.to_s)
97
+
98
+ if not File.exists?(path)
99
+ sharedir ||= PKGData.get_caller_sharedir
100
+ get_datafile(file.to_s, path, get, sharedir)
101
+ end
102
+
103
+ FILES[file.to_s] = path
104
+ end
105
+ end
106
+
107
+ def find_datafile(file)
108
+ FILES[file.to_s]
109
+ end
110
+ end
@@ -0,0 +1,130 @@
1
+ require 'rbbt/util/open'
2
+ require 'rbbt/util/tsv'
3
+ require 'rbbt/util/log'
4
+ require 'rbbt/util/cmd'
5
+ require 'rake'
6
+
7
+ module PKGSoftware
8
+ SOFTWARE = {} unless defined? SOFTWARE
9
+
10
+ class SharedirNotFoundError < StandardError; end
11
+
12
+ def self.sharedir_for_file(file = __FILE__)
13
+ dir = File.expand_path(File.dirname file)
14
+
15
+ while not File.exists?(File.join(dir, 'lib')) and dir != '/'
16
+ dir = File.dirname(dir)
17
+ end
18
+
19
+ if File.exists? File.join(dir, 'lib')
20
+ File.join(dir, 'share')
21
+ else
22
+ raise SharedirNotFoundError
23
+ end
24
+ end
25
+
26
+ def self.get_caller_sharedir
27
+ caller.each do |line|
28
+ next if line =~ /\/data_module\.rb/ or line =~ /\/pkg_software\.rb/
29
+ begin
30
+ return PKGData.sharedir_for_file(line)
31
+ rescue SharedirNotFoundError
32
+ end
33
+ end
34
+ raise SharedirNotFoundError
35
+ end
36
+
37
+ def software_dir
38
+ File.join(datadir, 'software')
39
+ end
40
+
41
+ def opt_dir
42
+ File.join(software_dir, 'opt')
43
+ end
44
+
45
+ def bin_dir
46
+ File.join(opt_dir, 'bin')
47
+ end
48
+
49
+
50
+ def get_pkg(pkg, path, get, sharedir)
51
+ Log.log "Getting software '#{ pkg }' into '#{ path }'. Get: #{get.to_s}"
52
+
53
+ FileUtils.mkdir_p File.dirname(path) unless File.exists?(File.dirname(path))
54
+
55
+ if get.nil? or get.empty?
56
+ CMD.cmd("#{File.join(sharedir, 'install', 'software', pkg)} #{File.join(Rbbt.rootdir, 'share/install/software/lib', 'install_helpers')} #{software_dir}", :stderr => Log::HIGH)
57
+ else
58
+ CMD.cmd("#{File.join(sharedir, 'install', 'software', get)} #{File.join(Rbbt.rootdir, 'share/install/software/lib', 'install_helpers')} #{software_dir}")
59
+ end
60
+ end
61
+
62
+ def add_software(pkgs = {})
63
+ pkgs.each do |pkg, info|
64
+ subpath, get, sharedir = info
65
+
66
+ setup_env(software_dir)
67
+
68
+ path = File.join(opt_dir, subpath.to_s, pkg.to_s)
69
+
70
+ if not File.exists?(path)
71
+ sharedir ||= PKGSoftware.get_caller_sharedir
72
+ get_pkg(pkg.to_s, path, get, sharedir)
73
+ end
74
+
75
+ SOFTWARE[pkg.to_s] = path
76
+ end
77
+ end
78
+
79
+ def find_software(pkg)
80
+ SOFTWARE[pkg.to_s]
81
+ end
82
+
83
+
84
+ def setup_env(software_dir)
85
+ Misc.env_add 'PATH', bin_dir
86
+
87
+ FileUtils.mkdir_p opt_dir unless File.exists? opt_dir
88
+ %w(.ld-paths .pkgconfig-paths .aclocal-paths .java-classpaths).each do |file|
89
+ filename = File.join(opt_dir, file)
90
+ FileUtils.touch filename unless File.exists? filename
91
+ end
92
+
93
+ if not File.exists? File.join(opt_dir,'.post_install')
94
+ Open.write(File.join(opt_dir,'.post_install'),"#!/bin/bash\n")
95
+ end
96
+
97
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
98
+ Misc.env_add('LD_LIBRARY_PATH',line.chomp)
99
+ Misc.env_add('LD_RUN_PATH',line.chomp)
100
+ end
101
+
102
+ Open.read(File.join opt_dir, '.pkgconfig-paths').split(/\n/).each do |line|
103
+ Misc.env_add('PKG_CONFIG_PATH',line.chomp)
104
+ end
105
+
106
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
107
+ Misc.env_add('LD_LIBRARY_PATH',line.chomp)
108
+ end
109
+
110
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
111
+ Misc.env_add('LD_LIBRARY_PATH',line.chomp)
112
+ end
113
+
114
+ Open.read(File.join opt_dir, '.aclocal-paths').split(/\n/).each do |line|
115
+ Misc.env_add('ACLOCAL_FLAGS', "-I#{File.join(opt_dir, line.chomp)}", ' ')
116
+ end
117
+
118
+ Open.read(File.join opt_dir, '.java-classpaths').split(/\n/).each do |line|
119
+ Misc.env_add('CLASSPATH', "#{File.join(opt_dir,'java', 'lib', line.chomp)}")
120
+ end
121
+
122
+ Dir.glob(File.join opt_dir, 'jars', '*').each do |file|
123
+ Misc.env_add('CLASSPATH', "#{File.expand_path(file)}")
124
+ end
125
+
126
+ File.chmod 0774, File.join(opt_dir, '.post_install')
127
+
128
+ CMD.cmd(File.join(opt_dir, '.post_install'))
129
+ end
130
+ end
@@ -0,0 +1,92 @@
1
+ # This class helps designing DSL in ruby based on method_missing. Class
2
+ # is initialize with a block of code or a file with the code, and it is
3
+ # given a method to be invoked instead of method missing. This class
4
+ # deals simply with making the method_missing alias and removing it and
5
+ # executing the block of file with code.
6
+ module SimpleDSL
7
+
8
+ class ConfigFileMissingError < StandardError; end
9
+ class NoRuby2Ruby < StandardError; end
10
+
11
+ private
12
+
13
+ def hook_method(method = nil)
14
+ method ||= :DSL_action
15
+ @@restore_name = ("restore_DSL_" + method.to_s).to_sym
16
+ @@method_name = method.to_sym
17
+
18
+ class << self
19
+ @restore_stack ||= []
20
+ @restore_stack << @@restore_name
21
+ alias_method(@@restore_name, :method_missing)
22
+ alias_method(:method_missing, @@method_name)
23
+ end
24
+ end
25
+
26
+ def unhook_method
27
+ class << self
28
+ alias_method(:method_missing, @restore_stack.pop)
29
+ end
30
+ end
31
+
32
+ public
33
+
34
+ def parse(method = nil, actions = nil, &block)
35
+
36
+ actions ||= block
37
+
38
+ hook_method(method)
39
+
40
+ # Execute
41
+ if actions.is_a? Proc
42
+ begin
43
+ require 'parse_tree_extensions'
44
+ require 'parse_tree'
45
+ require 'ruby2ruby'
46
+ @config[@@method_name] = actions.to_ruby.collect[1..-2].join
47
+ rescue Exception
48
+ @config[@@method_name] = NoRuby2Ruby.new "The gem ruby2ruby is not installed. It will not work on ruby 1.9."
49
+ end
50
+
51
+ instance_eval &actions
52
+ elsif File.exists?(actions)
53
+
54
+ @config[@@method_name] = File.open(actions).read
55
+
56
+ eval File.open(actions).read
57
+ end
58
+
59
+ unhook_method
60
+
61
+ end
62
+
63
+
64
+ # Processes a DSL. +method+ is the name of the method executed instead
65
+ # of method_missing. The code to be evaluated as a DSL is either
66
+ # specified in +&block+ or in the file pointed by +file+.
67
+ def load_config(method = nil, file = nil, &block)
68
+ @config = {}
69
+ if file
70
+ raise ConfigFileMissingError.new "File '#{ file }' is missing. Have you installed the config files? (use rbbt_config)." unless File.exists? file
71
+ parse(method, file)
72
+ end
73
+
74
+ if block
75
+ parse(method, block)
76
+ end
77
+ end
78
+
79
+ def config(action = nil)
80
+ if action
81
+ config = @config[action.to_sym]
82
+ else
83
+ config = @config[:DSL_action]
84
+ end
85
+
86
+ raise config if NoRuby2Ruby === config
87
+
88
+ config
89
+ end
90
+ end
91
+
92
+
@@ -0,0 +1,56 @@
1
+ module SOPT
2
+ def self.name(info)
3
+ (info[:long] || info[:short]).sub(/^-*/,'')
4
+ end
5
+
6
+ def self.parse(opts)
7
+ info = {}
8
+ opts.split(/:/).each do |opt|
9
+ short, long = opt.sub(/\*$/,'').split('--').values_at(0,1)
10
+ i= {
11
+ :arg => !opt.match(/\*$/).nil?,
12
+ }
13
+ i[:short] = short unless short.nil? || short.empty?
14
+ i[:long] = '--' + long unless long.nil? || long.empty?
15
+ info[name(i)] = i
16
+ end
17
+
18
+ info
19
+ end
20
+
21
+ def self.get(opts)
22
+ info = parse(opts)
23
+
24
+ switches = {}
25
+ info.each do |name, i|
26
+ switches[i[:short]] = name if i[:short]
27
+ switches[i[:long]] = name if i[:long]
28
+ end
29
+
30
+ options = Hash.new(false)
31
+ rest = []
32
+
33
+ index = 0
34
+ while index < ARGV.length do
35
+ arg = ARGV[index]
36
+ if switches.include? arg
37
+ name = switches[arg]
38
+ i = info[name]
39
+ if i[:arg]
40
+ options[name.to_sym] = ARGV[index + 1]
41
+ index += 1
42
+ else
43
+ options[name.to_sym] = true
44
+ end
45
+ else
46
+ rest << arg
47
+ end
48
+ index += 1
49
+ end
50
+
51
+ ARGV.delete_if do true end
52
+ rest.each do |e| ARGV << e end
53
+
54
+ options
55
+ end
56
+ end