expect-pty 0.3.0 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eda03bcece07a45c1c1f4f4010ae389928db6954b44624d072ce0e4249ee5a4d
4
- data.tar.gz: df16127b3002243113a3f4bb6f1945ebb5430a4a1ba614e1926f5c4be17c6a0b
3
+ metadata.gz: 67be724673aa5ba809cdba4e65b38f13edac9b1bca3be44f25981e5847d4eec7
4
+ data.tar.gz: 79837ec52929259e42f2dc7883ca4962fcf1cab5614c5d3a43f6f731892f01c5
5
5
  SHA512:
6
- metadata.gz: 0aab6a9174549cac6cbdfd33eb658b4027c6509bc9a8f246d48d76329fd9c8594e38bfc0f03430f2121bbdc82b7810f89b329c5f05051ea2657c2d0498e12825
7
- data.tar.gz: d819201280329ce39678db25c32d4657336b2e2e0288945285377b90d309e30aa616a60847024a1aeccf157eedbfd32165e6b01caba7e4c8c66b357c72656e3b
6
+ metadata.gz: c106240812e6ef1669ba2028f0a400eeeb03e26ad6bfbabb6832fb006171ff01fba37df047f0efd28d25d2320ad2a862772609bc954a9faa80361b0c8737e0b0
7
+ data.tar.gz: a09279ed617b6bc050edd1372f59321d2c6b3e89e01657a8b5d1bc576d79aa4d2c108673940df8a06c04a37af5aec2b1da658046e4b0abc0848e77751548c501
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.1 - 2026-09-26
6
+
7
+ - **安装依赖**:显式声明五个运行时标准库 gem,开发工具依赖单独管理,并补齐应用 Gemfile 中的 `require: "expect/pty"` 用法。
8
+ - **本地发布**:新增 `--rubygems-only`,可复用本机 Gem 登录单独发布 RubyGems,构建包和可重试的发布候选包统一保存到 `tmp/`。
9
+ - **安装验证**:增加普通安装和最小 Bundler 应用的依赖及 PTY 检查,发布测试覆盖本地与 CI 环境,不需要真实发布凭据。
10
+
5
11
  ## 0.3.0 - 2026-09-26
6
12
 
7
13
  - **终端模式调整**:通用 `interconnect` 改由调用方设置和恢复终端模式,需要自动切换本地输入终端时使用 `interact`,直接转接终端的现有代码需要相应调整。
data/Gemfile CHANGED
@@ -3,8 +3,24 @@
3
3
  source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
- gem "minitest", "~> 5.0"
7
- # RuboCop's worker dependency must also support the minimum Ruby version.
8
- gem "parallel", "~> 1.27", require: false
9
- gem "rake", "~> 13.0"
10
- gem "rubocop", "~> 1.89", require: false
6
+ group :development, :test do
7
+ gem "minitest", "~> 5.0", require: false
8
+ # RuboCop 的依赖也必须支持最低 Ruby 版本。
9
+ gem "parallel", "~> 1.27", require: false
10
+ gem "rake", "~> 13.0", require: false
11
+ gem "rubocop", "~> 1.89", require: false
12
+
13
+ # 测试、示例和发布工具直接使用的标准库 gem,不依赖其他开发工具间接引入。
14
+ gem "digest", require: false
15
+ gem "etc", require: false
16
+ gem "fileutils", require: false
17
+ gem "json", require: false
18
+ gem "net-http", require: false
19
+ gem "open3", require: false
20
+ gem "optparse", require: false
21
+ gem "securerandom", require: false
22
+ gem "tempfile", require: false
23
+ gem "time", require: false
24
+ gem "timeout", require: false
25
+ gem "tmpdir", require: false
26
+ end
data/README.md CHANGED
@@ -4,27 +4,28 @@
4
4
 
