expect-pty 0.7.3 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +3 -3
- data/docs/API.md +1 -0
- data/lib/expect/interaction.rb +3 -1
- data/lib/expect/matcher.rb +5 -4
- data/lib/expect/redactor.rb +17 -7
- data/lib/expect/session.rb +6 -0
- data/lib/expect/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2b48d4fb81d2c6f7035133387df5641fb420b5c108e7257c2348f4ad119edecf
|
|
4
|
+
data.tar.gz: c6dcfa0a5edc30db418739decdaa262a480e905a234ddf179c67c609edac56a4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a310e67d4303ebc2d9a2db7231722ab59b52a46bca2cf1aa32a1abd0de63a956867c17f4013df5029d21e4df509c8c6980fcc4193484f1e485b84e0933dff64
|
|
7
|
+
data.tar.gz: 19a972f1e1c19a64ba9b18f2148d0436c2f0a4211261f4a3396447b5863d8e6ac9e8f30322cb28e92ef45a5e8801dc519593c6a82044dacb42fe33b0ed17b1e0
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.7.4 - 2026-10-06
|
|
6
|
+
|
|
7
|
+
- **连续匹配**:修复回调中嵌套读取相同内容的新消息后漏触发匹配、最终超时的问题,保留零宽匹配和同值赋回的防空转保护。
|
|
8
|
+
- **大缓冲转接**:降低已积累大量输出时的转接耗时与 GC 压力,保持完整交付、结果快照和失败续发行为。
|
|
9
|
+
- **流式脱敏**:减少长短秘密混合、细粒度分片时的重复扫描和临时对象,保留规则更新、跨块重叠及已有掩码。
|
|
10
|
+
|
|
5
11
|
## 0.7.3 - 2026-10-06
|
|
6
12
|
|
|
7
13
|
- **转义连续性**:匹配消费、显式缓冲替换/清空及实际窗口裁剪后清除旧正则历史,避免跨过已消费输入误拼转义并吞字节;内部交接及非消费匹配保留连续历史。
|
data/README.md
CHANGED
|
@@ -17,7 +17,7 @@ RubyGems/Bundler 解析。推荐入口 **`require "expect/pty"`**;本项目提
|
|
|
17
17
|
项目和仓库名为 `expect-ruby`,Gem 名为 `expect-pty`。在应用的 Gemfile 中添加以下内容,然后运行 `bundle install`:
|
|
18
18
|
|
|
19
19
|
```ruby
|
|
20
|
-
gem "expect-pty", "~> 0.7.
|
|
20
|
+
gem "expect-pty", "~> 0.7.4", require: "expect/pty"
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
也可直接执行 `gem install expect-pty`。需要跟随开发分支时,可从 GitHub 安装:
|
|
@@ -30,8 +30,8 @@ gem "expect-pty", git: "https://github.com/gatework/expect-ruby.git", branch: "m
|
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
32
|
mkdir -p tmp
|
|
33
|
-
gem build expect-pty.gemspec --output tmp/expect-pty-0.7.
|
|
34
|
-
gem install ./tmp/expect-pty-0.7.
|
|
33
|
+
gem build expect-pty.gemspec --output tmp/expect-pty-0.7.4.gem
|
|
34
|
+
gem install ./tmp/expect-pty-0.7.4.gem
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
```ruby
|
data/docs/API.md
CHANGED
|
@@ -49,6 +49,7 @@ result => { number:, captures: }
|
|
|
49
49
|
`reset_timeout: false` 保持原相对期限。全部 EOF 后直接返回 EOF;已处理的来源不再参与超时。
|
|
50
50
|
|
|
51
51
|
`consume: false` 仅在本轮保留完整匹配缓冲;继续但不改变缓冲的模式暂停到输入变化,避免反复触发。
|
|
52
|
+
回调中的嵌套等待实际读入新字节时,即使缓冲内容与之前相同也会恢复匹配;仅同值赋回缓冲不算新输入。
|
|
52
53
|
`reset_timeout_on_read: true` 使每次读取重置本轮相对期限。`deadline` 是单调时钟绝对秒数,不被输入或回调延长。
|
|
53
54
|
IO 期限不打断用户代码或单次正则;不可信正则应使用 Ruby `Regexp` 自身的 timeout。
|
|
54
55
|
|
data/lib/expect/interaction.rb
CHANGED
|
@@ -111,7 +111,9 @@ module Expect
|
|
|
111
111
|
trim_history(history, buffer.byteslice(0, count), limit: session.buffer_limit || REGEXP_ESCAPE_HISTORY_LIMIT,
|
|
112
112
|
utf8: utf8_regexp)
|
|
113
113
|
end
|
|
114
|
-
|
|
114
|
+
# 排队前缀与尾部可共享原字节;替换窗口而非删除前缀,避免逐块复制整个余量。
|
|
115
|
+
# 保留缓冲对象身份,嵌套 Matcher 仍把尾部交回 Relay 借用的同一个对象。
|
|
116
|
+
buffer.replace(buffer.byteslice(count..)) if count.positive?
|
|
115
117
|
return count.positive? ? :queued : :ready
|
|
116
118
|
end
|
|
117
119
|
end
|
data/lib/expect/matcher.rb
CHANGED
|
@@ -71,7 +71,7 @@ module Expect
|
|
|
71
71
|
|
|
72
72
|
buffer = buffers ? (buffers[session] ||= session.scan_buffer) : session.scan_buffer
|
|
73
73
|
stalled = @stalled_matches[session]
|
|
74
|
-
if stalled && stalled[:buffer] != buffer
|
|
74
|
+
if stalled && (stalled[:received_bytes] != session.received_bytes || stalled[:buffer] != buffer)
|
|
75
75
|
@stalled_matches.delete(session)
|
|
76
76
|
stalled = nil
|
|
77
77
|
end
|
|
@@ -124,13 +124,14 @@ module Expect
|
|
|
124
124
|
# 先记录并消费匹配,再执行回调;回调可选择结束、重置期限或保留期限继续。
|
|
125
125
|
def handle_match(session, pattern, position)
|
|
126
126
|
previous_buffer = session.buffer
|
|
127
|
+
received_bytes = session.received_bytes
|
|
127
128
|
result = session.record_match(pattern, position, consume: @consume)
|
|
128
129
|
action = pattern.call(session)
|
|
129
130
|
return result unless continuing?(action)
|
|
130
131
|
|
|
131
|
-
#
|
|
132
|
-
if session.buffer == previous_buffer
|
|
133
|
-
stalled = (@stalled_matches[session] ||= { buffer: previous_buffer, patterns: [] })
|
|
132
|
+
# 同值赋回仍须防止空转;嵌套读取到的新字节即使内容相同,也能恢复匹配。
|
|
133
|
+
if session.received_bytes == received_bytes && session.buffer == previous_buffer
|
|
134
|
+
stalled = (@stalled_matches[session] ||= { buffer: previous_buffer, received_bytes:, patterns: [] })
|
|
134
135
|
stalled[:patterns] << pattern
|
|
135
136
|
end
|
|
136
137
|
@deadline = next_deadline if CONTINUE.equal?(action)
|
data/lib/expect/redactor.rb
CHANGED
|
@@ -32,6 +32,7 @@ module Expect
|
|
|
32
32
|
|
|
33
33
|
@patterns = patterns.map { |pattern| pattern.b.freeze }.uniq.freeze
|
|
34
34
|
@lookbehind = [(@patterns.map(&:bytesize).max || 0) - 1, 0].max
|
|
35
|
+
@scanned_bytes = 0
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
# 追加一个原始字节块,返回已经可以确定的安全前缀;新秘密可能跨越此前保留的尾部。
|
|
@@ -94,14 +95,18 @@ module Expect
|
|
|
94
95
|
end
|
|
95
96
|
end
|
|
96
97
|
|
|
97
|
-
#
|
|
98
|
-
#
|
|
98
|
+
# 每个模式只扫描可能跨越新增字节的起点;规则更新后从头重扫保留窗口。
|
|
99
|
+
# 重叠命中取并集,同一模式的相交/相邻区间只写一次,不清除旧掩码。
|
|
99
100
|
def mark_secrets
|
|
101
|
+
size = @pending.bytesize
|
|
102
|
+
return if @scanned_bytes == size
|
|
103
|
+
|
|
100
104
|
@patterns.each do |pattern|
|
|
101
|
-
|
|
105
|
+
length = pattern.bytesize
|
|
106
|
+
offset = @scanned_bytes >= length ? @scanned_bytes - length + 1 : 0
|
|
107
|
+
starting = @pending.index(pattern, offset)
|
|
102
108
|
next unless starting
|
|
103
109
|
|
|
104
|
-
length = pattern.bytesize
|
|
105
110
|
ending = starting + length
|
|
106
111
|
offset = starting
|
|
107
112
|
while (offset = @pending.index(pattern, offset + 1))
|
|
@@ -113,12 +118,15 @@ module Expect
|
|
|
113
118
|
end
|
|
114
119
|
@hidden[starting, ending - starting] = "\1" * (ending - starting)
|
|
115
120
|
end
|
|
121
|
+
@scanned_bytes = size
|
|
116
122
|
end
|
|
117
123
|
|
|
118
124
|
# 按连续区间输出,避免逐字节构造字符串;只保存尚可能与下一块组成秘密的后缀。
|
|
119
125
|
# masking 跨 append 保留,使被分成多个块的同一隐藏区间只输出一次替换标记。
|
|
120
126
|
def release(length)
|
|
121
127
|
output = "".b
|
|
128
|
+
return output if length.zero?
|
|
129
|
+
|
|
122
130
|
cursor = 0
|
|
123
131
|
while cursor < length
|
|
124
132
|
hidden = @hidden.getbyte(cursor) == 1
|
|
@@ -135,9 +143,11 @@ module Expect
|
|
|
135
143
|
end
|
|
136
144
|
cursor = ending
|
|
137
145
|
end
|
|
138
|
-
|
|
139
|
-
@
|
|
140
|
-
@
|
|
146
|
+
remaining = @pending.bytesize - length
|
|
147
|
+
@pending = @pending.byteslice(length, remaining)
|
|
148
|
+
@hidden = @hidden.byteslice(length, remaining)
|
|
149
|
+
@suppressed = @suppressed.byteslice(length, remaining) if @suppressed
|
|
150
|
+
@scanned_bytes = remaining
|
|
141
151
|
output
|
|
142
152
|
end
|
|
143
153
|
|
data/lib/expect/session.rb
CHANGED
|
@@ -145,6 +145,10 @@ module Expect
|
|
|
145
145
|
# @api private
|
|
146
146
|
def scan_buffer = @buffer
|
|
147
147
|
|
|
148
|
+
# 成功读取的累计字节数;消费、替换和移交缓冲不算新的接收进展。
|
|
149
|
+
# @api private
|
|
150
|
+
attr_reader :received_bytes
|
|
151
|
+
|
|
148
152
|
# 复制并替换原始字节缓冲,应用当前上限;调用方后续修改原字符串不会影响会话。
|
|
149
153
|
def buffer=(value)
|
|
150
154
|
raise ArgumentError, "buffer must be a String" unless value.is_a?(String)
|
|
@@ -359,6 +363,7 @@ module Expect
|
|
|
359
363
|
|
|
360
364
|
data = data.b
|
|
361
365
|
buffer << data
|
|
366
|
+
@received_bytes += data.bytesize
|
|
362
367
|
trim_buffer if trim
|
|
363
368
|
# 本块完成全部交付前不能递归读取,否则后块会抢先进入其他日志及输出目标。
|
|
364
369
|
# 回调仍可匹配已有缓冲或驱动其他会话;拒绝嵌套读取不能释放外层的保护。
|
|
@@ -388,6 +393,7 @@ module Expect
|
|
|
388
393
|
@tty_name = slave.path if slave
|
|
389
394
|
@buffer = "".b
|
|
390
395
|
@buffer_generation = 0
|
|
396
|
+
@received_bytes = 0
|
|
391
397
|
@buffer_discarded_bytes = 0
|
|
392
398
|
@outputs = []
|
|
393
399
|
@sequences = {}
|
data/lib/expect/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expect-pty
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- expect-pty contributors
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10-
|
|
10
|
+
date: 2026-10-07 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: io-console
|