lib/tqdm/decorator.rb in tqdm-0.3.0 vs lib/tqdm/decorator.rb in tqdm-0.4.0

- old
+ new

@@ -42,10 +42,11 @@ options.merge!(total: total!) unless options[:total] @printer = Printer.new(options) @min_iterations = options[:min_iters] || 1 @min_interval = options[:min_interval] || 0.5 @leave = options[:leave] || false + @force_refreeze = false end # Starts the textual progress bar. def start! @iteration = @last_printed_iteration = 0 @@ -85,29 +86,43 @@ # # @return [Enumerable] a clone of Enumerable enhanced so that every call to `#each` animates the # progress bar. def enhance decorate_enumerable_each + enhanced.freeze if @force_refreeze enhanced end private def decorate_enumerable_each tqdm = self enhanced.define_singleton_method(:each) do |*args, &block| tqdm.start! - result = super(*args) do |item| - block.call item if block + result = super(*args) do |*items| + block.call *items if block tqdm.increment! end tqdm.finish! result end end def enhanced - @enhanced ||= enumerable.clone + @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? + @force_refreeze = true + unfrozen = Object.instance_method(:clone).bind(enumerable).call(freeze: false) + unfrozen end def total! enumerable.size rescue enumerable.count rescue nil end