5
5
  用 Ruby 自动操作交互式程序:启动拥有控制终端的子进程,等待文本或正则,发送输入,处理超时、EOF 和回调,也能接管已有 IO、同时监听多个会话和转接人工交互。交互能力参考 [Expect.pm](https://github.com/jacoby/expect.pm),接口采用 Ruby 的属性、关键字参数和代码块。
6
6
 
7
- 要求 **Ruby 3.2+、POSIX 系统(Linux/macOS)**。运行时仅使用 Ruby 标准库。推荐入口 **`require "expect/pty"`**;本项目提供独立的 `Expect` 类,不修改标准库的 `IO#expect`。
7
+ 要求 **Ruby 3.2+、POSIX 系统(Linux/macOS)**。运行时仅使用 Ruby 标准库,其中可独立安装的 gem 已在 gemspec 中声明,由 RubyGems/Bundler 解析。推荐入口 **`require "expect/pty"`**;本项目提供独立的 `Expect` 类,不修改标准库的 `IO#expect`。
8
8
 
9
9
  ## 安装和运行
10
10
 
11
11
  项目和仓库名为 `expect-ruby`,Gem 名为 `expect-pty`。在应用的 Gemfile 中添加以下内容,然后运行 `bundle install`:
12
12
 
13
13
  ```ruby
14
- gem "expect-pty", "~> 0.2.0"
14
+ gem "expect-pty", "~> 0.3.1", require: "expect/pty"
15
15
  ```
16
16
 
17
17
  也可直接执行 `gem install expect-pty`。需要跟随开发分支时,可从 GitHub 安装:
18
18
 
19
19
  ```ruby
20
- gem "expect-pty", git: "https://github.com/gatework/expect-ruby.git", branch: "main"
20
+ gem "expect-pty", git: "https://github.com/gatework/expect-ruby.git", branch: "main", require: "expect/pty"
21
21
  ```
22
22
 
23
- 本地开发可改用 `gem "expect-pty", path: "/path/to/expect-ruby"`,也可在源码目录构建安装:
23
+ 本地开发可改用 `gem "expect-pty", path: "/path/to/expect-ruby", require: "expect/pty"`,也可在源码目录构建安装:
24
24
 
25
25
  ```sh
26
- gem build expect-pty.gemspec
27
- gem install ./expect-pty-0.2.0.gem
26
+ mkdir -p tmp
27
+ gem build expect-pty.gemspec --output tmp/expect-pty-0.3.1.gem
28
+ gem install ./tmp/expect-pty-0.3.1.gem
28
29
  ```
29
30
 
30
31
  ```ruby
@@ -265,7 +266,18 @@ ruby examples/ssh_interact.rb --auto
265
266
 
266
267
  [GitHub Actions](https://github.com/gatework/expect-ruby/actions/workflows/ci.yml) 在推送 `main`、推送 `v*` 标签、提交到 `main` 的 Pull Request 或手动触发时运行。流水线覆盖 Ubuntu 24.04 / macOS 15 与 Ruby 3.2、3.3、3.4、4.0 的 8 种组合;每个环境执行 `script/ci`,包括真实 PTY 测试和构建包的隔离安装验证。Ubuntu / Ruby 4.0 作业保留已验证的 Gem 构建产物 14 天,可从该次工作流的 Artifacts 下载。
267
268
 
268
- 运行前先执行 `bundle install`。Gem 库的开发锁文件 `Gemfile.lock` 保留在本地,各 Ruby 环境按 `Gemfile` 解析兼容依赖。生成文件写入已忽略的 `tmp/`,Gem 构建产物位于 `tmp/ci/`,发布候选包位于 `tmp/release/`。更新工作流中的 Action 时,应同步更新固定的提交 SHA 和版本注释。
269
+ 运行前先执行 `bundle install`。Gem 库的开发锁文件 `Gemfile.lock` 保留在本地,各 Ruby 环境按 `Gemfile` 解析兼容依赖。生成文件写入已忽略的 `tmp/`,Gem 构建产物位于 `tmp/ci/`,发布候选包位于 `tmp/release/`。安装验证会清除外部 Bundler 环境,分别运行普通 RubyGems 加载和只声明 `expect-pty` 的 Bundler 应用,检查运行时依赖、终端模式、窗口大小及真实 PTY 对话。更新工作流中的 Action 时,应同步更新固定的提交 SHA 和版本注释。
270
+
271
+ 运行时依赖只在 `expect-pty.gemspec` 声明,开发依赖放在 Gemfile 的 `development` / `test` 组;安装或使用本库不会引入 Minitest、Rake、RuboCop 及发布工具的依赖。
272
+
273
+ | 运行时模块 | Gem | 用途 |
274
+ | --- | --- | --- |
275
+ | `forwardable` | `forwardable` | 会话配置委托 |
276
+ | `io/console` | `io-console` | 终端模式和窗口大小 |
277
+ | `io/wait` | `io-wait` | IO 可读等待 |
278
+ | `shellwords` | `shellwords` | `stty` 参数拆分 |
279
+ | `stringio` | `stringio` | Ruby `puts` 语义 |
280
+ | `pty` | Ruby 自带扩展 | POSIX 伪终端,无独立 gem |
269
281
 
270
282
  仅发布 RubyGems 使用 `ruby script/release.rb --rubygems-only`,直接复用本机已有的 Gem 登录状态;添加 `--dry-run` 可先完成本地检查、测试、构建和安装验证。需要同时创建 GitHub Release 时使用 `ruby script/release.rb`,也可以在 GitHub Actions 手动运行 Release 工作流。版本准备、Actions 凭据和失败重试见 [发布说明](docs/RELEASING.md)。
271
283
 
data/docs/RELEASING.md CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  ## 准备版本
6
6
 
7
- 1. 更新 `lib/expect/version.rb` 的 `Expect::VERSION`,例如 `0.2.0`。
8
- 2. 把 `CHANGELOG.md` 的 `Unreleased` 内容移到对应版本标题下,例如 `## 0.2.0 - 2026-09-13`;可以保留空的 `Unreleased` 标题。
7
+ 1. 更新 `lib/expect/version.rb` 的 `Expect::VERSION`,例如 `0.3.1`。
8
+ 2. 把 `CHANGELOG.md` 的 `Unreleased` 内容移到对应版本标题下,例如 `## 0.3.1 - 2026-09-26`;可以保留空的 `Unreleased` 标题。
9
9
  3. 提交源码,发布时工作区必须干净。若同时发布 GitHub Release,还需推送到 `main`,远端 `main` 必须包含该提交,已有同名标签必须指向该提交。
10
10
 
11
11
  发布脚本只接受正式版 `X.Y.Z`;未归档的变更会阻止发布。
@@ -40,9 +40,9 @@ ruby script/release.rb
40
40
  GitHub Runner 不会继承本机的 Gem 登录状态。要在 Actions 发布 RubyGems,需在仓库的 Settings → Secrets and variables → Actions 中配置 `RUBYGEMS_API_KEY`,使用具有 `Push rubygem` 权限的发布 Key。
41
41
 
42
42
  ```sh
43
- git tag -a v0.2.0 -m 'Release v0.2.0'
44
- git push origin v0.2.0
45
- gh workflow run release.yml --ref v0.2.0 --repo gatework/expect-ruby
43
+ git tag -a v0.3.1 -m 'Release v0.3.1'
44
+ git push origin v0.3.1
45
+ gh workflow run release.yml --ref v0.3.1 --repo gatework/expect-ruby
46
46
  ```
47
47
 
48
48
  也可以在 Actions → Release → Run workflow 选择对应版本标签。工作流仅支持手动触发,避免本地发布时出现第二次并发上传。
@@ -56,7 +56,7 @@ gh workflow run release.yml --ref v0.2.0 --repo gatework/expect-ruby
56
56
  保留脚本输出的 `Artifact` 路径,用该候选 Gem 重试发布;更换 RubyGems 工具版本或重新构建可能得到不同字节,同一个版本不得覆盖已有内容。也可以直接指定从 CI 或 Release 下载的原包:
57
57
 
58
58
  ```sh
59
- ruby script/release.rb --rubygems-only --artifact tmp/ci/expect-pty-0.3.0.gem
59
+ ruby script/release.rb --rubygems-only --artifact tmp/ci/expect-pty-0.3.1.gem
60
60
  ```
61
61
 
62
62
  将示例路径替换为实际输出的 `Artifact` 路径。`--artifact` 会跳过构建和测试,但仍核对包与当前源码是否一致;需要同时恢复 GitHub Release 时去掉 `--rubygems-only`。
data/expect-pty.gemspec CHANGED
@@ -18,6 +18,13 @@ Gem::Specification.new do |spec|
18
18
  ".rubocop.yml", "expect-pty.gemspec", "README.md", "LICENSE", "CHANGELOG.md", "script/ci", "script/release.rb"
19
19
  ]
