silent_stream-1.0.12/0000755000004100000410000000000015053076402014476 5ustar www-datawww-datasilent_stream-1.0.12/silent_stream.gemspec0000644000004100000410000001606615053076402020725 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: silent_stream 1.0.12 ruby lib Gem::Specification.new do |s| s.name = "silent_stream".freeze s.version = "1.0.12".freeze s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "https://github.com/galtzo-floss/silent_stream/issues", "changelog_uri" => "https://github.com/galtzo-floss/silent_stream/blob/v1.0.12/CHANGELOG.md", "discord_uri" => "https://discord.gg/3qme4XHNKN", "documentation_uri" => "https://www.rubydoc.info/gems/silent_stream/1.0.12", "funding_uri" => "https://github.com/sponsors/pboling", "homepage_uri" => "https://silent-stream.galtzo.com/", "news_uri" => "https://www.railsbling.com/tags/silent_stream", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/galtzo-floss/silent_stream/tree/v1.0.12", "wiki_uri" => "https://github.com/galtzo-floss/silent_stream/wiki" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Jeremy Daer".freeze, "David Heinemeier Hansson".freeze, "Andrew White".freeze, "Santiago Pastorino".freeze, "Sam Stephenson".freeze, "Akira Matsuda".freeze, "Raphael Lee".freeze, "Rafael Fran\u00E7a".freeze, "Mario Visic".freeze, "\u041C\u0430\u0440'\u044F\u043D \u041A\u0440\u0435\u043A\u043E\u0442\u0435\u043D\u044C".freeze, "Sergey Nartimov".freeze, "Josh Kalderimis".freeze, "Xavier Noria".freeze, "David Rodr\u00EDguez".freeze, "Dmitry Vorotilin".freeze, "Aaron Patterson".freeze, "Guillermo Iguaran".freeze, "Alexey Gaziev".freeze, "Yehuda Katz".freeze, "Tom Meier".freeze, "Pratik Naik".freeze, "Charlie Somerville".freeze, "Alex Tambellini".freeze, "Arthur Nogueira Neves".freeze, "Anil Wadghule".freeze, "Peter Boling".freeze] s.bindir = "exe".freeze s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl\nci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW\nA2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM\nDHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy\nLGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA\nuoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61\nLRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5\nmZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN\ncoEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV\nFMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj\nyGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1\nto/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD\nqbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj\nfzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ\nHlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG\nA1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD\nggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9\nwmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR\nL8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm\nGUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k\nkNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq\nQekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA\n0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p\nDVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt\nL9nRqA==\n-----END CERTIFICATE-----\n".freeze] s.date = "2025-08-21" s.description = "\u{1F515} (formerly) ActiveSupport Kernel Reporting Detritus with a few enhancementsFund overlooked open source projects - bottom of stack, dev/test dependencies: floss-funding.dev".freeze s.email = ["floss@galtzo.com".freeze] s.extra_rdoc_files = ["CHANGELOG.md".freeze, "CITATION.cff".freeze, "CODE_OF_CONDUCT.md".freeze, "CONTRIBUTING.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "REEK".freeze, "RUBOCOP.md".freeze, "SECURITY.md".freeze, "checksums/silent_stream-1.0.10.gem.sha256".freeze, "checksums/silent_stream-1.0.10.gem.sha512".freeze, "checksums/silent_stream-1.0.11.gem.sha256".freeze, "checksums/silent_stream-1.0.11.gem.sha512".freeze, "checksums/silent_stream-1.0.12.gem.sha256".freeze, "checksums/silent_stream-1.0.12.gem.sha512".freeze, "checksums/silent_stream-1.0.9.gem.sha256".freeze, "checksums/silent_stream-1.0.9.gem.sha512".freeze, "sig/silent_stream.rbs".freeze] s.files = ["CHANGELOG.md".freeze, "CITATION.cff".freeze, "CODE_OF_CONDUCT.md".freeze, "CONTRIBUTING.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "REEK".freeze, "RUBOCOP.md".freeze, "SECURITY.md".freeze, "checksums/silent_stream-1.0.10.gem.sha256".freeze, "checksums/silent_stream-1.0.10.gem.sha512".freeze, "checksums/silent_stream-1.0.11.gem.sha256".freeze, "checksums/silent_stream-1.0.11.gem.sha512".freeze, "checksums/silent_stream-1.0.12.gem.sha256".freeze, "checksums/silent_stream-1.0.12.gem.sha512".freeze, "checksums/silent_stream-1.0.9.gem.sha256".freeze, "checksums/silent_stream-1.0.9.gem.sha512".freeze, "lib/silent_stream.rb".freeze, "lib/silent_stream/version.rb".freeze, "sig/silent_stream.rbs".freeze] s.homepage = "https://github.com/galtzo-floss/silent_stream".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--title".freeze, "silent_stream - \u{1F515} (formerly) ActiveSupport's Stream Silencing - Without ActiveSupport".freeze, "--main".freeze, "checksums/**/*.sha256".freeze, "checksums/**/*.sha512".freeze, "sig/**/*.rbs".freeze, "CHANGELOG.md".freeze, "CITATION.cff".freeze, "CODE_OF_CONDUCT.md".freeze, "CONTRIBUTING.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "REEK".freeze, "RUBOCOP.md".freeze, "SECURITY.md".freeze, "--line-numbers".freeze, "--inline-source".freeze, "--quiet".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze) s.rubygems_version = "3.7.1".freeze s.summary = "\u{1F515} (formerly) ActiveSupport's Stream Silencing - Without ActiveSupport".freeze s.specification_version = 4 s.add_development_dependency(%q.freeze, ["~> 3.0".freeze]) s.add_development_dependency(%q.freeze, [">= 2.2".freeze]) s.add_development_dependency(%q.freeze, ["~> 1.0".freeze, ">= 1.0.3".freeze]) s.add_runtime_dependency(%q.freeze, ["~> 1.2".freeze]) s.add_development_dependency(%q.freeze, [">= 5.15".freeze]) s.add_development_dependency(%q.freeze, ["~> 1.7".freeze, ">= 1.7.1".freeze]) s.add_development_dependency(%q.freeze, ["~> 2.7".freeze, ">= 2.7.1".freeze]) s.add_development_dependency(%q.freeze, ["~> 13.0".freeze]) s.add_development_dependency(%q.freeze, ["~> 2.0".freeze, ">= 2.0.3".freeze]) s.add_development_dependency(%q.freeze, ["~> 1.0".freeze, ">= 1.0.3".freeze]) s.add_development_dependency(%q.freeze, ["~> 1.0".freeze]) s.add_development_dependency(%q.freeze, [">= 3.7".freeze]) s.add_runtime_dependency(%q.freeze, [">= 1.1.8".freeze, "< 3".freeze]) end silent_stream-1.0.12/RUBOCOP.md0000644000004100000410000000653115053076402016136 0ustar www-datawww-data# RuboCop Usage Guide ## Overview A tale of two RuboCop plugin gems. ### RuboCop Gradual This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file. ### RuboCop LTS This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2. RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more. ## Checking RuboCop Violations To check for RuboCop violations in this project, always use: ```bash bundle exec rake rubocop_gradual:check ``` **Do not use** the standard RuboCop commands like: - `bundle exec rubocop` - `rubocop` ## Understanding the Lock File The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to: 1. Prevent new violations while gradually fixing existing ones 2. Track progress on code style improvements 3. Ensure CI builds don't fail due to pre-existing violations ## Common Commands - **Check violations** - `bundle exec rake rubocop_gradual` - `bundle exec rake rubocop_gradual:check` - **(Safe) Autocorrect violations, and update lockfile if no new violations** - `bundle exec rake rubocop_gradual:autocorrect` - **Force update the lock file (w/o autocorrect) to match violations present in code** - `bundle exec rake rubocop_gradual:force_update` ## Workflow 1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect` a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task. 2. If there are new violations, either: - Fix them in your code - Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately) 3. Commit the updated `.rubocop_gradual.lock` file along with your changes ## Never add inline RuboCop disables Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways: - Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide. - Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow: - `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced) - If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately) In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test. ## Benefits of rubocop_gradual - Allows incremental adoption of code style rules - Prevents CI failures due to pre-existing violations - Provides a clear record of code style debt - Enables focused efforts on improving code quality over time silent_stream-1.0.12/CONTRIBUTING.md0000644000004100000410000001471715053076402016741 0ustar www-datawww-data# Contributing Bug reports and pull requests are welcome on GitHub, CodeBerg, or [GitLab][🚎src-main]. This project should be a safe, welcoming space for collaboration, so contributors agree to adhere to the [code of conduct][🤝conduct]. To submit a patch, please fork the project, create a patch with tests, and send a pull request. Remember to [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog]. ## Help out! Take a look at the `reek` list which is the file called `REEK` and find something to improve. Follow these instructions: 1. Fork the repository 2. Create a feature branch (`git checkout -b my-new-feature`) 3. Make some fixes. 4. Commit changes (`git commit -am 'Added some feature'`) 5. Push to the branch (`git push origin my-new-feature`) 6. Make sure to add tests for it. This is important, so it doesn't break in a future release. 7. Create new Pull Request. ## Appraisals From time to time the Appraisal2 gemfiles in `gemfiles/` will need to be updated. They are created and updated with the commands: ```console bin/rake appraisal:update ``` When adding an appraisal to CI check the [runner tool cache][🏃‍♂️runner-tool-cache] to see which runner to use. ## The Reek List Take a look at the `reek` list which is the file called `REEK` and find something to improve. To refresh the `reek` list: ```console bundle exec reek > REEK ``` ## Run Tests To run all tests ```console bundle exec rake test ``` ## Lint It Run all the default tasks, which includes running the gradually autocorrecting linter, `rubocop-gradual`. ```console bundle exec rake ``` Or just run the linter. ```console bundle exec rake rubocop_gradual:autocorrect ``` For more detailed information about using RuboCop in this project, please see the [RUBOCOP.md](RUBOCOP.md) guide. This project uses `rubocop_gradual` instead of vanilla RuboCop, which requires specific commands for checking violations. ### Important: Do not add inline RuboCop disables Never add `# rubocop:disable ...` / `# rubocop:enable ...` comments to code or specs (except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). Instead: - Prefer configuration-based exclusions when a rule should not apply to certain paths or files (e.g., via `.rubocop.yml`). - When a violation is temporary and you plan to fix it later, record it in `.rubocop_gradual.lock` using the gradual workflow: - `bundle exec rake rubocop_gradual:autocorrect` (preferred) - `bundle exec rake rubocop_gradual:force_update` (only when you cannot fix the violations immediately) As a general rule, fix style issues rather than ignoring them. For example, our specs should follow RSpec conventions like using `described_class` for the class under test. ## Contributors Your picture could be here! [![Contributors][🖐contributors-img]][🖐contributors] Made with [contributors-img][🖐contrib-rocks]. Also see GitLab Contributors: [https://gitlab.com/galtzo-floss/silent_stream/-/graphs/main][🚎contributors-gl] ## For Maintainers ### One-time, Per-maintainer, Setup **IMPORTANT**: If you want to sign the build you create, your public key for signing gems will need to be picked up by the line in the `gemspec` defining the `spec.cert_chain` (check the relevant ENV variables there). All releases to RubyGems.org will be signed. See: [RubyGems Security Guide][🔒️rubygems-security-guide] NOTE: To build without signing the gem you must set `SKIP_GEM_SIGNING` to some value in your environment. ### To release a new version: 1. Run `bin/setup && bin/rake` as a "test, coverage, & linting" sanity check 2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes 3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock` 4. Run `git commit -am "🔖 Prepare release v"` to commit the changes 5. Run `git push` to trigger the final CI pipeline before release, and merge PRs - NOTE: Remember to [check the build][🧪build]. 6. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME` 7. Run `git checkout $GIT_TRUNK_BRANCH_NAME` 8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure latest trunk code 9. Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use same timestamp, and generate same checksums - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH` - If the echo above has no output, then it didn't work. - Note: `zsh/datetime` module is needed, if running `zsh`. - In older versions of `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH` 10. Run `bundle exec rake build` 11. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr]) to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums` [gem][💎stone_checksums]. - The script automatically commits but does not push the checksums 12. Run `bundle exec rake release` which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems] [🚎src-main]: https://gitlab.com/galtzo-floss/silent_stream [🧪build]: https://github.com/galtzo-floss/silent_stream/actions [🤝conduct]: https://gitlab.com/galtzo-floss/silent_stream/-/blob/main/CODE_OF_CONDUCT.md [🖐contrib-rocks]: https://contrib.rocks [🖐contributors]: https://github.com/galtzo-floss/silent_stream/graphs/contributors [🚎contributors-gl]: https://gitlab.com/galtzo-floss/silent_stream/-/graphs/main [🖐contributors-img]: https://contrib.rocks/image?repo=galtzo-floss/silent_stream [💎rubygems]: https://rubygems.org [🔒️rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems [🔒️rubygems-checksums-pr]: https://github.com/rubygems/rubygems/pull/6022 [🔒️rubygems-guides-pr]: https://github.com/rubygems/guides/pull/325 [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139 [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html [🏃‍♂️runner-tool-cache]: https://github.com/ruby/ruby-builder/releases/tag/toolcache silent_stream-1.0.12/SECURITY.md0000755000004100000410000000110215053076402016264 0ustar www-datawww-data# Security Policy ## Supported Versions | Version | Supported | |-----------|-----------| | 1.latest | ✅ | ## Security contact information To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. ## Additional Support If you are interested in support for versions older than the latest release, please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate, or find other sponsorship links in the [README]. [README]: README.mdsilent_stream-1.0.12/lib/0000755000004100000410000000000015053076402015244 5ustar www-datawww-datasilent_stream-1.0.12/lib/silent_stream.rb0000644000004100000410000001522015053076402020442 0ustar www-datawww-data# frozen_string_literal: true # Std Lib require "tempfile" # Extracted Std Lib require "logger" # as of Ruby 3.5 # External gems require "version_gem" # This gem require_relative "silent_stream/version" module SilentStream def self.included(base) base.send(:extend, Extracted) base.send(:include, Extracted) base.send(:extend, Enhanced) base.send(:include, Enhanced) end module Enhanced # Silences STDOUT and optionally a Logger while executing the block. # # @param switch [Boolean] When false, do not silence. Defaults to true. # @param temporary_level [Integer] Logger level to set temporarily (e.g., Logger::ERROR). # @param logger [Logger, nil] Logger instance to adjust; defaults to Rails.logger when available. # @yield The work to perform while silenced. # @return [Object] Returns the block's return value. # @note This method is not thread-safe. def silence_all(switch = true, temporary_level = Logger::ERROR, logger = nil, &block) if !switch || silent_stream_no_silence yield else begin logger ||= silent_stream_logger old_logger_level = silent_stream_reset_logger_level(logger, temporary_level) # silence STDOUT (like puts) silence_stream(STDOUT, &block) ensure silent_stream_reset_logger_level(logger, old_logger_level) end end end private def silent_stream_no_silence ENV["NO_SILENCE"] == "true" end def silent_stream_logger (defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger) ? Rails.logger : nil end # returns previous logger's level def silent_stream_reset_logger_level(logger, temporary_level) logger && (old_logger_level = logger.level || true) && (logger.level = temporary_level) old_logger_level end end # Extracted from: # https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/core_ext/kernel/reporting.rb module Extracted SILENT_STREAM_NULL_DEVICE = if defined?(IO::NULL) IO::NULL else # :nocov: Gem.win_platform? ? "NUL:" : "/dev/null" # :nocov: end # This method is not thread-safe. # @yield Work to perform while STDERR is silenced. # @return [Object] The block's return value. def silence_stderr(&block) silence_stream(STDERR, &block) end # Silences any stream for the duration of the block. # # silence_stream(STDOUT) do # puts 'This will never be seen' # end # # puts 'But this will' # # @param stream [IO] The stream to silence (e.g., STDOUT or STDERR). # @yield Work to perform while the stream is silenced. # @return [Object] The block's return value. # @note This method is not thread-safe. def silence_stream(stream) old_stream = stream.dup begin stream.reopen(SILENT_STREAM_NULL_DEVICE, "a+") rescue StandardError => e stream.puts "[SilentStream] Unable to silence. #{e.class}: #{e.message}" end stream.sync = true yield ensure stream.reopen(old_stream) old_stream.close end # Captures the given stream and returns it: # # stream = capture(:stdout) { puts 'notice' } # stream # => "notice\n" # # stream = capture(:stderr) { warn 'error' } # stream # => "error\n" # # even for subprocesses: # # stream = capture(:stdout) { system('echo notice') } # stream # => "notice\n" # # stream = capture(:stderr) { system('echo error 1>&2') } # stream # => "error\n" # # @param stream [Symbol, String] :stdout or :stderr (or equivalents), selecting which stream to capture. # @yield Work that writes to the selected stream. # @return [String] Captured contents of the stream written during the block. # @note This method is not thread-safe. def capture(stream) stream = stream.to_s io_const = (stream == "stdout") ? STDOUT : STDERR # rubocop:disable Style/GlobalStdStream captured_stream = Tempfile.new(stream) # Save original global var ($stdout/$stderr) and a dup of IO constant for restoration origin_gvar = (stream == "stdout") ? $stdout : $stderr origin_io_dup = io_const.dup begin io_const.reopen(captured_stream) rescue StandardError => e io_const.puts "[SilentStream] Unable to capture. #{e.class}: #{e.message}" end io_const.sync = true if stream == "stdout" $stdout = io_const else $stderr = io_const end yield begin io_const.flush rescue StandardError # ignore end captured_stream.rewind captured_stream.read ensure begin io_const.reopen(origin_io_dup) if defined?(io_const) && io_const origin_io_dup.close if defined?(origin_io_dup) && origin_io_dup rescue StandardError # ignore end # Unexpected, and not reasonably testable. # :nocov: raise "Expected the global variable to exist" unless defined?(origin_gvar) # :nocov: if stream == "stdout" $stdout = origin_gvar else $stderr = origin_gvar end if defined?(captured_stream) && captured_stream begin captured_stream.close rescue nil end begin captured_stream.unlink rescue nil end end end # silence is provided by the LoggerSilence concern that continues to be # shipped with Rails, so not continuing with this alias. # alias silence capture # Silences both STDOUT and STDERR, even for subprocesses. # # quietly { system 'bundle install' } # # @yield Work to perform while both streams are silenced. # @return [Object] The block's return value. # @note This method is not thread-safe. # rubocop:disable Style/GlobalStdStream def quietly(&block) silence_stream(STDOUT) do silence_stream(STDERR, &block) end end # rubocop:enable Style/GlobalStdStream private SILENT_STREAM_WINDOWS_REGEXP = /mswin|mingw/.freeze SILENT_STREAM_REGEXP_HAS_MATCH = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4") def windows_os_test # When available, in Ruby 2.4+, we use Regexp#match? which does not update # the $~ global object and may be 3x faster than alternative match tests if SILENT_STREAM_REGEXP_HAS_MATCH SILENT_STREAM_WINDOWS_REGEXP.match?(RbConfig::CONFIG["host_os"]) else SILENT_STREAM_WINDOWS_REGEXP =~ RbConfig::CONFIG["host_os"] end end end end SilentStream::Version.class_eval do extend VersionGem::Basic end silent_stream-1.0.12/lib/silent_stream/0000755000004100000410000000000015053076402020115 5ustar www-datawww-datasilent_stream-1.0.12/lib/silent_stream/version.rb0000644000004100000410000000014515053076402022127 0ustar www-datawww-data# frozen_string_literal: true module SilentStream module Version VERSION = "1.0.12" end end silent_stream-1.0.12/LICENSE.txt0000644000004100000410000000213315053076402016320 0ustar www-datawww-dataThe MIT License (MIT) Copyright (c) 2018-2020, 2024-2025 Peter H. Boling (railsbling.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. silent_stream-1.0.12/CITATION.cff0000644000004100000410000000110115053076402016361 0ustar www-datawww-datacff-version: 1.2.0 title: silent_stream message: >- If you use this work and you want to cite it, then you can use the metadata from this file. type: software authors: - given-names: Peter Hurn family-names: Boling email: peter@railsbling.com affiliation: railsbling.com orcid: 'https://orcid.org/0009-0008-8519-441X' identifiers: - type: url value: 'https://github.com/galtzo-floss/silent_stream' description: silent_stream repository-code: 'https://github.com/galtzo-floss/silent_stream' abstract: >- silent_stream license: See license file silent_stream-1.0.12/checksums.yaml.gz.sig0000444000004100000410000000060015053076402020541 0ustar www-datawww-datak޹V @O'#n^)}q 0C1f093Jro)x/QaxMBD NuMXKP5A>S>p;i(m;snĩz3yeKRK ǖÀW`dNt%~Rp;=,f0Qz8R.*h+imm f1y61ÿ<1?dXbX IQ=5EP"t)^30x]sBX( /b%/Q&fWX 7R/15Y'-kr½q N8i*(Wq5\T+9tW13C9silent_stream-1.0.12/CODE_OF_CONDUCT.md0000644000004100000410000001307715053076402017305 0ustar www-datawww-data # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations [🚂bdfl-contact]: http://www.railsbling.com/contact [🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red silent_stream-1.0.12/data.tar.gz.sig0000444000004100000410000000060015053076402017311 0ustar www-datawww-dataRHI0JBM@tVXq*|c>*y660| /_n{ZDiv8;%h4L?Gk,,4c kAh/ TBȺ.q-q"3uc Ә[`4tbw'UASd+6$1ىhPUw 9̊3y4Gh@"d~yo3&RF*f\t7Θ'6Šw! TlZʺF=N@qHl:G{:oSa'LzgW*=ajb國silent_stream-1.0.12/checksums/0000755000004100000410000000000015053076402016463 5ustar www-datawww-datasilent_stream-1.0.12/checksums/silent_stream-1.0.11.gem.sha2560000644000004100000410000000010015053076402023540 0ustar www-datawww-data62f30ff2c1352f675eb2bff9170168d4e2524d71caf3e86be36a1ea741eedcd7silent_stream-1.0.12/checksums/silent_stream-1.0.12.gem.sha2560000644000004100000410000000010015053076402023541 0ustar www-datawww-dataf3cdf0e2ef000d28ea28cd324a4e74fcf3ec49a0fee6f156b862aedd1ae7d19csilent_stream-1.0.12/checksums/silent_stream-1.0.12.gem.sha5120000644000004100000410000000020015053076402023535 0ustar www-datawww-data677edc4416117621d892c13e119be6335b2a29c4efc0c09ce1a71d7ad33792572a7922d5b16f14c409ea6743518621d053eaf182a880aad492be49e6bb77d366silent_stream-1.0.12/checksums/silent_stream-1.0.10.gem.sha5120000644000004100000410000000020015053076402023533 0ustar www-datawww-data062b86979e8ba71e8ad2d5861e62a6624afc00758cfd5752be7cf8209e87fabe1b9d51cc2e35c4be7c8f25a7f46011d485605b4d40c4f1fcfd8d813f5d1ab218silent_stream-1.0.12/checksums/silent_stream-1.0.10.gem.sha2560000644000004100000410000000010015053076402023537 0ustar www-datawww-datab67962588acdddcb8b1972e35b4b0606bfcc23dd966841b7fec26cd282dc8a47silent_stream-1.0.12/checksums/silent_stream-1.0.9.gem.sha2560000644000004100000410000000010015053076402023467 0ustar www-datawww-data45e15ce4ba2d8d2ccbc07b165e795be4bff64715565fb102eb8be8a7c4a0b36csilent_stream-1.0.12/checksums/silent_stream-1.0.9.gem.sha5120000644000004100000410000000020015053076402023463 0ustar www-datawww-data196f3d50a68953899daeafa4e6ef1da6ecf073a1e4f9dbc56ff2e606b50be717297de84309c81d4d32c66a1a85545e721d662233affc512add1616f0ad6fc2f4silent_stream-1.0.12/checksums/silent_stream-1.0.11.gem.sha5120000644000004100000410000000020015053076402023534 0ustar www-datawww-data9a3bd81805f4514e499baf2de8994e3782239f09251304e17fdd5fa822bdc68938ad7a7c00cd92c633ed851e003b720b4230082f17a7095150e9305ac9dab0cbsilent_stream-1.0.12/REEK0000644000004100000410000000000015053076402015135 0ustar www-datawww-datasilent_stream-1.0.12/metadata.gz.sig0000444000004100000410000000060015053076402017373 0ustar www-datawww-dataa&%7d90/V< cqHriRp2sts[^Tg-9 U!ke7:Կ;2fIY A:dx~V( a y sgT)?gvd^q12nV!:*ۨwjUyH*>`fp(silent_stream-1.0.12/README.md0000644000004100000410000011327015053076402015761 0ustar www-datawww-data[![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-i]][🖼️galtzo-discord] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![silent_stream Logo by Aboling0, CC BY-SA 4.0][🖼️silent_stream-i]][🖼️silent_stream] [🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg [🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN [🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg [🖼️ruby-lang]: https://www.ruby-lang.org/ [🖼️silent_stream-i]: https://logos.galtzo.com/assets/images/galtzo-floss/silent_stream/avatar-192px.svg [🖼️silent_stream]: https://github.com/galtzo-floss/silent_stream # 🪶 SilentStream [![Version][👽versioni]][👽version] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls] [![CodeCov Test Coverage][🔑codecovi♻️]][🔑codecov] [![QLTY Test Coverage][🔑qlty-covi]][🔑qlty-cov] [![QLTY Maintainability][🔑qlty-mnti]][🔑qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] If ☝️ `ci_badges.map(&:color).detect { it != "green"}` [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord]. --- OTOH, if `ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS is now my full-time job. [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] ## 🌻 Synopsis SilentStream is an extraction of some parts of ActiveSupport's Kernel Reporting Core Extentions around silencing IO streams. Since July 2014 `silence_stream`, `silence_stderr`, `capture`, `silence`, and `quietly` have been deprecated because they are not thread safe. See that discussion in the [PR where it all went down](https://github.com/rails/rails/pull/13392). I rely on them a lot in *single threaded* code, and so I plan to keep them alive. With the exception of `silence`, which was just an alias of `capture`. This gem was taken out of Rails but it is *not* Rails dependent. The extraction was total (**even the tests**!), and this is now a pure Ruby library, which can be used in any Ruby project without encumbrances. I dramatically increased test coverage to 100% / 100% for lines / branches, and fixed issues with modern Rubies, *This gem has no runtime dependencies*. ### NOTE One aspect of what this gem provides can be achieved with the Rails' built-in [`LoggerSilence`](https://github.com/rails/rails/blob/5-2-stable/activesupport/lib/active_support/logger_silence.rb), which is thread safe. You will have to decide what is right for you! ### Doing a Rails <= 4 to Rails >= 5 Upgrade? The reason for not keeping `silence` as it was in Rails 4, i.e. an alias of `capture`, is that the just mentioned `LoggerSilence` now uses this term, and it is shipping with Rails 5. I don't want to make this gem incompatible with Rails 5, so you will have to convert Rails <= 4 implementations that utilize `silence` over to `capture` when using this gem. One further point of difference is this gem does not add the methods to `Kernel` or `Object`. You can do that if you like via `include`. By default this gem does not pollute anything, so you will need to `include SilentStream` in any class, or RSpec context, using these methods. | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 | |------------------------------------------------|-------------------------------------------------------------------------------------| | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ | ## 💡 Info you can shake a stick at ### Federated DVCS
Find this repo on other forges | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | |--------------------------------------------------------|-------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| | 🧪 [galtzo-floss/silent_stream on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ | | 🧊 [galtzo-floss/silent_stream on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ | | 🐙 [galtzo-floss/silent_stream on GitHub][📜src-gh] | A Dirty Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | [💚][gh-discussions] | | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
[gh-discussions]: https://github.com/galtzo-floss/silent_stream/discussions ### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/timecop-rspec)](https://tidelift.com/subscription/pkg/rubygems-timecop-rspec?utm_source=rubygems-timecop-rspec&utm_medium=referral&utm_campaign=readme)
Need enterprise-level guarantees? [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift] - 💡Subscribe for support guarantees covering _all_ FLOSS dependencies - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar] - 💡Tidelift pays maintainers to maintain the software you depend on!
📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers Alternatively: - [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
| Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Works with JRuby | ![JRuby 9.1 Compat][💎jruby-9.1i] ![JRuby 9.2 Compat][💎jruby-9.2i]
[![JRuby 9.3 Compat][💎jruby-9.3i]][🚎10-j-wf] [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] | | Works with Truffle Ruby | ![Truffle Ruby 22.3 Compat][💎truby-22.3i]
[![Truffle Ruby 23.0 Compat][💎truby-23.0i]][🚎9-t-wf] [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] ![Truffle Ruby HEAD Compat][💎truby-headi] | | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] | | Works with MRI Ruby 2 | ![Ruby 2.3 Compat][💎ruby-2.3i] ![Ruby 2.4 Compat][💎ruby-2.4i]
[![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] | | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] | | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![Wiki][📜wiki-img]][📜wiki] | | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] | | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] | | Support | [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] | | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] | | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] | ## ✨ Installation Install the gem and add to the application's Gemfile by executing: $ bundle add silent_stream If bundler is not being used to manage dependencies, install the gem by executing: $ gem install silent_stream ### 🔒 Secure Installation
For Medium or High Security Installations This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by [stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with by following the instructions below. Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate: ```console gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem) ``` You only need to do that once. Then proceed to install with: ```console gem install silent_stream -P MediumSecurity ``` The `MediumSecurity` trust profile will verify signed gems, but allow the installation of unsigned dependencies. If you want to up your security game full-time: ```console bundle config set --global trust-policy MediumSecurity ``` `MediumSecurity` instead of `HighSecurity` is necessary if not all the gems you use are signed. NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine.
## 🔧 Basic Usage Four standard methods you may be familiar with from ActiveSupport's previous implementation are provided: ``` silence_stderr silence_stream capture quietly ``` They are direct replicas, *except* not mixed into `Kernel` or `Object`, so in order to use them you must mix them into your classes or modules. ``` class Bogosity include SilentStream::Extracted # allows use at instance level extend SilentStream::Extracted # allows use at class level # or include SilentStream # access everything, and add #silence_all method, see below end ``` In addition there is a `silence_all` method that is a useful wrapper that can be easily instrumented (turned off and on) with an ENV variable switch. - Environment toggle: Set `NO_SILENCE=true` to bypass silencing entirely (useful in CI or when debugging). Any truthy value other than the literal string `"true"` is ignored — use exactly `true`. Including the `SilentStream` namespace fully gives access to this enhanced method, as well as the extracted methods above, and also makes everything available at the class and instance levels. ```ruby class Bogosity include SilentStream # allows use of any method at instance or class level def silent silence_all(true) do puts "play that funky music" Rails.logger.info("git jiggy with it") end end class << self def noise silence_all(false) do puts "play that funky music" Rails.logger.info("git jiggy with it") end end end end ``` And run ``` >> Bogosity.new.silent # has no output => nil >> Bogosity.noise # is noisy play that funky music => nil ``` ### Use in Specs / Tests Make the methods avaialble: ``` RSpec.configure do |conf| conf.include(SilentStream) end ``` Then add a test on output: ``` it "has output" do output = capture(:stdout) { subject.request(:get, "/success") } logs = [ "INFO -- request: GET https://api.example.com/success", "INFO -- response: Status 200", ] expect(output).to(include(*logs)) end ``` #### Better use in specs ```ruby config.include(SilentStream) # Silence STDOUT for examples NOT tagged with :check_output config.around(:example) do |example| if example.metadata[:check_output] example.run else silence_stream($stdout) do example.run end end end ``` See it in practice in the specs for the [oauth2 gem](https://github.com/oauth-xx/oauth2/blob/main/spec/oauth2/client_spec.rb#L193) and the [debug_logging gem](https://github.com/pboling/debug_logging/blob/main/spec/debug_logging/instance_logger_spec.rb#L10) ### Migrate from ActiveSupport::Testing::Stream, or remove ActiveSupport completely, in your ruby library! For most scenarios, simple. Change three lines. Here's an example from a gem I just converted from ActiveSupport to SilentStream ([see commit](https://github.com/pboling/debug_logging/commit/d0cd109e1509084bbcf753be39f2173f0e2878a7)) `gemspec` diff: ``` -spec.add_development_dependency 'activesupport', '>= 5' +spec.add_development_dependency 'silent_stream', '>= 1' ``` `spec_helper.rb` diff: ``` -require 'active_support/testing/stream' +require 'silent_stream' RSpec.configure do |config| - config.include ActiveSupport::Testing::Stream + config.include SilentStream ``` Run spec suite to verify everything is good. This gem is as close as can be to a drop-in replacement for Rails' `ActiveSupport::Testing::Stream`. ## 🚚 Switch to `main` branch We migrated from `master` to `main` as the default branch. If this affected your local checkout: ```console git branch -m master main git fetch origin git branch -u origin/main main git remote set-head origin -a ``` ## 🔐 Security See [SECURITY.md][🔐security]. ## 🤝 Contributing If you need some ideas of where to help, you could work on adding more code coverage, or if it is already 💯 (see [below](#code-coverage)), check [reek](REEK), check [GitHub][🤝gh-issues], [GitLab][🤝gl-issues], or [CodeBerg][🤝cb-issues], issues, or use the gem and think about how it could be better. We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it. See [CONTRIBUTING.md][🤝contributing] for more detailed instructions. ### 🚀 Release Instructions See [CONTRIBUTING.md][🤝contributing]. ### Types This library ships RBS type definitions under `sig/` that cover the public API. Editors and tools like Steep and TypeProf can use these for type checking and navigation. - Methods like `silence_stream`, `silence_stderr`, and `quietly` return the value returned by the given block. - `capture(:stdout | :stderr) { ... }` returns a String of the captured output. YARD is also provided for human-readable API docs. See the badges above for links to the generated documentation. ### Code Coverage [![Coverage Graph][🔑codecov-g♻️]][🔑codecov] [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls] [![QLTY Test Coverage][🔑qlty-covi]][🔑qlty-cov] ### 🪇 Code of Conduct Everyone interacting with this project's codebases, issue trackers, chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct]. ## 🌈 Contributors [![Contributors][🖐contributors-img]][🖐contributors] Made with [contributors-img][🖐contrib-rocks]. Also see GitLab Contributors: [https://gitlab.com/galtzo-floss/silent_stream/-/graphs/main][🚎contributors-gl]
⭐️ Star History Star History Chart
## 📌 Versioning This Library adheres to [![Semantic Versioning 2.0.0][📌semver-img]][📌semver]. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions. > dropping support for a platform is both obviously and objectively a breaking change
>—Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716][📌semver-breaking] I understand that policy doesn't work universally ("exceptions to every rule!"), but it is the policy here. As such, in many cases it is good to specify a dependency on this library using the [Pessimistic Version Constraint][📌pvc] with two digits of precision. For example: ```ruby spec.add_dependency("silent_stream", "~> 1.0") ```
📌 Is "Platform Support" part of the public API? More details inside. SemVer should, but doesn't explicitly, say that dropping support for specific Platforms is a *breaking change* to an API. It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless. To get a better understanding of how SemVer is intended to work over a project's lifetime, read this article from the creator of SemVer: - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
See [CHANGELOG.md][📌changelog] for a list of releases. ## 📄 License The gem is available as open source under the terms of the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref]. See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer]. ### © Copyright
  • Copyright (c) 2018-2020, 2024-2025 Peter H. Boling, of Galtzo.com Galtzo.com Logo (Wordless) by Aboling0, CC BY-SA 4.0 , and silent-stream contributors
