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