20
20
  spec.require_paths = ["lib"]
21
+ # 显式声明可独立升级的标准库 gem,供应用的 Bundler 解析完整运行时依赖。
22
+ # pty 是 Ruby 自带的 POSIX 扩展,不是独立 gem。
23
+ spec.add_dependency "forwardable", "~> 1.3"
24
+ spec.add_dependency "io-console", ">= 0.6", "< 1.0"
25
+ spec.add_dependency "io-wait", ">= 0.3", "< 1.0"
26
+ spec.add_dependency "shellwords", ">= 0.1", "< 1.0"
27
+ spec.add_dependency "stringio", "~> 3.0"
21
28
  spec.metadata["rubygems_mfa_required"] = "true"
22
29
  spec.metadata["source_code_uri"] = spec.homepage
23
30
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
@@ -2,5 +2,5 @@
2
2
 
3
3
  class Expect
4
4
  # Gem 与库共用的版本号;独立文件使 gemspec 无需加载完整会话实现。
5
- VERSION = "0.3.0"
5
+ VERSION = "0.3.1"
6
6
  end
data/script/ci CHANGED
@@ -17,19 +17,44 @@ gem build expect-pty.gemspec --output "$gem_file"
17
17
  # 在独立目录安装刚构建的包,避免源码路径或 Bundler 掩盖打包遗漏。