## 🤑 A request for help Maintainers have teeth, and need to pay their dentists. After getting laid off in an RIF in March, and filled with many dozens of rejections, I'm now spending ~80 hours a week building open source tools. I'm hoping to be able to pay for my kids' health insurance this month, so if you value the work I am doing, I need your support. Please consider sponsoring me. [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay-img] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal-img] To say "thanks for maintaining such a great tool" 👇️ Join the Discord or ☝️ send money. To join the community or get help 👇️ Join the Discord. [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] Thanks for RTFM. ☺️ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611 [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611 [⛳liberapay]: https://liberapay.com/pboling/donate [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github [🖇sponsor]: https://github.com/sponsors/pboling [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg [🖇polar]: https://polar.sh/pboling [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg [🖇kofi]: https://ko-fi.com/O5O86SNP4 [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg [🖇patreon]: https://patreon.com/galtzo [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff [🖇buyme]: https://www.buymeacoffee.com/pboling [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A [🖇paypal]: https://www.paypal.com/paypalme/peterboling [🖇floss-funding.dev]: https://floss-funding.dev [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding [✉️discord-invite]: https://discord.gg/3qme4XHNKN [✉️discord-invite-img]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780 [⛳️gem-namespace]: https://github.com/galtzo-floss/silent_stream [⛳️namespace-img]: https://img.shields.io/badge/namespace-SilentStream-3C2D2D.svg?style=square&logo=ruby&logoColor=white [⛳️gem-name]: https://rubygems.org/gems/silent_stream [⛳️name-img]: https://img.shields.io/badge/name-silent__stream-3C2D2D.svg?style=square&logo=rubygems&logoColor=red [🚂maint-blog]: http://www.railsbling.com/tags/silent_stream [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange [🚂maint-contact]: http://www.railsbling.com/contact [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red [💖🖇linkedin]: http://www.linkedin.com/in/peterboling [💖🖇linkedin-img]: https://img.shields.io/badge/PeterBoling-LinkedIn-0B66C2?style=flat&logo=newjapanprowrestling [💖✌️wellfound]: https://wellfound.com/u/peter-boling/u/peter-boling [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase [💖🐘ruby-mast]: https://ruby.social/@galtzo [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=flat&logo=mastodon&label=Ruby%20%40galtzo [💖🦋bluesky]: https://bsky.app/profile/galtzo.com [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white [💖🌳linktree]: https://linktr.ee/galtzo [💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree [💖💁🏼‍♂️devto]: https://dev.to/galtzo [💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white [💖💁🏼‍♂️aboutme]: https://about.me/peter.boling [💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white [💖🧊berg]: https://codeberg.org/pboling [💖🐙hub]: https://github.org/pboling [💖🛖hut]: https://sr.ht/~galtzo/ [💖🧪lab]: https://gitlab.com/pboling [👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white [🏙️entsup-tidelift]: https://tidelift.com/subscription [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar [💁🏼‍♂️peterboling]: http://www.peterboling.com [🚂railsbling]: http://www.railsbling.com [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange [📜src-gl]: https://gitlab.com/galtzo-floss/silent_stream/ [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue [📜src-cb]: https://codeberg.org/galtzo-floss/silent_stream [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green [📜src-gh]: https://github.com/galtzo-floss/silent_stream [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white [📜wiki]: https://gitlab.com/galtzo-floss/silent_stream/-/wikis/home [📜wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=Wiki&logoColor=white [👽dl-rank]: https://rubygems.org/gems/silent_stream [👽dl-ranki]: https://img.shields.io/gem/rd/silent_stream.svg [👽oss-help]: https://www.codetriage.com/galtzo-floss/silent_stream [👽oss-helpi]: https://www.codetriage.com/galtzo-floss/silent_stream/badges/users.svg [👽version]: https://rubygems.org/gems/silent_stream [👽versioni]: https://img.shields.io/gem/v/silent_stream.svg [🔑qlty-mnt]: https://qlty.sh/gh/galtzo-floss/projects/silent_stream [🔑qlty-mnti]: https://qlty.sh/gh/galtzo-floss/projects/silent_stream/maintainability.svg [🔑qlty-cov]: https://qlty.sh/gh/galtzo-floss/projects/silent_stream/metrics/code?sort=coverageRating [🔑qlty-covi]: https://qlty.sh/gh/galtzo-floss/projects/silent_stream/coverage.svg [🔑codecov]: https://codecov.io/gh/galtzo-floss/silent_stream [🔑codecovi♻️]: https://codecov.io/gh/galtzo-floss/silent_stream/graph/badge.svg?token=Ad3ets1psE [🔑coveralls]: https://coveralls.io/github/galtzo-floss/silent_stream?branch=main [🔑coveralls-img]: https://coveralls.io/repos/github/galtzo-floss/silent_stream/badge.svg?branch=main [🖐codeQL]: https://github.com/galtzo-floss/silent_stream/security/code-scanning [🖐codeQL-img]: https://github.com/galtzo-floss/silent_stream/actions/workflows/codeql-analysis.yml/badge.svg [🚎1-an-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/ancient.yml [🚎1-an-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/ancient.yml/badge.svg [🚎2-cov-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/coverage.yml [🚎2-cov-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/coverage.yml/badge.svg [🚎3-hd-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/heads.yml [🚎3-hd-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/heads.yml/badge.svg [🚎4-lg-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/legacy.yml [🚎4-lg-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/legacy.yml/badge.svg [🚎5-st-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/style.yml [🚎5-st-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/style.yml/badge.svg [🚎6-s-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/supported.yml [🚎6-s-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/supported.yml/badge.svg [🚎7-us-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/unsupported.yml [🚎7-us-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/unsupported.yml/badge.svg [🚎8-ho-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/hoary.yml [🚎8-ho-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/hoary.yml/badge.svg [🚎9-t-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/truffle.yml [🚎9-t-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/truffle.yml/badge.svg [🚎10-j-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/jruby.yml [🚎10-j-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/jruby.yml/badge.svg [🚎11-c-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/current.yml [🚎11-c-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/current.yml/badge.svg [🚎13-🔒️-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/locked_deps.yml [🚎13-🔒️-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/locked_deps.yml/badge.svg [🚎14-🔓️-wf]: https://github.com/galtzo-floss/silent_stream/actions/workflows/unlocked_deps.yml [🚎14-🔓️-wfi]: https://github.com/galtzo-floss/silent_stream/actions/workflows/unlocked_deps.yml/badge.svg [💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.6i]: https://img.shields.io/badge/Ruby-2.6-DF00CA?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.7i]: https://img.shields.io/badge/Ruby-2.7-DF00CA?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-3.0i]: https://img.shields.io/badge/Ruby-3.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-3.1i]: https://img.shields.io/badge/Ruby-3.1-CC342D?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-3.2i]: https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink [💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green [💎truby-headi]: https://img.shields.io/badge/Truffle_Ruby-HEAD_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=blue [💎jruby-9.1i]: https://img.shields.io/badge/JRuby-9.1_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue [🤝gh-issues]: https://github.com/galtzo-floss/silent_stream/issues [🤝gh-pulls]: https://github.com/galtzo-floss/silent_stream/pulls [🤝gl-issues]: https://gitlab.com/galtzo-floss/silent_stream/-/issues [🤝gl-pulls]: https://gitlab.com/galtzo-floss/silent_stream/-/merge_requests [🤝cb-issues]: https://codeberg.org/galtzo-floss/silent_stream/issues [🤝cb-pulls]: https://codeberg.org/galtzo-floss/silent_stream/pulls [🤝cb-donate]: https://donate.codeberg.org/ [🤝contributing]: CONTRIBUTING.md [🔑codecov-g♻️]: https://codecov.io/gh/galtzo-floss/silent_stream/graphs/tree.svg?token=Ad3ets1psE [🖐contrib-rocks]: https://contrib.rocks [🖐contributors]: https://github.com/galtzo-floss/silent_stream/graphs/contributors [🖐contributors-img]: https://contrib.rocks/image?repo=galtzo-floss/silent_stream [🚎contributors-gl]: https://gitlab.com/galtzo-floss/silent_stream/-/graphs/main [🪇conduct]: CODE_OF_CONDUCT.md [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint [📌semver]: https://semver.org/spec/v2.0.0.html [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139 [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html [📌changelog]: CHANGELOG.md [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat [📌gitmoji]:https://gitmoji.dev [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.80-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue [🔐security]: SECURITY.md [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year [📄license]: LICENSE.txt [📄license-ref]: https://opensource.org/licenses/MIT [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat [🚎yard-current]: http://rubydoc.info/gems/silent_stream [🚎yard-head]: https://silent-stream.galtzo.com [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums [💎SHA_checksums]: https://gitlab.com/galtzo-floss/silent_stream/-/tree/main/checksums [💎rlts]: https://github.com/rubocop-lts/rubocop-lts [💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white [💎appraisal2]: https://github.com/appraisal-rb/appraisal2 [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/ silent_stream-1.0.12/sig/0000755000004100000410000000000015053076402015260 5ustar www-datawww-datasilent_stream-1.0.12/sig/silent_stream.rbs0000644000004100000410000000267615053076402020654 0ustar www-datawww-datamodule SilentStream module Enhanced # Silence STDOUT (and optionally a Logger) while executing the given block. # When switch is false or NO_SILENCE env var is true, the block executes without silencing. # Returns the block's return value. def silence_all: (*untyped) { () -> untyped } -> untyped private def silent_stream_no_silence: () -> bool def silent_stream_logger: () -> (::Logger | nil) # Sets logger.level, returns previous level (Integer) or true when previous level was nil def silent_stream_reset_logger_level: (::Logger?, Integer) -> (Integer | true | nil) end module Extracted SILENT_STREAM_NULL_DEVICE: String | IO # Silence STDERR for the duration of the given block. def silence_stderr: () { () -> untyped } -> untyped # Silences the given stream for the duration of the block. # Returns the block's return value. def silence_stream: (IO) { () -> untyped } -> untyped # Capture the given stream (:stdout or :stderr) while running the block and # return it as a String. def capture: (Symbol | String) { () -> untyped } -> String # Silence both STDOUT and STDERR while running the block. # Returns the block's return value. def quietly: () { () -> untyped } -> untyped private SILENT_STREAM_WINDOWS_REGEXP: Regexp SILENT_STREAM_REGEXP_HAS_MATCH: bool def windows_os_test: () -> (bool | Integer) end end module SilentStream::Version end silent_stream-1.0.12/CHANGELOG.md0000644000004100000410000001042315053076402016307 0ustar www-datawww-data# Changelog Starting with v1.0.9, All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added ### Changed ### Deprecated ### Removed ### Fixed ### Security ## [1.0.12] - 2025-08-21 - TAG: [v1.0.12][1.0.12t] - COVERAGE: 100.00% -- 80/80 lines in 2 files - BRANCH COVERAGE: 100.00% -- 21/21 branches in 2 files - 50.00% documented ### Added - RBS types - More YARD documentation - Published docs site: [silent-stream.galtzo.com](https://silent-stream.galtzo.com) - Complete test coverage for lines and branches at 100% ### Fixed - TypeError: can't convert Tempfile into StringIO ## [1.0.11] - 2025-05-16 - TAG: [v1.0.11][1.0.11t] - COVERAGE: 88.06% -- 59/67 lines in 2 files - BRANCH COVERAGE: 30.00% -- 3/10 branches in 2 files - 50.00% documented ### Changed - Reduced minimum version of logger dependency to 1.2 - To help with testing old libraries, or newer libraries that still support old libraries ### Fixed - Code Coverage setup in CI ## [1.0.10] - 2025-05-05 - TAG: [v1.0.10][1.0.10t] - COVERAGE: 47.76% -- 32/67 lines in 2 files - BRANCH COVERAGE: 10.00% -- 1/10 branches in 2 files - 50.00% documented ### Changed - SilentStream::Version => SilentStream::Version::VERSION - Allows test coverage to be tracked for version.rb ## [1.0.9] - 2025-05-05 - TAG: [v1.0.9][1.0.9t] - COVERAGE: 40.62% -- 26/64 lines in 2 files - BRANCH COVERAGE: 10.00% -- 1/10 branches in 2 files - 54.55% documented ### Added - Releases will be signed by my key that expires 2045-04-29 - Allow unsigned gem builds (for linux distros) - In the ENV set `SKIP_GEM_SIGNING` to any value - Compatibility with Ruby 3.5 - Make `logger` a direct dependency, since it is removed from stdlib in Ruby 3.5 - Expanded CI test matrix to include JRuby, TruffleRuby, and MRI 2.3+, including heads ## [1.0.8] - 2024-03-20 - TAG: [v1.0.8][1.0.8t] ## [1.0.7] - 2024-03-20 - TAG: [v1.0.7][1.0.7t] ## [1.0.6] - 2020-02-25 - TAG: [v1.0.6][1.0.6t] ## [1.0.5] - 2018-10-10 - TAG: [v1.0.5][1.0.5t] ## [1.0.4] - 2018-10-06 - TAG: [v1.0.4][1.0.4t] ## [1.0.3] - 2018-09-25 - TAG: [v1.0.3][1.0.3t] ## [1.0.2] - 2018-09-25 - TAG: [v1.0.2][1.0.2t] ## [1.0.1] - 2018-09-23 - TAG: [v1.0.1][1.0.1t] ## [1.0.0] - 2018-09-23 - TAG: [v1.0.0][1.0.0t] [Unreleased]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.12...HEAD [1.0.12]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.11...v1.0.12 [1.0.12t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.12 [1.0.11]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.10...v1.0.11 [1.0.11t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.11 [1.0.10]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.9...v1.0.10 [1.0.10t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.10 [1.0.9]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.8...v1.0.9 [1.0.9t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.9 [1.0.8]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.7...v1.0.8 [1.0.8t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.8 [1.0.7]: https://gitlab.com/galtzo-floss/silent_stream-/compare/v1.0.5...v1.0.7 [1.0.7t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.7 [1.0.6]: https://rubygems.org/gems/silent_stream/versions/1.0.6 [1.0.6t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.6 [1.0.5]: https://gitlab.com/galtzo-floss/silent_stream-/tags/v1.0.5 [1.0.5t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.5 [1.0.4]: https://rubygems.org/gems/silent_stream/versions/1.0.4 [1.0.4t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.4 [1.0.3]: https://rubygems.org/gems/silent_stream/versions/1.0.3 [1.0.3t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.3 [1.0.2]: https://rubygems.org/gems/silent_stream/versions/1.0.2 [1.0.2t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.2 [1.0.1]: https://rubygems.org/gems/silent_stream/versions/1.0.1 [1.0.1t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.1 [1.0.0]: https://rubygems.org/gems/silent_stream/versions/1.0.0 [1.0.0t]: https://gitlab.com/galtzo-floss/timecop-rspec/-/tags/v1.0.0