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