em-popen3 0.0.4

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,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: []