tqdm 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd2cc2ae1f682e5a99a462698ec94a5363752ad2
4
- data.tar.gz: ee799a36386c9a151fe555e0d856d56bf0650e66
3
+ metadata.gz: 18fbbebb6aadc15bb9b2cea3caf012e49e087908
4
+ data.tar.gz: 3da06e2b16e451592014ebdf94b0012ad165d589
5
5
  SHA512:
6
- metadata.gz: be8161fd9956a94aa0bf195b7b1de88c3e063c4438b6ab88ba47019c2948ee1ccb31dfe1442930ac6023a8bdb64feaa9a15368f650c25a819fc39f9390631102
7
- data.tar.gz: ae7f1c956f1f10121130909124f4d26794fea5fd94690f6ba8420db3f1b0ac060b7f4728123c4525cd0c1f809445b80d08c7256d078f0297cb9e96fc21945fcc
6
+ metadata.gz: 0aefc092a3fb9a925107689fe03eaf8196393a60331fcb41031bca5159423693e65db4bd5cf60a333cb0d16c1cb0eaf9dfe5682003955665d1bdedcf0ea49d70
7
+ data.tar.gz: 7bdd329b81bca2cc2951753815c7459f58ac6009b8dffa8e5a650cbb921f67cc7ac7b4e976478a5fd9d09fcbcea82842757dc80d1f8b83a28ebd55adc711abca
@@ -0,0 +1,4 @@
1
+ --readme README.md
2
+ --charset utf-8
3
+ --markup markdown
4
+ 'lib/**/*.rb'
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: <a href="https://github.com/tqdm/tqdm" target="_blank">https://github.com/tqdm/tqdm</a>.
5
+ It is a port of the excellent [tdqm library][tqdm] for python.
6
6
 
7
- Call #tqdm on any `Enumerable`, which enhances the object so that iterating over it will produce an animated progress bar on `$stderr`.
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
- require 'tqdm'
10
- (0...1000).tqdm.each {|x| sleep 0.01 }
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
- |####------| 492/1000 49% [elapsed: 00:05 left: 00:05, 88.81 iters/sec]
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
- Add this line to your application's `Gemfile`:
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
- Or install it yourself as:
38
+ ## Usage
29
39
 
30
- $ gem install tqdm
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
- ## Usage
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
- 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.
70
+ # Show progress during big inserts (this isn't new)
71
+ (0..100000).tqdm.each { DB[:items].insert(price: rand * 100) }
35
72
 
36
- require 'tqdm'
37
- (0...100).tqdm.each {|x| sleep 0.01 }
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
 
@@ -1,18 +1,23 @@
1
1
  require "tqdm"
2
2
 
3
- # This is where the real magic begins
4
- # All enumerable objects (e.g.) Arrays will have these methods added to them
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
- # Upgrades an Enumerable so that any subsequent call to .each will spit out a progress bar
8
- # opts is a hash that can include:
9
- # desc: Short string, describing the progress, added to the beginning of the line
10
- # total: Expected number of iterations, if not given, self.size is used
11
- # file: A file-like object to output the progress message to, by default, $stderr
12
- # leave: A boolean (default False) should the progress bar should stay on screen after it's done?
13
- # min_interval: See below
14
- # min_iters: If less than min_interval seconds or min_iters iterations have passed since
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
@@ -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
- def print_status(s)
20
- @file.write("\r" + s + ' ' * [@last_printed_len - s.size, 0].max)
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 = s.size
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 time.time()
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
 
@@ -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, {total: count}.merge!(opts)).enhance
20
+ Tqdm::TqdmDecorator.new(self, opts).enhance
9
21
  end
22
+
10
23
  end
11
24
 
12
25
  end
@@ -2,11 +2,13 @@ require "tqdm"
2
2
 
3
3
  module Tqdm
4
4
 
5
- N_BARS = 10
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)
@@ -1,3 +1,4 @@
1
1
  module Tqdm
2
- VERSION = "0.0.1"
2
+ # The version of this module and gem by the same name.
3
+ VERSION = "0.1.0"
3
4
  end
@@ -20,4 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+
24
+ spec.required_ruby_version = '>= 1.9.2'
23
25
  end
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.1
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: '0'
73
+ version: 1.9.2
73
74
  required_rubygems_version: !ruby/object:Gem::Requirement
74
75
  requirements:
75
76
  - - ">="