18
18
  smoke_dir="$(mktemp -d)"
19
19
  trap 'rm -rf "$smoke_dir"' EXIT
20
- gem install --local --no-document --install-dir "$smoke_dir/gems" "$gem_file"
20
+ gem_file="$(pwd)/$gem_file"
21
+ bundler_version="$(bundle exec ruby -rbundler -e 'print Bundler::VERSION')"
22
+ bundler_gem="$(bundle exec ruby -e 'print Gem.loaded_specs.fetch("bundler").cache_file')"
21
23
 
22
24
  (
23
25
  cd "$smoke_dir"
24
- unset BUNDLE_GEMFILE BUNDLE_BIN_PATH RUBYOPT RUBYLIB
26
+ # 清除 Bundler 的自动加载与路径设置;Ruby 4 还会通过 BUNDLER_SETUP 自动启用 Bundler。
27
+ for bundle_variable in ${!BUNDLE_@} ${!BUNDLER_@}; do
28
+ unset "$bundle_variable"
29
+ done
30
+ unset RUBYOPT RUBYLIB RUBYGEMS_GEMDEPS
25
31
  export GEM_HOME="$smoke_dir/gems" GEM_PATH="$smoke_dir/gems"
26
- ruby -r expect/pty -r rbconfig <<'RUBY'
32
+ gem install --local --no-document "$gem_file"
33
+
34
+ cat > smoke.rb <<'RUBY'
35
+ require "expect/pty"
36
+ require "rbconfig"
37
+
27
38
  spec = Gem.loaded_specs.fetch("expect-pty")
28
39
  # 临时目录可能经由符号链接访问,先统一为实际路径再检查。
29
40
  install_root = File.realpath(ENV.fetch("GEM_HOME"))
30
41
  abort "gem was loaded outside the isolated install" unless File.realpath(spec.full_gem_path).start_with?("#{install_root}/")
42
+ abort "Bundler leaked into the plain gem smoke" if ARGV.first == "plain" && defined?(Bundler)
43
+ unexpected = %w[minitest rake rubocop parallel].select { |name| Gem.loaded_specs.key?(name) }
44
+ abort "development dependencies leaked into the application: #{unexpected.join(', ')}" unless unexpected.empty?
45
+ spec.runtime_dependencies.each do |dependency|
46
+ loaded = Gem.loaded_specs.fetch(dependency.name)
47
+ abort "incompatible dependency: #{dependency}" unless dependency.matches_spec?(loaded)
48
+ end
49
+
50
+ # 检查实际使用的标准库已在包元数据中声明,默认 gem 可加载不能代替依赖声明。
51
+ %w[forwardable io-console io-wait shellwords stringio].each do |name|
52
+ abort "undeclared runtime dependency: #{name}" unless spec.runtime_dependencies.any? { |dependency| dependency.name == name }
53
+ end
31
54
  child = 'STDOUT.sync = true; puts "ready"; puts "reply:#{$stdin.gets&.strip}"'
32
- Expect.spawn(RbConfig.ruby, "--disable-gems", "-e", child, log_stdout: false) do |session|
55
+ Expect.spawn(RbConfig.ruby, "--disable-gems", "-e", child, raw_pty: true, log_stdout: false) do |session|
56
+ session.winsize = [30, 100]
57
+ abort "io-console terminal size failed" unless session.winsize == [30, 100]
33
58
  abort "installed gem did not receive the PTY prompt" unless session.expect("ready", timeout: 5)
34
59
 
35
60
  session.puts("expect-ruby")
@@ -38,6 +63,19 @@ Expect.spawn(RbConfig.ruby, "--disable-gems", "-e", child, log_stdout: false) do
38
63
  abort "installed gem child did not exit successfully" unless status&.success?
39
64
  end
40
65
 
41
- puts "Installed #{spec.full_name}: PTY and isolated installation passed"
66
+ puts "Installed #{spec.full_name}: #{ARGV.fetch(0)} PTY and runtime dependencies passed"
42
67
  RUBY
68
+ ruby smoke.rb plain
69
+
70
+ # 消费方仅声明当前 Gem,不能借用项目 Gemfile 中的测试和发布依赖。
71
+ # 单独安装本次开发检查使用的 Bundler,避免依赖宿主 Ruby 的默认 Bundler 副本。
72
+ if [ -f "$bundler_gem" ]; then
73
+ gem install --local --no-document "$bundler_gem"
74
+ else
75
+ gem install --no-document bundler --version "$bundler_version"
76
+ fi
77
+ export BUNDLE_IGNORE_CONFIG=true
78
+ printf 'source "https://rubygems.org"\ngem "expect-pty", "= %s", require: "expect/pty"\n' "$gem_version" > Gemfile
79
+ bundle lock --local
80
+ bundle exec ruby -rbundler -e 'Bundler.require; load "smoke.rb"' bundler
43
81
  )
