miniflow 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a891bee3c3d611ddca2990643196bae2bd0c9b545e3234e3b67acb68e9661cf6
4
+ data.tar.gz: 1ce90004f51af85a58dce4e72fb59812d0714302967216b227b61d12901e934c
5
+ SHA512:
6
+ metadata.gz: ded8fa695a81f5021eb916943a718fdc0ea31efbe2ad8457fb50be66d43975e0254258a1b92243a7c0ec245f1314072d2e1403aa5fe10f5d9183731229708bb4
7
+ data.tar.gz: fbdf6fbf13522d926b80c441ba912a0e8cabf47f4f878108435fd605df4c010c2a8c5d11583ba32d4af3c83b9a637eb69fd95dc3c8e61c3ace22bb6ccb12a036
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 kojix2
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # Miniflow
2
+
3
+ A very small tool to help you execute workflows
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'miniflow/version'
4
+ require_relative 'miniflow/tty_command'
5
+ require_relative 'miniflow/filecheck'
6
+ require_relative 'miniflow/flow'
7
+ require_relative 'miniflow/tool'
8
+
9
+ module Miniflow
10
+ TTYCMD = TTYCommand.new
11
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module Miniflow
6
+ module FileCheck
7
+ module_function
8
+
9
+ # Checks that the file exists and that the extension is correct.
10
+ # @params path [String] The path to the file to check if it exists
11
+ # @params extnames [Array, String] File extensions to check.
12
+ # Multiple extensions can be specified in an array.
13
+ def check_file(path, extnames)
14
+ check_file_extname(path, extnames)
15
+ check_file_exist(path)
16
+ end
17
+
18
+ # Checks if the file exists in the specified path.
19
+ # @params path [String] The path to the file to check if it exists.
20
+ def check_file_exist(path)
21
+ raise "Cannot find: #{path}" unless File.exist?(path)
22
+ end
23
+
24
+ # Make sure that the file has the specified extension.
25
+ # @params path [String] The path to the file.
26
+ # @params extnames [Array, String] File extensions to check.
27
+ def check_file_extname(path, extnames)
28
+ case extnames
29
+ when Array
30
+ raise "Extension is not #{extnames}: #{path}" unless extnames.include?(File.extname(path))
31
+ when File.extname(path)
32
+ true
33
+ else
34
+ raise "Extension is not #{extnames}: #{path}"
35
+ end
36
+ end
37
+
38
+ # Creates a directory and all its parent directories.
39
+ def mkdir_p(*arg)
40
+ FileUtils.mkdir_p(*arg)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-tree'
4
+ require 'tty-screen'
5
+
6
+ module Miniflow
7
+ # Base class for all flows in Miniflow
8
+ # The input file must be specified as an absolute path.
9
+ # Each flow has one output directory
10
+ class Flow
11
+ include FileCheck
12
+
13
+ # Define the initialize method according to the following rules
14
+ # * Take file paths as arguments. The file paths can be either absolute or
15
+ # relative.
16
+ # * Other arguments are keyword arguments.
17
+ def initialize
18
+ raise NotImplementedError
19
+ end
20
+
21
+ def cmd
22
+ TTYCMD
23
+ end
24
+
25
+ # This section is mainly for file validation.
26
+ def before_run; end
27
+
28
+ # This section is mainly used to validate the generated files, display
29
+ # runtime information, etc.
30
+ def after_run
31
+ check_output_files
32
+ show_results
33
+ end
34
+
35
+ # The main process. It must be implemented.
36
+ def main_run
37
+ raise NotImplementedError
38
+ end
39
+
40
+ # If you have a reason, you can overwrite it.
41
+ # Normally, you should not change it.
42
+ def run
43
+ show_start
44
+ before_run
45
+ main_run
46
+ after_run
47
+ rescue TTY::Command::ExitError => e
48
+ show_exit_error
49
+ raise e
50
+ rescue Errno::ENOENT => e # Maybe we should expand the scope of the error.
51
+ show_exit_error
52
+ raise e
53
+ end
54
+
55
+ # Show the banner when the workflow starts.
56
+ def show_start
57
+ @start_time = Time.now
58
+ puts TTY::Box.frame(self.class.name,
59
+ "Start : #{@start_time}",
60
+ width: TTY::Screen.width, padding: 1,
61
+ border: { left: false, right: false })
62
+ end
63
+
64
+ # Show the banner when the workflow is finished.
65
+ def show_results(generated_files: true)
66
+ @end_time = Time.now
67
+ tree = if generated_files
68
+ [' ',
69
+ "Generated files: #{@out_dir}",
70
+ ' ',
71
+ TTY::Tree.new(@out_dir).render]
72
+ else
73
+ ''
74
+ end
75
+ puts
76
+ puts TTY::Box.frame("Start : #{@start_time}",
77
+ "End : #{@end_time}",
78
+ "Time : #{@end_time - @start_time} sec",
79
+ *tree,
80
+ title: { top_left: " #{self.class.name} " },
81
+ width: TTY::Screen.width, padding: 1)
82
+ end
83
+
84
+ # Show the banner when an error occurs and the workflow is abnormally interrupted.
85
+ def show_exit_error
86
+ @end_time = Time.now
87
+ puts TTY::Box.error(
88
+ "Flow : #{self.class.name}\n" \
89
+ "Start : #{@start_time}\n" \
90
+ "End : #{@end_time}\n" \
91
+ "Time : #{@end_time - @start_time} sec",
92
+ width: TTY::Screen.width, padding: 1
93
+ )
94
+ end
95
+
96
+ # Returns the path in the output directory.
97
+ # The file path is recorded. When the workflow is finished, the output
98
+ # files are checked for existence in the `check_output_files` method.
99
+ def odir(file_name)
100
+ @output_files ||= []
101
+ file_path = File.join(@out_dir, file_name)
102
+ @output_files << file_path
103
+ file_path
104
+ end
105
+
106
+ # Returns the path in the output directory.
107
+ def dir(file_name)
108
+ File.join(@out_dir, file_name)
109
+ end
110
+
111
+ # When the workflow is finished, make sure that all the registered output
112
+ # files are present.Currently, the error does not occur even if the output
113
+ # file does not exist. A warning will be shown.
114
+ def check_output_files
115
+ return if @output_files.nil?
116
+
117
+ flag = true
118
+ @output_files.uniq.each do |file_path|
119
+ unless File.exist?(file_path)
120
+ warn "Output file not found: #{file_path}"
121
+ flag = false
122
+ end
123
+ end
124
+ puts 'All output file exist.' if flag
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-box'
4
+ require 'tty-screen'
5
+
6
+ module Miniflow
7
+ # Burrow-Wheeler Aligner for short-read alignment.
8
+ class Tool
9
+ include FileCheck
10
+
11
+ # Use the version options to check if the command is available
12
+ def available?(command)
13
+ # puts Pastel.new.magenta("Check #{self.class.name}")
14
+ pastel = Pastel.new
15
+ class_name = self.class.name.split('::').last
16
+ begin
17
+ result = cmd.run!(command)
18
+ rescue Errno::ENOENT => e
19
+ pastel = Pastel.new
20
+ msg = "\n" \
21
+ "Please make sure that the #{class_name} is available.\n\n"
22
+ e.message << msg
23
+ raise e
24
+ end
25
+ if result.failure?
26
+ msg = "The exit status of #{command} is not zero.\n" \
27
+ "Please make sure that the #{command} is available.\n\n"
28
+ raise Errno::ENOENT, msg # FIXME
29
+ else
30
+ puts pastel.green.bold("✔ #{class_name}")
31
+ end
32
+ end
33
+
34
+ # Get tool options
35
+ def [](key)
36
+ @options[key]
37
+ end
38
+
39
+ def cmd
40
+ TTYCMD
41
+ end
42
+
43
+ # Calling the Ruby method executes a subcommand with the same name.
44
+ # Since the Ruby methods are called first, care must be taken to avoid
45
+ # name collisions. For example, subcommands such as `call` need to be
46
+ # redefined.
47
+ def method_missing(name, *args)
48
+ cmd.run2(@command, name, *args)
49
+ end
50
+
51
+ # respond_to_missing?(sym, include_private)g
52
+ # end
53
+ end
54
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-command'
4
+
5
+ module Miniflow
6
+ # Miniflow uses tty-command to execute the command.
7
+ # Please see the following website for more information.
8
+ # https://ttytoolkit.org/
9
+ class TTYCommand < TTY::Command
10
+ # TTY::Command custom printer
11
+ # * change default colors.
12
+ # https://github.com/piotrmurach/tty-command#34-custom-printer
13
+ class CustomPretty < Printers::Pretty
14
+ def print_command_start(cmd, *args)
15
+ message = ["Running #{decorate(cmd.to_command, :cyan)}"]
16
+ message << args.map(&:chomp).join(' ') unless args.empty?
17
+ write(cmd, message.join)
18
+ end
19
+
20
+ def print_command_err_data(cmd, *args)
21
+ message = args.map(&:chomp).join(' ')
22
+ write(cmd, "\t#{decorate(message, :white)}", err_data)
23
+ end
24
+
25
+ def write(cmd, message, data = nil)
26
+ cmd_set_uuid = cmd.options.fetch(:uuid, true)
27
+ uuid_needed = cmd.options[:uuid].nil? ? @uuid : cmd_set_uuid
28
+ out = []
29
+ out << "[#{decorate(cmd.uuid, :green)}] " if uuid_needed && !cmd.uuid.nil?
30
+ out << "#{message}\n"
31
+ target = cmd.only_output_on_error && !data.nil? ? data : output
32
+ target << out.join
33
+ end
34
+ end
35
+
36
+ def initialize(*args)
37
+ # Do not output uuid
38
+ super(*args, printer: CustomPretty, uuid: true)
39
+ end
40
+
41
+ # run2 can execute the command in which the UNIX pipeline is used.
42
+ def run2(*args)
43
+ args.map!(&:to_s)
44
+ command = args.join(' ')
45
+ if include_meta_character?(command)
46
+ run(command)
47
+ else
48
+ run(*args)
49
+ end
50
+ end
51
+
52
+ def include_meta_character?(str)
53
+ ['*', '?', '{', '}', '[', ']', '<', '>', '(', ')', '~', '&', '|', '\\',
54
+ '$', ';', "'", '`', '"', "\n"].any? { |i| str.include?(i) }
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Miniflow
4
+ VERSION = '0.0.1'
5
+ end
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: miniflow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - kojix2
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tty-box
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-command
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-screen
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tty-tree
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: A very small tool to help you execute workflows
154
+ email:
155
+ - 2xijok@gmail.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - LICENSE.txt
161
+ - README.md
162
+ - lib/miniflow.rb
163
+ - lib/miniflow/filecheck.rb
164
+ - lib/miniflow/flow.rb
165
+ - lib/miniflow/tool.rb
166
+ - lib/miniflow/tty_command.rb
167
+ - lib/miniflow/version.rb
168
+ homepage: https://github.com/kojix2/miniflow
169
+ licenses:
170
+ - MIT
171
+ metadata: {}
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: 2.4.0
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubygems_version: 3.1.4
188
+ signing_key:
189
+ specification_version: 4
190
+ summary: A very small tool to help you execute workflows
191
+ test_files: []