tqdm 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +4 -0
- data/README.md +51 -13
- data/lib/core_ext/enumerable.rb +15 -10
- data/lib/tqdm.rb +76 -7
- data/lib/tqdm/sequel.rb +14 -1
- data/lib/tqdm/utils.rb +10 -6
- data/lib/tqdm/version.rb +2 -1
- data/tqdm.gemspec +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18fbbebb6aadc15bb9b2cea3caf012e49e087908
|
4
|
+
data.tar.gz: 3da06e2b16e451592014ebdf94b0012ad165d589
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0aefc092a3fb9a925107689fe03eaf8196393a60331fcb41031bca5159423693e65db4bd5cf60a333cb0d16c1cb0eaf9dfe5682003955665d1bdedcf0ea49d70
|
7
|
+
data.tar.gz: 7bdd329b81bca2cc2951753815c7459f58ac6009b8dffa8e5a650cbb921f67cc7ac7b4e976478a5fd9d09fcbcea82842757dc80d1f8b83a28ebd55adc711abca
|
data/.yardopts
ADDED
data/README.md
CHANGED
@@ -2,22 +2,32 @@
|
|
2
2
|
|
3
3
|
tqdm-ruby is a small utility to show a progress indicator while iterating through an Enumerable object.
|
4
4
|
|
5
|
-
It is a port of the excellent tdqm library for python
|
5
|
+
It is a port of the excellent [tdqm library][tqdm] for python.
|
6
6
|
|
7
|
-
Call
|
7
|
+
Call `#tqdm` on any `Enumerable`, which enhances the object so that iterating over it will produce an animated progress bar on `$stderr`.
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
```ruby
|
10
|
+
require 'tqdm'
|
11
|
+
(0...1000).tqdm.each { |x| sleep 0.01 }
|
12
|
+
```
|
11
13
|
|
12
14
|
The default output looks like this:
|
13
15
|
|
14
|
-
|
16
|
+
![|####------| 492/1000 49% [elapsed: 00:05 left: 00:05, 88.81 iters/sec]](http://i.imgur.com/6y0t7XS.gif)
|
15
17
|
|
16
|
-
It works equally well from within [pry](http://pryrepl.org/) and [Jupyter notebooks](https://jupyter.org/).
|
18
|
+
It works equally well from within irb, [pry](http://pryrepl.org/), and [Jupyter notebooks](https://jupyter.org/).
|
19
|
+
|
20
|
+
*Why not progressbar, ruby-progressbar, etc.?* These have a bazillion formatting options and you typically have to update the progressbar object throughout other code. tqdm pleasantly encourages the laziest imaginable usage, in that you "set it and forget it".
|
21
|
+
|
22
|
+
[tqdm]: https://github.com/tqdm/tqdm
|
17
23
|
|
18
24
|
## Install
|
19
25
|
|
20
|
-
|
26
|
+
Install it globally from [Rubygems](https://rubygems.org/gems/tqdm):
|
27
|
+
|
28
|
+
$ gem install tqdm # (might need sudo on OS X)
|
29
|
+
|
30
|
+
*or* add this line to your application's Gemfile:
|
21
31
|
|
22
32
|
gem 'tqdm'
|
23
33
|
|
@@ -25,16 +35,44 @@ And then execute:
|
|
25
35
|
|
26
36
|
$ bundle
|
27
37
|
|
28
|
-
|
38
|
+
## Usage
|
29
39
|
|
30
|
-
|
40
|
+
All `Enumerable` objects gain access to the `#tqdm` method, which returns an enhanced object wherein any iteration (by calling `#each` or any of its relatives, e.g., `#each_with_index`, `#each_with_object`, etc.) produces an animated progress bar on `$stderr`.
|
31
41
|
|
32
|
-
|
42
|
+
Options can be provided for `#tqdm`:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
require 'tqdm'
|
46
|
+
Hash[*(1..1000)].tqdm(desc: "working on it", leave: true).each { |x| sleep 0.01 }
|
47
|
+
```
|
48
|
+
|
49
|
+
The following options are available:
|
50
|
+
|
51
|
+
- `desc`: Short string, describing the progress, added to the beginning of the line
|
52
|
+
- `total`: Expected number of iterations, if not given, `self.size` is used
|
53
|
+
- `file`: A file-like object to output the progress message to, by default, `$stderr`
|
54
|
+
- `leave`: A boolean (default false). Should the progress bar should stay on screen after it's done?
|
55
|
+
- `min_interval`: Default is `0.5`. If less than `min_interval` seconds or `min_iters` iterations have passed since the last progress meter update, it is not re-printed (decreases IO thrashing).
|
56
|
+
- `min_iters`: Default is `1`. See previous.
|
57
|
+
|
58
|
+
[Sequel](http://sequel.jeremyevans.net/) is an amazing database library for Ruby. tqdm can enhance its [`Dataset`](http://sequel.jeremyevans.net/rdoc/classes/Sequel/Dataset.html) objects to show progress while iterating (same options as above):
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require 'tqdm/sequel' # Automatically requires tqdm and sequel
|
62
|
+
|
63
|
+
# In-memory database for demonstration purposes
|
64
|
+
DB = Sequel.sqlite
|
65
|
+
DB.create_table :items do
|
66
|
+
primary_key :id
|
67
|
+
Float :price
|
68
|
+
end
|
33
69
|
|
34
|
-
|
70
|
+
# Show progress during big inserts (this isn't new)
|
71
|
+
(0..100000).tqdm.each { DB[:items].insert(price: rand * 100) }
|
35
72
|
|
36
|
-
|
37
|
-
|
73
|
+
# Show progress during long SELECT queries
|
74
|
+
DB[:items].where{ price > 10 }.tqdm.each { |row| "do some processing here" }
|
75
|
+
```
|
38
76
|
|
39
77
|
## Contributing
|
40
78
|
|
data/lib/core_ext/enumerable.rb
CHANGED
@@ -1,18 +1,23 @@
|
|
1
1
|
require "tqdm"
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
3
|
+
# We enhance all enumerable objects (e.g. `Array`, `Hash`, `Range`, ...) by extending the `Enumerable` module.
|
4
|
+
# This mixin is only supposed to be present on objects that provide an `#each` method.
|
5
|
+
#
|
6
|
+
# @see http://ruby-doc.org/core-2.2.3/Enumerable.html
|
5
7
|
module Enumerable
|
6
8
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
9
|
+
# Returns a clone of `self` where all calls to `#each` and related methods will print an animated progress bar
|
10
|
+
# while iterating.
|
11
|
+
#
|
12
|
+
# @param opts [Hash] more options used to control behavior of the progress bar
|
13
|
+
# @option opts [String] :desc a short description added to the beginning of the progress bar
|
14
|
+
# @option opts [Integer] :total (self.size) the expected number of iterations
|
15
|
+
# @option opts [File, IO] :file ($stderr) a file-like object to output the progress bar to
|
16
|
+
# @option opts [Boolean] :leave (false) should the progress bar should stay on screen after it's done?
|
17
|
+
# @option opts [Integer] :min_iters see `:min_interval`
|
18
|
+
# @option opts [Float] :min_interval If less than min_interval seconds or min_iters iterations have passed since
|
15
19
|
# the last progress meter update, it is not updated again.
|
20
|
+
# @return [Enumerable] `self` with the `#each` method wrapped as described above
|
16
21
|
def tqdm(opts = {})
|
17
22
|
Tqdm::TqdmDecorator.new(self, opts).enhance
|
18
23
|
end
|
data/lib/tqdm.rb
CHANGED
@@ -2,35 +2,89 @@ require "tqdm/version"
|
|
2
2
|
require "tqdm/utils"
|
3
3
|
require "core_ext/enumerable"
|
4
4
|
|
5
|
+
# Add a progress bar to your loops in a second.
|
6
|
+
# A port of Python's [tqdm library](https://github.com/tqdm/tqdm), although we're currently
|
7
|
+
# closer to the feature set of [@noamraph's original release](https://github.com/noamraph/tqdm).
|
8
|
+
#
|
9
|
+
# Specifically, `Tqdm` enhances `Enumerable` by printing a progress indicator whenever
|
10
|
+
# iterating with `#each` or its close relatives.
|
11
|
+
#
|
12
|
+
# @author Theodore Pak
|
13
|
+
# @see https://github.com/tqdm/tqdm
|
5
14
|
module Tqdm
|
6
15
|
|
16
|
+
# The default width of the progress bar, in characters.
|
17
|
+
N_BARS = 10
|
18
|
+
|
7
19
|
class << self
|
20
|
+
# Upgrades `Sequel::Datasets` with the #tqdm method.
|
21
|
+
# @see Enumerable#tqdm
|
8
22
|
def enhance_sequel!
|
9
23
|
require "tqdm/sequel"
|
10
24
|
end
|
11
25
|
end
|
12
|
-
|
26
|
+
|
27
|
+
# Prints a status line, handling the deletion of previously printed lines with carriage
|
28
|
+
# returns as necessary. Instantiated by a `TqdmDecorator`.
|
29
|
+
#
|
30
|
+
# @private
|
13
31
|
class StatusPrinter
|
32
|
+
# Initialize a new StatusPrinter.
|
33
|
+
#
|
34
|
+
# @param file [File, IO] the status will be printed to this via `#write` and `#flush`
|
14
35
|
def initialize(file)
|
15
36
|
@file = file
|
16
37
|
@last_printed_len = 0
|
17
38
|
end
|
18
39
|
|
19
|
-
|
20
|
-
|
40
|
+
# Prints a line of text to @file, after deleting the previously printed line
|
41
|
+
#
|
42
|
+
# @param line [String] a line of text to be printed
|
43
|
+
# @return [Integer] the number of bytes written
|
44
|
+
def print_status(line)
|
45
|
+
@file.write("\r" + line + ' ' * [@last_printed_len - line.size, 0].max)
|
21
46
|
@file.flush
|
22
|
-
@last_printed_len =
|
47
|
+
@last_printed_len = line.size
|
23
48
|
end
|
24
49
|
end
|
25
50
|
|
26
51
|
|
52
|
+
# Decorates the #each method of an `Enumerable` by wrapping it so that each
|
53
|
+
# iteration produces a pretty progress bar printed to the console or a file handle.
|
54
|
+
#
|
55
|
+
# @note The `Enumerable` is cloned before it is enhanced; it is not modified directly.
|
56
|
+
#
|
57
|
+
# @example Enhances `arr` so that an animated progress bar prints while iterating.
|
58
|
+
# arr = (0...1000)
|
59
|
+
# arr_tqdm = TqdmDecorator.new(arr).enhance
|
60
|
+
# arr_tqdm.each { |x| sleep 0.01 }
|
27
61
|
class TqdmDecorator
|
28
62
|
|
29
63
|
include Utils
|
30
|
-
|
64
|
+
|
65
|
+
# Initialize a new TqdmDecorator. Typically you wouldn't use this object, but
|
66
|
+
# would immediately call `#enhance` to retrieve the enhanced `Enumerable`.
|
67
|
+
#
|
68
|
+
# @param enumerable [Enumerable] the Enumerable object to be enhanced
|
69
|
+
# @param opts [Hash] more options used to control behavior of the progress bar
|
70
|
+
# @option opts [String] :desc a short description added to the beginning of the progress bar
|
71
|
+
# @option opts [Integer] :total (self.size) the expected number of iterations
|
72
|
+
# @option opts [File, IO] :file ($stderr) a file-like object to output the progress bar to
|
73
|
+
# @option opts [Boolean] :leave (false) should the progress bar should stay on screen after it's done?
|
74
|
+
# @option opts [Integer] :min_iters see `:min_interval`
|
75
|
+
# @option opts [Float] :min_interval If less than min_interval seconds or min_iters iterations have passed since
|
76
|
+
# the last progress meter update, it is not updated again.
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
# a = (1...1000)
|
80
|
+
# TqdmDecorator.new(a).enhance.each { |x| sleep 0.01 }
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# a = [1, 2, 3, 4]
|
84
|
+
# TqdmDecorator.new(a, file: $stdout, leave: true)
|
31
85
|
def initialize(enumerable, opts={})
|
32
86
|
@enumerable = enumerable
|
33
|
-
@total = opts[:total] || @enumerable.size rescue nil
|
87
|
+
@total = opts[:total] || @enumerable.size rescue @enumerable.count rescue nil
|
34
88
|
@prefix = opts[:desc] ? opts[:desc] + ': ' : ''
|
35
89
|
@file = opts[:file] || $stderr
|
36
90
|
@sp = StatusPrinter.new(@file)
|
@@ -39,6 +93,7 @@ module Tqdm
|
|
39
93
|
@leave = opts[:leave] || false
|
40
94
|
end
|
41
95
|
|
96
|
+
# Starts the textual progress bar.
|
42
97
|
def start!
|
43
98
|
@start_t = @last_print_t = Time.now
|
44
99
|
@last_print_n = 0
|
@@ -47,11 +102,17 @@ module Tqdm
|
|
47
102
|
@sp.print_status(@prefix + format_meter(0, @total, 0))
|
48
103
|
end
|
49
104
|
|
105
|
+
# Called everytime the textual progress bar might need to be updated (i.e. on
|
106
|
+
# every iteration). We still check whether the update is appropriate to print to
|
107
|
+
# the progress bar before doing so, according to the `:min_iters` and `:min_interval`
|
108
|
+
# options.
|
109
|
+
#
|
110
|
+
# @see #initialize
|
50
111
|
def increment!
|
51
112
|
@n += 1
|
52
113
|
|
53
114
|
if @n - @last_print_n >= @min_iters
|
54
|
-
# We check the counter first, to reduce the overhead of
|
115
|
+
# We check the counter first, to reduce the overhead of Time.now
|
55
116
|
cur_t = Time.now
|
56
117
|
if cur_t - @last_print_t >= @min_interval
|
57
118
|
@sp.print_status(@prefix + format_meter(@n, @total, cur_t - @start_t))
|
@@ -61,6 +122,8 @@ module Tqdm
|
|
61
122
|
end
|
62
123
|
end
|
63
124
|
|
125
|
+
# Prints the final state of the textual progress bar. Based on the `:leave` option, this
|
126
|
+
# may include deleting it entirely.
|
64
127
|
def finish!
|
65
128
|
if !@leave
|
66
129
|
@sp.print_status('')
|
@@ -73,6 +136,12 @@ module Tqdm
|
|
73
136
|
end
|
74
137
|
end
|
75
138
|
|
139
|
+
# Enhances the wrapped `Enumerable`.
|
140
|
+
#
|
141
|
+
# @note The `Enumerable` is cloned (shallow copied) before it is enhanced; it is not modified directly.
|
142
|
+
#
|
143
|
+
# @return [Enumerable] a clone of Enumerable enhanced so that every call to `#each` animates the
|
144
|
+
# progress bar.
|
76
145
|
def enhance
|
77
146
|
tqdm = self
|
78
147
|
|
data/lib/tqdm/sequel.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
1
|
require "sequel"
|
2
2
|
require "tqdm"
|
3
3
|
|
4
|
+
# @see Sequel::Dataset
|
4
5
|
module Sequel
|
5
6
|
|
7
|
+
# In order to use `Tqdm` with Sequel Datasets, we can simply extend `Sequel::Dataset`
|
8
|
+
# with the same `#tqdm` method
|
9
|
+
#
|
10
|
+
# @see Enumerable#tqdm
|
11
|
+
# @see http://sequel.jeremyevans.net/
|
12
|
+
# @see http://sequel.jeremyevans.net/rdoc/classes/Sequel/Dataset.html
|
6
13
|
class Dataset
|
14
|
+
|
15
|
+
# Returns a clone of `self` where all calls to `#each` and related methods will print an animated progress bar
|
16
|
+
# while iterating.
|
17
|
+
#
|
18
|
+
# @see Enumerable#tqdm
|
7
19
|
def tqdm(opts = {})
|
8
|
-
Tqdm::TqdmDecorator.new(self,
|
20
|
+
Tqdm::TqdmDecorator.new(self, opts).enhance
|
9
21
|
end
|
22
|
+
|
10
23
|
end
|
11
24
|
|
12
25
|
end
|
data/lib/tqdm/utils.rb
CHANGED
@@ -2,11 +2,13 @@ require "tqdm"
|
|
2
2
|
|
3
3
|
module Tqdm
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
# Utility functions related to `Tqdm`.
|
7
6
|
module Utils
|
8
7
|
|
9
8
|
# Formats a number of seconds into an hh:mm:ss string.
|
9
|
+
#
|
10
|
+
# @param t [Integer] a number of seconds
|
11
|
+
# @return [String] an hh:mm:ss string
|
10
12
|
def format_interval(t)
|
11
13
|
mins, s = t.to_i.divmod(60)
|
12
14
|
h, m = mins.divmod(60)
|
@@ -14,11 +16,13 @@ module Tqdm
|
|
14
16
|
end
|
15
17
|
|
16
18
|
# Formats a count (n) of total items processed + an elapsed time into a
|
17
|
-
# textual progress meter.
|
19
|
+
# textual progress bar + meter.
|
20
|
+
#
|
21
|
+
# @param n [Integer] number of finished iterations
|
22
|
+
# @param total [Integer, nil] total number of iterations, or nil
|
23
|
+
# @param elapsed [Integer] number of seconds passed since start
|
24
|
+
# @return [String] a textual progress bar + meter
|
18
25
|
def format_meter(n, total, elapsed)
|
19
|
-
# n - number of finished iterations
|
20
|
-
# total - total number of iterations, or nil
|
21
|
-
# elapsed - number of seconds passed since start
|
22
26
|
total = (n > total ? nil : total) if total
|
23
27
|
|
24
28
|
elapsed_str = format_interval(elapsed)
|
data/lib/tqdm/version.rb
CHANGED
data/tqdm.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tqdm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Theodore Pak
|
@@ -47,6 +47,7 @@ extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
49
|
- ".gitignore"
|
50
|
+
- ".yardopts"
|
50
51
|
- Gemfile
|
51
52
|
- LICENSE.txt
|
52
53
|
- README.md
|
@@ -69,7 +70,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
70
|
requirements:
|
70
71
|
- - ">="
|
71
72
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
73
|
+
version: 1.9.2
|
73
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
75
|
requirements:
|
75
76
|
- - ">="
|