em-popen3 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Njg3ZDUzYjJhNzc2YTQ2MzQ1ZmUwOWRkZTM5YTkzMjA3NmFhODlhYw==
5
+ data.tar.gz: !binary |-
6
+ MjZhOWIyNTMyMzliZDQyOTIzMjliMTkxN2IzOWU2MmYwMTc3YjA2NQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YjNkZmEwNDU5MDk3Yjg4NWU3Y2ZjZTFmNjNhODFlOTYyYzJkNGU0OTdhNTk1
10
+ MTI5MGQ5MzA4OGU4M2I4YjQwMDdiYzNhYjQ0NTVkYzQ0Y2Q5NzM5NmFlYTg2
11
+ MjFmMGQ3MTNiMjFjNGZlYzk3ZmU5ZjdmMzJjNzBiNDMyNzczZjg=
12
+ data.tar.gz: !binary |-
13
+ YWExN2JlNzQ0YWZhYWM2MTNlZWU5MTgyZDc2MDRkNzk3YTcxNGU1NGYyYWYw
14
+ N2E3ODkxNTZhMGQ1ODA1ODA3ODg0ZmRhOGNlODI4NTc5MGJiZTJhZGU5OGRh
15
+ Nzk4ODY1Y2U3NTFiYmNhZWFhNjAwYjY4ODBlZDhmODdiM2Q5NTM=
@@ -0,0 +1,5 @@
1
+ .bundle/
2
+ pkg/
3
+ *.swp
4
+ *.un~
5
+ Gemfile.lock
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@em-popen3 --create
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README ADDED
File without changes
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = "spec/*_spec.rb"
8
+ end
9
+
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'em-popen3/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'em-popen3'
6
+ s.version = EventMachine::POpen3::VERSION
7
+
8
+ s.authors = ['stask']
9
+ s.email = ['stask@kontera.com']
10
+ s.summary = "Adds popen3 support to eventmachine"
11
+ s.description = s.summary
12
+ s.rubyforge_project = 'em-popen3'
13
+
14
+ s.add_dependency 'eventmachine', '>= 1.0.0.beta.4'
15
+ s.add_dependency 'rake'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.require_paths = ['lib']
19
+ end
@@ -0,0 +1 @@
1
+ require 'em-popen3/popen3'
@@ -0,0 +1,97 @@
1
+ # --
2
+ # Author:: stask
3
+ # inspired by http://pastebin.com/TLgVF8GZ
4
+
5
+ require 'open3'
6
+
7
+ module EventMachine
8
+
9
+ # EM::popen3 is used to launch given command and capture the stdin, stdout and stderr streams.
10
+ #
11
+ # Example:
12
+ # EM.run do
13
+ # p = EM.popen3('ls', {
14
+ # :stdout => Proc.new { |data| puts "stdout: #{data}" },
15
+ # :stderr => Proc.new { |data| puts "stderr: #{data}" }
16
+ # })
17
+ # p.callback do
18
+ # puts "All good"
19
+ # end
20
+ # p.errback do |err_code|
21
+ # puts "Error: #{err_code}"
22
+ # end
23
+ # end
24
+ #
25
+ # It returns a deferrable object
26
+ def self.popen3(cmd, stream_callbacks)
27
+ raise ArgumentError, "stream_callbacks must be specified" unless stream_callbacks
28
+ raise ArgumentError, ":stdout callback must be specified" unless stream_callbacks[:stdout].is_a?(Proc)
29
+ raise ArgumentError, ":stderr callback must be specified" unless stream_callbacks[:stderr].is_a?(Proc)
30
+
31
+ POpen3::Wrapper.new(cmd, stream_callbacks)
32
+ end
33
+
34
+ private
35
+ module POpen3
36
+
37
+ class Wrapper
38
+ include EM::Deferrable
39
+ attr_accessor :pipes, :stream_callbacks
40
+
41
+ def initialize(cmd, stream_callbacks)
42
+ @pipes = {}
43
+ @stream_callbacks = stream_callbacks
44
+ @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(cmd)
45
+ @stdin_conn = EM.attach(@stdin, Handler, self, :stdin)
46
+ @stdout_conn = EM.attach(@stdout, OutHandler, self, :stdout)
47
+ @stderr_conn = EM.attach(@stderr, OutHandler, self, :stderr)
48
+ end
49
+
50
+ def send_data(data)
51
+ pipes[:stdin].send_data(data) if pipes.has_key?(:stdin)
52
+ end
53
+
54
+ def kill(signal='TERM', wait=false)
55
+ Process.kill(signal, @wait_thr.pid)
56
+ val = @wait_thr.value if wait
57
+ @stdin_conn.close_connection
58
+ @stdout_conn.close_connection
59
+ @stderr_conn.close_connection
60
+ return val
61
+ end
62
+
63
+ def unbind(name)
64
+ pipes.delete(name)
65
+ remove_instance_variable("@"+name.to_s)
66
+ if pipes.empty?
67
+ err_code = @wait_thr.value
68
+ err_code == 0 ? succeed : fail(err_code)
69
+ end
70
+ end
71
+ end
72
+
73
+ class Handler < EM::Connection
74
+ def initialize(parent, name)
75
+ @parent = parent
76
+ @name = name
77
+
78
+ @parent.pipes[@name] = self
79
+ end
80
+
81
+ def unbind
82
+ begin
83
+ @io.close unless @io.closed?
84
+ rescue Exception => e
85
+ #don't care if the stream has been closed already
86
+ end
87
+ @parent.unbind(@name)
88
+ end
89
+ end
90
+
91
+ class OutHandler < Handler
92
+ def receive_data(data)
93
+ @parent.stream_callbacks[@name].call(data) if @parent.stream_callbacks.has_key?(@name)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,5 @@
1
+ module EventMachine
2
+ module POpen3
3
+ VERSION = '0.0.4'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'bundler/setup'
4
+ require 'eventmachine'
5
+ require 'em-popen3'
@@ -0,0 +1,55 @@
1
+ $:.push File.expand_path('../../lib', __FILE__)
2
+ $:.push File.expand_path('../', __FILE__)
3
+ require 'helper'
4
+
5
+ describe EventMachine::POpen3 do
6
+ it "smokes" do
7
+ cmd = <<EOS
8
+ ruby -e "\\$stdout.sync = true; \\$stderr.sync=true; gets.to_i.times { |i| \\$stdout.puts i+1; \\$stderr.puts i+1; }"
9
+ EOS
10
+ stdout_capture = stderr_capture = ''
11
+ EM.run do
12
+ handler = EM.popen3(
13
+ cmd,
14
+ :stdout => Proc.new { |data| stdout_capture << data },
15
+ :stderr => Proc.new { |data| stderr_capture << data })
16
+ handler.callback do
17
+ 5.times do |i|
18
+ stdout_capture.must_match(/^#{i+1}$/)
19
+ stderr_capture.must_match(/^#{i+1}$/)
20
+ end
21
+ EM.stop
22
+ end
23
+ handler.errback do |err_code|
24
+ assert(false, "Failed to run command: #{err_code}")
25
+ EM.stop
26
+ end
27
+ handler.send_data("5\n")
28
+ end
29
+ end
30
+
31
+ it "can be killed" do
32
+ cmd = <<EOS
33
+ /bin/bash -l -c "trap \"echo TERM;echo 0\" SIGINT SIGTERM;sleep 10"
34
+ EOS
35
+ stdout_capture = stderr_capture = ''
36
+ EM.run do
37
+ handler = EM.popen3(
38
+ cmd,
39
+ :stdout => Proc.new { |data| stdout_capture << data },
40
+ :stderr => Proc.new { |data| stderr_capture << data }
41
+ )
42
+ handler.callback do
43
+ puts "stopped without error"
44
+ stdout_capture.must_match(/TERM/)
45
+ EM.stop
46
+ end
47
+ handler.errback do |err_code|
48
+ assert(false, "Failed to run command: #{err_code}")
49
+ EM.stop
50
+ end
51
+ EM.add_timer(1) { handler.kill('TERM', true) }
52
+ EM.add_timer(10) { assert(false, 'Failed to kill the damn thing'); EM.stop }
53
+ end
54
+ end
55
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-popen3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - stask
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: eventmachine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0.beta.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0.beta.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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
+ description: Adds popen3 support to eventmachine
42
+ email:
43
+ - stask@kontera.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .rvmrc
50
+ - Gemfile
51
+ - README
52
+ - Rakefile
53
+ - em-popen3.gemspec
54
+ - lib/em-popen3.rb
55
+ - lib/em-popen3/popen3.rb
56
+ - lib/em-popen3/version.rb
57
+ - spec/helper.rb
58
+ - spec/popen3_spec.rb
59
+ homepage:
60
+ licenses: []
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project: em-popen3
78
+ rubygems_version: 2.2.2
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Adds popen3 support to eventmachine
82
+ test_files: []