lib/tqdm/decorator.rb in tqdm-0.4.0 vs lib/tqdm/decorator.rb in tqdm-0.4.1
- old
+ new
@@ -1,8 +1,13 @@
require 'tqdm/printer'
+CLONE_UNFROZEN_SUPPORTED = RUBY_VERSION.split('.')[0..1].join('.').to_f >= 2.4
+
module Tqdm
+
+ class DecoratorError < StandardError
+ end
# Decorates the #each method of an `Enumerable` by wrapping it so that each
# iteration produces a pretty progress bar printed to the console or a file handle.
#
# @note The `Enumerable` is cloned before it is enhanced; it is not modified directly.
@@ -110,19 +115,26 @@
def enhanced
@enhanced ||= enumerable_unfrozen
end
# Uses progressively more invasive techniques to return an unfrozen copy of @enumerable
- # Significantly, for some classes like Sequel::Dataset, both #clone and #dup re-freeze
- # the object, so we have to drop back to Object#clone
def enumerable_unfrozen
- unfrozen = enumerable.clone(freeze: false)
- return unfrozen unless unfrozen.frozen?
- unfrozen = enumerable.dup
- return unfrozen unless unfrozen.frozen?
+ to_unfreeze = CLONE_UNFROZEN_SUPPORTED ? enumerable.clone(freeze: false) : enumerable.clone
+ return to_unfreeze unless to_unfreeze.frozen?
+ to_unfreeze = to_unfreeze.dup
+ return to_unfreeze unless to_unfreeze.frozen?
+
+ # Significantly, for some classes like Sequel::Dataset, both #clone and #dup re-freeze
+ # the object before returning it, so we have to drop back to Object#clone to avoid this
@force_refreeze = true
- unfrozen = Object.instance_method(:clone).bind(enumerable).call(freeze: false)
- unfrozen
+ if CLONE_UNFROZEN_SUPPORTED
+ to_unfreeze = Object.instance_method(:clone).bind(enumerable).call(freeze: false)
+ end
+ if Object.instance_method(:frozen?).bind(to_unfreeze).call
+ raise DecoratorError.new("could not create an unfrozen clone")
+ end
+
+ to_unfreeze
end
def total!
enumerable.size rescue enumerable.count rescue nil
end