mirror of
https://github.com/lostisland/faraday.git
synced 2025-10-09 00:04:39 -04:00
Create Faraday Deprecate class.
This implementation warns in stderr similar to Gem::Deprecate, but gives a semver instead of a date like the default Gem::Deprecate does.
This commit is contained in:
parent
22b689d78f
commit
6e746fceef
97
lib/faraday/deprecate.rb
Normal file
97
lib/faraday/deprecate.rb
Normal file
@ -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
|
@ -1,21 +1,25 @@
|
|||||||
module Faraday
|
# frozen_string_literal: true
|
||||||
class Error < StandardError; end
|
|
||||||
|
|
||||||
class ClientError < Error
|
require 'faraday/deprecate'
|
||||||
|
|
||||||
|
# Faraday namespace.
|
||||||
|
module Faraday
|
||||||
|
# Faraday error base class.
|
||||||
|
class Error < StandardError
|
||||||
attr_reader :response, :wrapped_exception
|
attr_reader :response, :wrapped_exception
|
||||||
|
|
||||||
def initialize(ex, response = nil)
|
def initialize(exc, response = nil)
|
||||||
@wrapped_exception = nil
|
@wrapped_exception = nil
|
||||||
@response = response
|
@response = response
|
||||||
|
|
||||||
if ex.respond_to?(:backtrace)
|
if exc.respond_to?(:backtrace)
|
||||||
super(ex.message)
|
super(exc.message)
|
||||||
@wrapped_exception = ex
|
@wrapped_exception = exc
|
||||||
elsif ex.respond_to?(:each_key)
|
elsif exc.respond_to?(:each_key)
|
||||||
super("the server responded with status #{ex[:status]}")
|
super("the server responded with status #{exc[:status]}")
|
||||||
@response = ex
|
@response = exc
|
||||||
else
|
else
|
||||||
super(ex.to_s)
|
super(exc.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -28,39 +32,80 @@ module Faraday
|
|||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
inner = ''
|
inner = +''
|
||||||
if @wrapped_exception
|
inner << " wrapped=#{@wrapped_exception.inspect}" if @wrapped_exception
|
||||||
inner << " wrapped=#{@wrapped_exception.inspect}"
|
inner << " response=#{@response.inspect}" if @response
|
||||||
end
|
inner << " #{super}" if inner.empty?
|
||||||
if @response
|
|
||||||
inner << " response=#{@response.inspect}"
|
|
||||||
end
|
|
||||||
if inner.empty?
|
|
||||||
inner << " #{super}"
|
|
||||||
end
|
|
||||||
%(#<#{self.class}#{inner}>)
|
%(#<#{self.class}#{inner}>)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ConnectionFailed < ClientError; end
|
# Faraday client error class. Represents 4xx status responses.
|
||||||
class ResourceNotFound < ClientError; end
|
class ClientError < Error
|
||||||
class ParsingError < ClientError; end
|
end
|
||||||
|
|
||||||
class TimeoutError < ClientError
|
# Raised by Faraday::Response::RaiseError in case of a 400 response.
|
||||||
def initialize(ex = nil)
|
class BadRequestError < ClientError
|
||||||
super(ex || "timeout")
|
end
|
||||||
|
|
||||||
|
# Raised by Faraday::Response::RaiseError in case of a 401 response.
|
||||||
|
class UnauthorizedError < ClientError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Raised by Faraday::Response::RaiseError in case of a 403 response.
|
||||||
|
class ForbiddenError < ClientError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Raised by Faraday::Response::RaiseError in case of a 404 response.
|
||||||
|
class ResourceNotFound < ClientError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Raised by Faraday::Response::RaiseError in case of a 407 response.
|
||||||
|
class ProxyAuthError < ClientError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Raised by Faraday::Response::RaiseError in case of a 409 response.
|
||||||
|
class ConflictError < ClientError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Raised by Faraday::Response::RaiseError in case of a 422 response.
|
||||||
|
class UnprocessableEntityError < ClientError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Faraday server error class. Represents 5xx status responses.
|
||||||
|
class ServerError < Error
|
||||||
|
end
|
||||||
|
|
||||||
|
# A unified client error for timeouts.
|
||||||
|
class TimeoutError < ServerError
|
||||||
|
def initialize(exc = 'timeout', response = nil)
|
||||||
|
super(exc, response)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SSLError < ClientError
|
# A unified error for failed connections.
|
||||||
|
class ConnectionFailed < Error
|
||||||
end
|
end
|
||||||
|
|
||||||
class RetriableResponse < ClientError; end
|
# A unified client error for SSL errors.
|
||||||
|
class SSLError < Error
|
||||||
[:ClientError, :ConnectionFailed, :ResourceNotFound,
|
|
||||||
:ParsingError, :TimeoutError, :SSLError, :RetriableResponse].each do |const|
|
|
||||||
Error.const_set(const, Faraday.const_get(const))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Raised by FaradayMiddleware::ResponseMiddleware
|
||||||
|
class ParsingError < Error
|
||||||
|
end
|
||||||
|
|
||||||
|
# Exception used to control the Retry middleware.
|
||||||
|
#
|
||||||
|
# @see Faraday::Request::Retry
|
||||||
|
class RetriableResponse < Error
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[ClientError ConnectionFailed ResourceNotFound
|
||||||
|
ParsingError TimeoutError SSLError RetriableResponse].each do |const|
|
||||||
|
Error.const_set(
|
||||||
|
const,
|
||||||
|
DeprecatedClass.proxy_class(Faraday.const_get(const))
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
84
spec/faraday/error_spec.rb
Normal file
84
spec/faraday/error_spec.rb
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Faraday::ClientError do
|
||||||
|
describe '.initialize' do
|
||||||
|
subject { described_class.new(exception, response) }
|
||||||
|
let(:response) { nil }
|
||||||
|
|
||||||
|
context 'with exception only' do
|
||||||
|
let(:exception) { RuntimeError.new('test') }
|
||||||
|
|
||||||
|
it { expect(subject.wrapped_exception).to eq(exception) }
|
||||||
|
it { expect(subject.response).to be_nil }
|
||||||
|
it { expect(subject.message).to eq(exception.message) }
|
||||||
|
it { expect(subject.backtrace).to eq(exception.backtrace) }
|
||||||
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with response hash' do
|
||||||
|
let(:exception) { { status: 400 } }
|
||||||
|
|
||||||
|
it { expect(subject.wrapped_exception).to be_nil }
|
||||||
|
it { expect(subject.response).to eq(exception) }
|
||||||
|
it { expect(subject.message).to eq('the server responded with status 400') }
|
||||||
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with string' do
|
||||||
|
let(:exception) { 'custom message' }
|
||||||
|
|
||||||
|
it { expect(subject.wrapped_exception).to be_nil }
|
||||||
|
it { expect(subject.response).to be_nil }
|
||||||
|
it { expect(subject.message).to eq('custom message') }
|
||||||
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with anything else #to_s' do
|
||||||
|
let(:exception) { %w[error1 error2] }
|
||||||
|
|
||||||
|
it { expect(subject.wrapped_exception).to be_nil }
|
||||||
|
it { expect(subject.response).to be_nil }
|
||||||
|
it { expect(subject.message).to eq('["error1", "error2"]') }
|
||||||
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'maintains backward-compatibility until 1.0' 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 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
|
||||||
|
|
||||||
|
it 'allows backward-compatible class to be subclassed' do
|
||||||
|
expect { class CustomError < Faraday::Error::ClientError; end }.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_warn_squelching
|
||||||
|
stderr_catcher = StringIO.new
|
||||||
|
original_stderr = $stderr
|
||||||
|
$stderr = stderr_catcher
|
||||||
|
result = yield if block_given?
|
||||||
|
[stderr_catcher.tap(&:rewind).string, result]
|
||||||
|
ensure
|
||||||
|
$stderr = original_stderr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user