Skip to content

Commit

Permalink
Update to a more extensible deprecation method.
Browse files Browse the repository at this point in the history
The previous implementation would not warn about deprecation upon
being inherited, and warned in a stdout. This implementation warns
in stderr similar to Gem::Deprecate, but gives a semver instead of
a date like the default Gem::Deprecate does.
  • Loading branch information
BobbyMcWho committed Oct 1, 2019
1 parent 5111b84 commit a8235ac
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 41 deletions.
97 changes: 97 additions & 0 deletions lib/faraday/deprecate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# frozen_string_literal: true

module Faraday
# @param new_klass [Class] new Klass to use
#
# @return [Class] A modified version of new_klass that warns on
# usage about deprecation.
# @see {Faraday::Deprecate}
module DeprecatedClass
def self.proxy_class(new_klass)
Class.new(new_klass).tap do |k|
class << k
extend Faraday::Deprecate
# Make this more human readable than #<Class:Faraday::ClientError>
klass_name = superclass.to_s[/^#<Class:(\w*::\w*)>$/, 1]
deprecate :new, "#{klass_name}.new", '1.0'
deprecate :inherited, klass_name, '1.0'
end
end
end
end

# Deprecation using semver instead of date, based on Gem::Deprecate
# Provides a single method +deprecate+ to be used to declare when
# something is going away.
#
# class Legacy
# def self.klass_method
# # ...
# end
#
# def instance_method
# # ...
# end
#
# extend Faraday::Deprecate
# deprecate :instance_method, "X.z", '1.0'
#
# class << self
# extend Faraday::Deprecate
# deprecate :klass_method, :none, '1.0'
# end
# end
module Deprecate
def self.skip # :nodoc:
@skip ||= false
end

def self.skip=(value) # :nodoc:
@skip = value
end

# Temporarily turn off warnings. Intended for tests only.
def skip_during
original = Faraday::Deprecate.skip
Faraday::Deprecate.skip, = true
yield
ensure
Faraday::Deprecate.skip = original
end

# Simple deprecation method that deprecates +name+ by wrapping it up
# in a dummy method. It warns on each call to the dummy method
# telling the user of +repl+ (unless +repl+ is :none) and the
# semver that it is planned to go away.
# @param name [Symbol] the method symbol to deprecate
# @param repl [#to_s, :none] the replacement to use, when `:none` it will
# alert the user that no replacemtent is present.
# @param ver [String] the semver the method will be removed.
def deprecate(name, repl, ver)
class_eval do
old = "_deprecated_#{name}"
alias_method old, name
define_method name do |*args, &block|
mod = is_a? Module
target = mod ? "#{self}." : "#{self.class}#"
target_message = if name == :inherited
"Inheriting #{self}"
else
"#{target}#{name}"
end

msg = [
"NOTE: #{target_message} is deprecated",
repl == :none ? ' with no replacement' : "; use #{repl} instead. ",
"It will be removed in or after version #{Gem::Version.new(ver)}",
"\n#{target}#{name} called from #{Gem.location_of_caller.join(':')}"
]
warn "#{msg.join}." unless Faraday::Deprecate.skip
send old, *args, &block
end
end
end

module_function :deprecate, :skip_during
end
end
28 changes: 0 additions & 28 deletions lib/faraday/deprecated_class.rb

This file was deleted.

7 changes: 2 additions & 5 deletions lib/faraday/error.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require 'faraday/deprecated_class'
require 'faraday/deprecate'

# Faraday namespace.
module Faraday
Expand Down Expand Up @@ -105,10 +105,7 @@ class RetriableResponse < Error
ParsingError TimeoutError SSLError RetriableResponse].each do |const|
Error.const_set(
const,
Faraday::DeprecatedClass.proxy_class(
"Faraday::Error::#{const}",
Faraday.const_get(const)
)
DeprecatedClass.proxy_class(Faraday.const_get(const))
)
end
end
30 changes: 22 additions & 8 deletions spec/faraday/error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,26 @@
end

context 'maintains backward-compatibility until 1.0' do
it 'does not raise an error for nested error classes but prints an error message' do
it 'does not raise an error for error-namespaced classes but prints an error message' do
error_message, error = with_warn_squelching { Faraday::Error::ClientError.new('foo') }

expect(error).to be_a Faraday::ClientError
expect(error_message).to eq(
"DEPRECATION WARNING: Faraday::Error::ClientError is deprecated! Use Faraday::ClientError instead.\n"
expect(error_message).to match(
Regexp.new(
'NOTE: Faraday::Error::ClientError.new is deprecated; '\
'use Faraday::ClientError.new instead. It will be removed in or after version 1.0'
)
)
end

it 'does not raise an error for inherited error-namespaced classes but prints an error message' do
error_message, = with_warn_squelching { class E < Faraday::Error::ClientError; end }

expect(error_message).to match(
Regexp.new(
'NOTE: Inheriting Faraday::Error::ClientError is deprecated; '\
'use Faraday::ClientError instead. It will be removed in or after version 1.0'
)
)
end

Expand All @@ -58,13 +72,13 @@
end

def with_warn_squelching
stdout_catcher = StringIO.new
original_stdout = $stdout
$stdout = stdout_catcher
stderr_catcher = StringIO.new
original_stderr = $stderr
$stderr = stderr_catcher
result = yield if block_given?
[stdout_catcher.tap(&:rewind).string, result]
[stderr_catcher.tap(&:rewind).string, result]
ensure
$stdout = original_stdout
$stderr = original_stderr
end
end
end

0 comments on commit a8235ac

Please sign in to comment.