data/test/process_test.rb CHANGED
@@ -36,9 +36,10 @@ class ProcessTest < ExpectTest
36
36
  assert session.slave.tty?
37
37
  session.slave.echo = false
38
38
  session.slave.winsize = [37, 111]
39
- session.spawn(RbConfig.ruby, "--disable-gems", "-rio/console", "-e",
39
+ # 子进程需要 io-console gem,保留 RubyGems 以使用 Bundler 选定的版本。
40
+ session.spawn(RbConfig.ruby, "-rio/console", "-e",
40
41
  'STDOUT.sync = true; puts STDIN.winsize.join(":"); puts STDIN.gets')
41
- assert_equal 1, session.expect("37:111", timeout: 2)
42
+ assert_equal 1, session.expect("37:111", timeout: 2), session.before.inspect
42
43
  assert_equal [37, 111], session.winsize
43
44
  session.winsize = [24, 80]
44
45
  assert_equal [24, 80], session.winsize
data/test/release_test.rb CHANGED
@@ -63,14 +63,34 @@ class ReleaseTest < Minitest::Test
63
63
  release.stub(:system, push) do
64
64
  release.stub(:github, ->(*) { flunk "RubyGems-only release contacted GitHub" }) do
65
65
  release.stub(:publish_github, -> { flunk "RubyGems-only release published to GitHub" }) do
66
- output, = capture_io { release.run }
67
- assert_includes output, "SHA256 verified"
66
+ [nil, "true"].each do |github_actions|
67
+ with_environment("GITHUB_ACTIONS" => github_actions,
68
+ "GEM_HOST_API_KEY" => (github_actions ? "test-only-api-key" : nil)) do
69
+ published = false
70
+ output, = capture_io { release.run }
71
+ assert_includes output, "SHA256 verified"
72
+ assert published
73
+ end
74
+ end
68
75
  end
69
76
  end
70
77
  end
71
78
  end
72
79
  end
73
- assert published
80
+ end
81
+ end
82
+
83
+ def test_ci_publish_requires_an_api_key_before_pushing
84
+ release = Release.new(rubygems_only: true)
85
+ release.stub(:registry_version, nil) do
86
+ release.stub(:system, ->(*) { flunk "pushed without a CI API key" }) do
87
+ [nil, ""].each do |api_key|
88
+ with_environment("GITHUB_ACTIONS" => "true", "GEM_HOST_API_KEY" => api_key) do
89
+ error = assert_raises(RuntimeError) { release.send(:publish_rubygems) }
90
+ assert_includes error.message, "RUBYGEMS_API_KEY"
91
+ end
92
+ end
93
+ end
74
94
  end
75
95
  end
76
96
 
@@ -194,6 +214,17 @@ class ReleaseTest < Minitest::Test
194
214
 
195
215
  private
196
216
 
217
+ # 发布测试显式控制凭据环境,避免本机登录状态或 CI 标记影响用例结果。
218
+ def with_environment(values)
219
+ previous = values.to_h { |name, _value| [name, ENV.fetch(name, nil)] }
220
+ begin
221
+ values.each { |name, value| ENV[name] = value }
222
+ yield
223
+ ensure
224
+ previous.each { |name, value| ENV[name] = value }
225
+ end
226
+ end
227
+
197
228
  def with_package
198
229
  Dir.mktmpdir("expect-release-test-") do |directory|
199
230
  Dir.chdir(directory) do
metadata CHANGED
@@ -1,14 +1,102 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expect-pty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - expect-pty contributors
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 2026-09-26 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: forwardable
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.3'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.3'
26
+ - !ruby/object:Gem::Dependency
27
+ name: io-console
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0.6'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '1.0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0.6'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '1.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: io-wait
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0.3'
53
+ - - "<"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.0'
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0.3'
63
+ - - "<"
64
+ - !ruby/object:Gem::Version
65
+ version: '1.0'
66
+ - !ruby/object:Gem::Dependency
67
+ name: shellwords
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0.1'
73
+ - - "<"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
83
+ - - "<"
84
+ - !ruby/object:Gem::Version
85
+ version: '1.0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: stringio
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - "~>"
91
+ - !ruby/object:Gem::Version
92
+ version: '3.0'
93
+ type: :runtime
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '3.0'
12
100
  description: Automate interactive programs with exact and regexp matching, Ruby blocks,
13
101
  multi-session waits, logging and terminal interaction.
14
102
  executables: []