Feature #1473
Improvements on expect.rb
| Status: | Closed | Start date: | 05/16/2009 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | % Done: | 100% |
||
| Category: | ext | |||
| Target version: | 1.9.2 |
Description
Hello, I was using expect.rb to substitute expect command (as I'm not in a mood to learn Tcl). However, it demands some attention. I took expect(1) command as a idea, but not a rule, of how expect should behave. First, a little bug that incorrect pattern classes are not treated correctly. It would result in a "e_pat unspecified" which gives no clues of what happened. Now I raise an exception. I let the another one parameter, timeout, unchecked cause the error messagem like "String can't be coerced into Fixnum" would give a good hint of what is wrong. I changed pat and e_pat to pattern to meet some other similar parameter references. Back to the timeout parameter, timeout was not a global timeout but a single char timeout. If the io keeps giving input, it never stops. For example: While using expect.rb to interact with a dlink switch telnet, if it generates any log information on the terminal (as it does constantly like "link down") before the timeout time, even if my expression never occurs, the timeout is never over. I changed this to use timeout as a global timeout as expect command does. Keeping on timeout stuff, if it read some input and times out, where this buffer goes? In expect.rb, it is just lost. For the expect command, this buffer can be used in the next matching. I use a instance variable to keep and reuse the unused buffer on the next expect call. I changed the default timeout value to meet the expect command default one. If someone really wants to use 9999999 seconds, just go ahead ans specify it on parameters. However, interactive scripts generally deal with unexpected behaviors. 30s, as expect command uses, seems to be reasonable. I also added some documentation that was missing.
Associated revisions
* ext/pty/lib/expect.rb: add rdoc. based on a patch from Luiz Angelo
Daros de Luca in [ruby-core:23464].
* ext/pty/lib/expect.rb: raise an error when argument is unexpected
type. based on a patch from Luiz Angelo Daros de Luca in
[ruby-core:23464].
* ext/pty/lib/expect.rb: preserve buffer read, instead of discard.
based on a patch from Luiz Angelo Daros de Luca in
[ruby-core:23464].
History
Updated by Ryan Davis over 2 years ago
On May 15, 2009, at 10:55 , Luiz Angelo Daros de Luca wrote: > Feature #1473: Improvements on expect.rb > http://redmine.ruby-lang.org/issues/show/1473 > > Author: Luiz Angelo Daros de Luca > Status: Open, Priority: Normal > Category: build can we pick this up? expect.rb could use some love.
Updated by Luiz Angelo Daros de Luca over 2 years ago
If no one is interested, I can try to improve expect.rb. Is there anything I
need to modify in my patch?
---
Luiz Angelo Daros de Luca, Me.
luizluca@gmail.com
2009/5/19 Ryan Davis <ryand-ruby@zenspider.com>
>
> On May 15, 2009, at 10:55 , Luiz Angelo Daros de Luca wrote:
>
> Feature #1473: Improvements on expect.rb
>> http://redmine.ruby-lang.org/issues/show/1473
>>
>> Author: Luiz Angelo Daros de Luca
>> Status: Open, Priority: Normal
>> Category: build
>>
>
> can we pick this up? expect.rb could use some love.
>
>
>
If no one is interested, I can try to improve expect.rb. Is there anything I need to modify in my patch?<br><br><br clear="all">---<br> Luiz Angelo Daros de Luca, Me.<br> <a href="mailto:luizluca@gmail.com">luizluca@gmail.com</a><br>
<br><br><div class="gmail_quote">2009/5/19 Ryan Davis <span dir="ltr"><<a href="mailto:ryand-ruby@zenspider.com">ryand-ruby@zenspider.com</a>></span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="im"><br>
On May 15, 2009, at 10:55 , Luiz Angelo Daros de Luca wrote:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Feature #1473: Improvements on expect.rb<br>
<a href="http://redmine.ruby-lang.org/issues/show/1473" target="_blank">http://redmine.ruby-lang.org/issues/show/1473</a><br>
<br>
Author: Luiz Angelo Daros de Luca<br>
Status: Open, Priority: Normal<br>
Category: build<br>
</blockquote>
<br></div>
can we pick this up? expect.rb could use some love.<br>
<br>
<br>
</blockquote></div><br>
Updated by Yusuke Endoh almost 2 years ago
- Category changed from build to ext
- Assignee set to Yusuke Endoh
Hi,
> I was using expect.rb to substitute expect command (as I'm not in a mood to learn Tcl). However, it demands some attention.
>
> I took expect(1) command as a idea, but not a rule, of how expect should behave.
Thank you for your writing a patch, and sorry for late response.
> First, a little bug that incorrect pattern classes are not treated correctly. It would result in a "e_pat unspecified" which gives no clues of what happened. Now I raise an exception.
Generally, standard library may raise unexpected error when argument
type is unexpected. It is the fate of duck typing. See #2495.
But in this case, I think it can be considered as a bug because it
explicitly dispatches on the type.
> I let the another one parameter, timeout, unchecked cause the error messagem like "String can't be coerced into Fixnum" would give a good hint of what is wrong.
I think this is a fate of duck typing.
> I changed pat and e_pat to pattern to meet some other similar parameter references.
I can't get your point.
What do you mean "some other similar parameter reference" ?
> Back to the timeout parameter, timeout was not a global timeout but a single char timeout. If the io keeps giving input, it never stops. For example: While using expect.rb to interact with a dlink switch telnet, if it generates any log information on the terminal (as it does constantly like "link down") before the timeout time, even if my expression never occurs, the timeout is never over. I changed this to use timeout as a global timeout as expect command does.
Hmm. One might expect the behavior you expected, but other might
expect the original behavior, I think.
I cannot determine, but at least, we should not delete the original
behavior in terms of compatibility.
> Keeping on timeout stuff, if it read some input and times out, where this buffer goes? In expect.rb, it is just lost. For the expect command, this buffer can be used in the next matching. I use a instance variable to keep and reuse the unused buffer on the next expect call.
It is reasonable for me, though I'm not sure whether or not your
implementation (buffering @unusedBuf) has no issue...
> I changed the default timeout value to meet the expect command default one. If someone really wants to use 9999999 seconds, just go ahead ans specify it on parameters. However, interactive scripts generally deal with unexpected behaviors. 30s, as expect command uses, seems to be reasonable.
Rejected for the compatibility reason.
> I also added some documentation that was missing.
Great, thanks.
I'll commit the following patch and close the ticket.
If there is objection, I'm happy to revert it.
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
index 08191b0..156b024 100644
--- a/ext/pty/lib/expect.rb
+++ b/ext/pty/lib/expect.rb
@@ -1,6 +1,12 @@
$expect_verbose = false
class IO
+ # Reads ios until pattern matches or the timeout is over. It returns
+ # an array with the read buffer, followed by the matches. If a block is given,
+ # the result is yielded to the block and returns nil. The optional timeout parameter defines,
+ # in seconds, the total time to wait for pattern. If it is over of eof is found, it
+ # returns/yields nil. However, the buffer in a timeout session is kept for the next expect call.
+ # The default timeout is 9999999 seconds.
def expect(pat,timeout=9999999)
buf = ''
case pat
@@ -8,13 +14,20 @@ class IO
e_pat = Regexp.new(Regexp.quote(pat))
when Regexp
e_pat = pat
+ else
+ raise ArgumentError, "unsupported pattern class: #{pattern.class}"
end
+ @unusedBuf ||= ''
while true
- if !IO.select([self],nil,nil,timeout) or eof? then
+ if not @unusedBuf.empty?
+ c = @unusedBuf.slice!(0).chr
+ elsif !IO.select([self],nil,nil,timeout) or eof? then
result = nil
+ @unusedBuf = buf
break
+ else
+ c = getc.chr
end
- c = getc.chr
buf << c
if $expect_verbose
STDOUT.print c
--
Yusuke Endoh <mame@tsg.ne.jp>
Updated by Kazuhiro NISHIYAMA almost 2 years ago
- Category set to ext
- Status changed from Open to Assigned
- Target version set to 1.9.2
Updated by Yusuke Endoh almost 2 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r27274. Luiz Angelo, thank you for reporting this issue. Your contribution to Ruby is greatly appreciated. May Ruby be with you.