tqdm 0.2.0 → 0.3.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: 3dc522c1cd180b959a8c36c2a3f1fb41ffdd51a8
4
- data.tar.gz: e17546f682e0adfe9b6970bc02477590b1d355cd
3
+ metadata.gz: a133210c842f8c1c583898dbf792545371bc69fe
4
+ data.tar.gz: 5718d34d881d6cf1b00d7fda4fe5386db526537b
5
5
  SHA512:
6
- metadata.gz: 2a5aecb337cfec0e565deabd81741aff57c48c1b1b13b562c08c9173ae6b9e520aeb18561734a317ee9ee2943dc0df3869c71495c17ff584580d7787857011b2
7
- data.tar.gz: 71e5e62669db44fe2d3b7aa42696c22bf5c34f87f374b48505ea9899536c9a614ae9ce92b874799e3e5df46525f2fc9ea251dea2a5f86c238db7f34468aa291b
6
+ metadata.gz: aa94d7a905513ca26e45d712db7b63bf1ddc503915e99f728bda5eef4475b916a99bbf969fae97511bc656d8cfd173664cdd16f9ef95b4a8ecf5fcd0263497ae
7
+ data.tar.gz: 491b60be374b5fa7c4ff2fa473f4359c6aa7130942197ea3e43b74c4e301d2f0ed348ffcc271c50b29d0a8334f81a60bc1c04ffa6ce14d4cabc22e1b4bf40ca9
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.2"
4
+ - "1.9.3"
5
+ - "2.0.0"
6
+ - "2.1.8"
7
+ - "2.2.4"
8
+ - rbx
data/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  # tqdm-ruby
2
- [![Gem Version](https://badge.fury.io/rb/tqdm.svg)](https://badge.fury.io/rb/tqdm)
2
+ [![Build Status](https://travis-ci.org/powerpak/tqdm-ruby.svg?branch=master)](https://travis-ci.org/powerpak/tqdm-ruby) [![Gem Version](https://badge.fury.io/rb/tqdm.svg)](https://badge.fury.io/rb/tqdm)
3
3
 
4
4
  tqdm-ruby allows you to add a progress indicator to your loops with minimal effort.
5
5
 
6
6
  It is a port of the excellent [tqdm library][tqdm] for python. tqdm (read taqadum, تقدّم) means "progress" in Arabic.
7
7
 
8
- Calling `#tqdm` (or its readable but longer alias `#with_progress`) on any `Enumerable` returns an enhanced clone that animates a meter on `$stderr` during iteration.
8
+ Calling `#tqdm` (or `#with_progress`) on any `Enumerable` returns an enhanced clone that animates a meter during iteration.
9
9
 
10
10
  ```ruby
11
11
  require 'tqdm'
12
12
  (0...1000).tqdm.each { |x| sleep 0.01 }
13
13
  ```
14
14
 
15
- The default output looks like this:
15
+ The default output is sent to `$stderr` and looks like this:
16
16
 
17
17
  ![|####------| 492/1000 49% [elapsed: 00:05 left: 00:05, 88.81 iters/sec]](http://i.imgur.com/6y0t7XS.gif)
18
18
 
@@ -82,7 +82,7 @@ DB[:items].where{ price > 10 }.with_progress.each { |row| "do some processing he
82
82
  ## TODO
83
83
 
84
84
  1. Performance improvements
85
- 2. Test/benchmark suite
85
+ 2. Add benchmark suite, expand test coverage
86
86
  3. Add smoothing for speed estimates
87
87
  4. Support unicode output (smooth blocks)
88
88
  5. By default, resize to the apparent width of the output terminal
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.pattern = Dir.glob('spec/**/*_spec.rb')
6
+ end
7
+
8
+ task :default => :spec
@@ -12,6 +12,8 @@ module Tqdm
12
12
  # arr_tqdm = Decorator.new(arr).enhance
13
13
  # arr_tqdm.each { |x| sleep 0.01 }
14
14
  class Decorator
15
+
16
+ extend Forwardable
15
17
 
16
18
  attr_reader :printer, :enumerable, :iteration, :start_time
17
19
 
@@ -46,9 +48,8 @@ module Tqdm
46
48
 
47
49
  # Starts the textual progress bar.
48
50
  def start!
49
- @iteration = 0
50
- @start_time = Time.now
51
- printer.start
51
+ @iteration = @last_printed_iteration = 0
52
+ @start_time = @last_print_time = current_time!
52
53
  end
53
54
 
54
55
  # Called everytime the textual progress bar might need to be updated (i.e. on
@@ -63,8 +64,9 @@ module Tqdm
63
64
  return unless (iteration - last_printed_iteration) >= @min_iterations
64
65
  # We check the counter first, to reduce the overhead of Time.now
65
66
  return unless (current_time! - last_print_time) >= @min_interval
67
+ return if iteration == total && !@leave
66
68
 
67
- printer.status(iteration, elapsed_time!)
69
+ printer.status(iteration, elapsed_time!)
68
70
  @last_printed_iteration = iteration
69
71
  @last_print_time = current_time
70
72
  end
@@ -134,5 +136,7 @@ module Tqdm
134
136
  def reprint?
135
137
  last_printed_iteration < iteration
136
138
  end
139
+
140
+ def_delegator :printer, :total
137
141
  end
138
142
  end
@@ -23,10 +23,6 @@ module Tqdm
23
23
  @file = options[:file] || $stderr
24
24
  @last_printed_length = 0
25
25
  end
26
-
27
- def start
28
- line(0, 0.0)
29
- end
30
26
 
31
27
  # Pads a status line so that it is long enough to overwrite the previously written line
32
28
  #
@@ -39,7 +39,7 @@ module Tqdm
39
39
  elapsed_str = interval(elapsed)
40
40
  rate = elapsed && elapsed > 0 ? ('%5.2f' % (n / elapsed)) : '?'
41
41
 
42
- if total
42
+ if total && total > 0
43
43
  frac = n.to_f / total
44
44
 
45
45
  bar_length = (frac * PROGRESS_BAR_WIDTH).to_i
@@ -62,7 +62,7 @@ module Tqdm
62
62
 
63
63
  # Formats a number of seconds into an hh:mm:ss string.
64
64
  #
65
- # @param t [Integer] a number of seconds
65
+ # @param seconds [Integer] a number of seconds
66
66
  # @return [String] an hh:mm:ss string
67
67
  def interval(seconds)
68
68
  m, s = seconds.to_i.divmod(60)
@@ -1,4 +1,4 @@
1
1
  module Tqdm
2
2
  # The version of this module and gem by the same name.
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'timecop'
3
+ require_relative '../lib/tqdm'
4
+
5
+ describe 'When enumerating over an object' do
6
+ before { Timecop.freeze }
7
+ after { Timecop.return }
8
+
9
+ def with_stderr(&block)
10
+ old_stderr = $stderr
11
+ $stderr = StringIO.new
12
+
13
+ block.call
14
+
15
+ return $stderr.string
16
+ ensure
17
+ $stderr = old_stderr
18
+ end
19
+
20
+ def timecop_loop(enumerable, options = {})
21
+ enumerable.tqdm(options).each do |x|
22
+ Timecop.travel 1
23
+ end
24
+ end
25
+
26
+ context 'that has zero elements' do
27
+ let(:enumerable) { (0...0) }
28
+
29
+ context 'with default options' do
30
+ it 'never displays a progress bar' do
31
+ final_stderr = with_stderr { timecop_loop(enumerable) }
32
+ expect(final_stderr).to eq "\r\r"
33
+ end
34
+ end
35
+
36
+ context 'with leave: true' do
37
+ it 'never displays a progress bar' do
38
+ final_stderr = with_stderr { timecop_loop(enumerable, leave: true) }
39
+ expect(final_stderr).to eq "\n"
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'that has one element' do
45
+ let(:enumerable) { (0...1) }
46
+
47
+ context 'with default options' do
48
+ it 'never displays a progress bar' do
49
+ final_stderr = with_stderr { timecop_loop(enumerable) }
50
+ expect(final_stderr).to eq "\r\r"
51
+ end
52
+ end
53
+
54
+ context 'with leave: true' do
55
+ it 'displays a progress bar once at 100%' do
56
+ final_stderr = with_stderr { timecop_loop(enumerable, leave: true) }
57
+ expect(final_stderr).to eq "" \
58
+ "\r|##########| 1/1 100% [elapsed: 00:01 left: 00:00, 1.00 iters/sec]" \
59
+ "\n"
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ context 'that has several (five) elements' do
66
+ let(:enumerable) { (0...5) }
67
+
68
+ context 'with default options' do
69
+ it 'displays a progress bar for the first four steps and deletes it' do
70
+ final_stderr = with_stderr { timecop_loop(enumerable) }
71
+
72
+ expect(final_stderr).to eq "" \
73
+ "\r|##--------| 1/5 20% [elapsed: 00:01 left: 00:04, 1.00 iters/sec]" \
74
+ "\r|####------| 2/5 40% [elapsed: 00:02 left: 00:03, 1.00 iters/sec]" \
75
+ "\r|######----| 3/5 60% [elapsed: 00:03 left: 00:02, 1.00 iters/sec]" \
76
+ "\r|########--| 4/5 80% [elapsed: 00:04 left: 00:01, 1.00 iters/sec]" \
77
+ "\r " \
78
+ "\r"
79
+ end
80
+ end
81
+
82
+ context 'with leave: true' do
83
+ it 'displays a progress bar with as many steps as elements and leaves it' do
84
+ final_stderr = with_stderr { timecop_loop(enumerable, leave: true) }
85
+
86
+ expect(final_stderr).to eq "" \
87
+ "\r|##--------| 1/5 20% [elapsed: 00:01 left: 00:04, 1.00 iters/sec]" \
88
+ "\r|####------| 2/5 40% [elapsed: 00:02 left: 00:03, 1.00 iters/sec]" \
89
+ "\r|######----| 3/5 60% [elapsed: 00:03 left: 00:02, 1.00 iters/sec]" \
90
+ "\r|########--| 4/5 80% [elapsed: 00:04 left: 00:01, 1.00 iters/sec]" \
91
+ "\r|##########| 5/5 100% [elapsed: 00:05 left: 00:00, 1.00 iters/sec]" \
92
+ "\n"
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'timecop'
3
+ require_relative '../lib/tqdm'
4
+ require_relative '../lib/tqdm/sequel'
5
+
6
+ describe 'When enumerating over a Sequel dataset' do
7
+ before { Timecop.freeze }
8
+ after { Timecop.return }
9
+
10
+ def timecop_loop(dataset, options = {})
11
+ dataset.tqdm(options).each do |x|
12
+ Timecop.travel 1
13
+ end
14
+ end
15
+
16
+ context 'that has several (five) elements' do
17
+ let(:database) do
18
+ db = Sequel.sqlite
19
+ db.create_table :items do
20
+ primary_key :id
21
+ Float :price
22
+ end
23
+
24
+ (0...5).each { db[:items].insert(price: rand * 100) }
25
+
26
+ db
27
+ end
28
+
29
+ context 'with default options' do
30
+ it 'displays a progress bar for the first four steps and deletes it' do
31
+ final_stderr = with_stderr { timecop_loop(database[:items]) }
32
+
33
+ expect(final_stderr).to eq "" \
34
+ "\r|##--------| 1/5 20% [elapsed: 00:01 left: 00:04, 1.00 iters/sec]" \
35
+ "\r|####------| 2/5 40% [elapsed: 00:02 left: 00:03, 1.00 iters/sec]" \
36
+ "\r|######----| 3/5 60% [elapsed: 00:03 left: 00:02, 1.00 iters/sec]" \
37
+ "\r|########--| 4/5 80% [elapsed: 00:04 left: 00:01, 1.00 iters/sec]" \
38
+ "\r " \
39
+ "\r"
40
+ end
41
+ end
42
+
43
+ context 'with leave: true' do
44
+ it 'displays a progress bar with as many steps as elements and leaves it' do
45
+ final_stderr = with_stderr { timecop_loop(database[:items], leave: true) }
46
+
47
+ expect(final_stderr).to eq "" \
48
+ "\r|##--------| 1/5 20% [elapsed: 00:01 left: 00:04, 1.00 iters/sec]" \
49
+ "\r|####------| 2/5 40% [elapsed: 00:02 left: 00:03, 1.00 iters/sec]" \
50
+ "\r|######----| 3/5 60% [elapsed: 00:03 left: 00:02, 1.00 iters/sec]" \
51
+ "\r|########--| 4/5 80% [elapsed: 00:04 left: 00:01, 1.00 iters/sec]" \
52
+ "\r|##########| 5/5 100% [elapsed: 00:05 left: 00:00, 1.00 iters/sec]" \
53
+ "\n"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,20 @@
1
+ RSpec.configure do |config|
2
+ config.expect_with :rspec do |expectations|
3
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
4
+ end
5
+
6
+ config.mock_with :rspec do |mocks|
7
+ mocks.verify_partial_doubles = true
8
+ end
9
+ end
10
+
11
+ def with_stderr(&block)
12
+ old_stderr = $stderr
13
+ $stderr = StringIO.new
14
+
15
+ block.call
16
+
17
+ return $stderr.string
18
+ ensure
19
+ $stderr = old_stderr
20
+ end
@@ -20,6 +20,10 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "sequel"
24
+ spec.add_development_dependency "sqlite3"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "timecop"
23
27
 
24
28
  spec.required_ruby_version = '>= 1.9.2'
25
29
  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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Theodore Pak
@@ -38,6 +38,62 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sequel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: timecop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
41
97
  description: Enhances Enumerables to show progress while iterating. (Port of tqdm
42
98
  for Python.)
43
99
  email:
@@ -47,6 +103,8 @@ extensions: []
47
103
  extra_rdoc_files: []
48
104
  files:
49
105
  - ".gitignore"
106
+ - ".rspec"
107
+ - ".travis.yml"
50
108
  - ".yardopts"
51
109
  - Gemfile
52
110
  - LICENSE.txt
@@ -59,6 +117,9 @@ files:
59
117
  - lib/tqdm/printer/default_format.rb
60
118
  - lib/tqdm/sequel.rb
61
119
  - lib/tqdm/version.rb
120
+ - spec/enumerable_spec.rb
121
+ - spec/sequel_spec.rb
122
+ - spec/spec_helper.rb
62
123
  - tqdm.gemspec
63
124
  homepage: https://github.com/powerpak/tqdm-ruby
64
125
  licenses:
@@ -84,4 +145,7 @@ rubygems_version: 2.2.5
84
145
  signing_key:
85
146
  specification_version: 4
86
147
  summary: Enhances Enumerables to show progress while iterating.
87
- test_files: []
148
+ test_files:
149
+ - spec/enumerable_spec.rb
150
+ - spec/sequel_spec.rb
151
+ - spec/spec_helper.rb