sequencer 1.0.3 → 1.0.5

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.
data/.gemtest ADDED
File without changes
data/History.txt CHANGED
@@ -1,6 +1,14 @@
1
+ === 1.0.5 / 2011-07-07
2
+
3
+ * Dicking around with testing frameworks that become obsolete is the worst thing ever.
4
+
5
+ === 1.0.4 / 2010-10-26
6
+
7
+ * Add rseqrename binary that batch-renames sequences
8
+
1
9
  === 1.0.3 / 2010-10-26
2
10
 
3
- * Add rseqpad binary that zero-pads filenames
11
+ * Add rseqpad binary that zero-pads sequences
4
12
 
5
13
  === 1.0.2 / 2010-05-06
6
14
 
data/Manifest.txt CHANGED
@@ -1,9 +1,10 @@
1
1
  .autotest
2
2
  History.txt
3
3
  Manifest.txt
4
- README.txt
4
+ README.rdoc
5
5
  Rakefile
6
6
  bin/rseqls
7
7
  bin/rseqpad
8
+ bin/rseqrename
8
9
  lib/sequencer.rb
9
10
  test/test_sequencer.rb
@@ -6,18 +6,34 @@
6
6
 
7
7
  Simplifies working with image sequences
8
8
 
9
- == FEATURES/PROBLEMS:
9
+ == FEATURES:
10
10
 
11
11
  * List all sequences in a directory interspersed with other file entries
12
12
  * Detect sequence from single file
13
13
 
14
14
  == SYNOPSIS:
15
15
 
16
- require "sequencer"
17
- s = Sequencer.from_single_file("/RAID/Film/CONFORM.092183.dpx")
18
- s.file_count #=> 3201
19
- s.gaps? #=> true
20
- s.missing_frames #=> 15, somebody was careless
16
+ From the terminal - go to a directory, and then:
17
+
18
+ $rseqls
19
+
20
+ Fussball_Shot[1..1, 3..3].sni
21
+ FinalLichtUitValSec_Shot1.[1..128].jpg
22
+ Fussball_Shot3_v02.sni
23
+ FinalLichtUitValSec_Shot1.0001.ifl
24
+ FinalLichtUitValSec.0001.ifl
25
+ FinalLichtUitValSec.[1..185].jpg
26
+
27
+ You also have <tt>rseqpad</tt> and <tt>rseqrename</tt> :-)
28
+
29
+ From code:
30
+
31
+ require "sequencer"
32
+ s = Sequencer.from_single_file("/RAID/Film/CONFORM.092183.dpx")
33
+ s.file_count #=> 3201
34
+ s.gaps? #=> true
35
+ s.missing_frames #=> 15, somebody was careless
36
+ s.pattern #=> "CONFORM.%06d.dpx", usable with printf right away
21
37
 
22
38
  == INSTALL:
23
39
 
data/Rakefile CHANGED
@@ -3,10 +3,11 @@ require 'rubygems'
3
3
  require 'hoe'
4
4
  require File.dirname(__FILE__) + "/lib/sequencer"
5
5
 
6
+ Hoe::RUBY_FLAGS.gsub!(/^-w/, '')
6
7
  Hoe.spec 'sequencer' do | s |
7
- s.version = Sequencer::VERSION
8
+ s.readme_file = 'README.rdoc'
9
+ s.extra_rdoc_files = FileList['*.rdoc']
8
10
  s.developer('Julik Tarkhanov', 'me@julik.nl')
9
- s.extra_dev_deps = {"test-spec" => ">=0"}
10
11
  end
11
12
 
12
13
  # vim: syntax=ruby
data/bin/rseqrename ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + "/../lib/sequencer"
4
+
5
+ one_file, base_pattern = ARGV.shift, ARGV.shift
6
+ Sequencer.from_single_file(one_file).bulk_rename(base_pattern)
data/lib/sequencer.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Sequencer
2
- VERSION = '1.0.3'
2
+ VERSION = '1.0.5'
3
3
  NUMBERS_AT_END = /(\d+)([^\d]+)?$/
4
4
 
5
5
  extend self
@@ -30,7 +30,8 @@ module Sequencer
30
30
 
31
31
  # Detect a Sequence from a single file and return a handle to it
32
32
  def from_single_file(path_to_single_file)
33
- File.stat(path_to_single_file)
33
+ #File.stat(path_to_single_file)
34
+
34
35
  frame_number = path_to_single_file.scan(NUMBERS_AT_END).flatten.shift
35
36
  if frame_number =~ /^0/ # Assume that the input is padded and take the glob path
36
37
  sequence_via_glob(path_to_single_file)
@@ -86,7 +87,7 @@ module Sequencer
86
87
  attr_reader :directory
87
88
 
88
89
  def initialize(directory, filenames)
89
- raise "Can't sequence nothingness" if filenames.empty?
90
+ raise "Cannot create a Sequence with no files" if filenames.empty?
90
91
  @directory, @filenames = directory, natural_sort(filenames)
91
92
  @directory.freeze
92
93
  @filenames.freeze
@@ -202,9 +203,17 @@ module Sequencer
202
203
  end
203
204
 
204
205
  # Apply a bulk rename
205
- def bulk_rename(with_pattern)
206
- rename_map = filenames.inject({}) do | filename, map |
206
+ def bulk_rename(with_pattern, into_directory = nil, &operation)
207
+ # Check if the pattern includes a number. If it doesnt, add one and the
208
+ # extension
209
+ unless with_pattern.include?("%")
210
+ padz = last_frame_no.to_s.length
211
+ with_pattern = [with_pattern, ".%0#{padz}d", File.extname(pattern)].join
212
+ end
213
+
214
+ rename_map = @filenames.inject({}) do | map, filename |
207
215
  frame_no = filename.scan(NUMBERS_AT_END).flatten.shift.to_i
216
+
208
217
  map.merge(filename => (with_pattern % frame_no))
209
218
  end
210
219
 
@@ -217,15 +226,19 @@ module Sequencer
217
226
  raise "This would overwrite old files with the renamed ones (#{error[0..1]}.join(',')..)"
218
227
  end
219
228
 
220
- if (error = (Dir.entries(@directory) % rename_map.values)).any?
229
+ if (error = (Dir.entries(@directory) & rename_map.values)).any?
221
230
  raise "Files that will be created by the rename are already in place (#{error[0..1]}.join(',')..)"
222
231
  end
223
232
 
233
+ destination = into_directory || directory
224
234
 
225
- end
226
-
227
- def bulk_rename!(with_pattern)
228
- replace(bulk_rename(with_pattern))
235
+ rename_map.each_pair do | from_path, to_path |
236
+ src, dest = File.join(directory, from_path), File.join(destination, to_path)
237
+ File.rename(src, dest)
238
+ #yield(src, dest)
239
+ end
240
+
241
+ self.class.new(destination, rename_map.values)
229
242
  end
230
243
 
231
244
  private
@@ -1,10 +1,9 @@
1
1
  require 'test/unit'
2
- require 'rubygems'
3
- require 'test/spec'
2
+ require 'set'
4
3
  require 'fileutils'
5
4
  require File.dirname(__FILE__) + '/../lib/sequencer'
6
5
 
7
- TEST_DIR = File.dirname(__FILE__) + "/tmp"
6
+ TEST_DIR = File.expand_path(File.dirname(__FILE__)) + "/tmp"
8
7
 
9
8
  def emit_test_dirs
10
9
  start_f = 123
@@ -59,131 +58,166 @@ def teardown_test_dirs
59
58
  FileUtils.rm_rf(TEST_DIR)
60
59
  end
61
60
 
62
- context "Sequencer.glob_and_padding_for should" do
61
+ class Test_glob_and_padding_for < Test::Unit::TestCase
63
62
 
64
- specify "return proper glob pattern and padding for a path with extension" do
63
+ def test_returns_proper_glob_pattern_padding_for_a_path_with_extension
65
64
  glob, pad = Sequencer.glob_and_padding_for("file.00001.gif")
66
- glob.should.equal "file.[0-9][0-9][0-9][0-9][0-9].gif"
67
- pad.should.equal 5
65
+ assert_equal "file.[0-9][0-9][0-9][0-9][0-9].gif", glob
66
+ assert_equal 5, pad
68
67
  end
69
-
70
- specify "return proper glob pattern and padding for a path without extension" do
68
+
69
+ def test_returns_proper_glob_pattern_and_padding_for_a_path_without_extension
71
70
  glob, pad = Sequencer.glob_and_padding_for("file.00001")
72
- glob.should.equal "file.[0-9][0-9][0-9][0-9][0-9]"
73
- pad.should.equal 5
71
+ assert_equal "file.[0-9][0-9][0-9][0-9][0-9]", glob
72
+ assert_equal 5, pad
74
73
  end
75
74
 
76
- specify "return nil for a file that is not a sequence" do
75
+ def return_nil_for_a_file_that_is_not_in_the_sequence
77
76
  glob, pad = Sequencer.glob_and_padding_for("file")
78
- glob.should.be.nil
77
+ assert_nil glob
79
78
  end
80
79
  end
81
80
 
82
- context "Sequencer.entries should" do
83
- before { emit_test_dirs }
84
- after { teardown_test_dirs }
85
- specify "return entries for every sequence in a directory" do
81
+ class Sequencer_entries_should < Test::Unit::TestCase
82
+ def setup; emit_test_dirs; end
83
+ def teardown; teardown_test_dirs; end
84
+
85
+ def test_returns_entries_for_every_sequence_in_a_directory
86
86
  entries = Sequencer.entries(TEST_DIR + "/many_seqs")
87
+ flunk "this test is not finished"
87
88
  end
88
89
  end
89
90
 
90
- context "A Sequence created from unpadded files should" do
91
- before { emit_test_dirs }
92
- after { teardown_test_dirs }
91
+ class A_Sequence_created_from_unpadded_files_should < Test::Unit::TestCase
92
+ def setup; emit_test_dirs; end
93
+ def teardown; teardown_test_dirs; end
93
94
 
94
- specify "be properly created" do
95
+ def test_properly_created
95
96
  s = Sequencer.from_single_file(TEST_DIR + "/natural_numbering/somefiles 5545168.png")
96
- s.should.not.be.nil
97
- s.expected_frames.should.equal 30
98
- s.file_count.should.equal 30
99
- s.pattern.should.equal "somefiles %07d.png"
97
+ assert_not_nil s
98
+ assert_equal 30, s.expected_frames
99
+ assert_equal 30, s.file_count
100
+ assert_equal "somefiles %07d.png", s.pattern
101
+ end
102
+ end
103
+
104
+ class A_Sequence_created_from_a_file_that_has_no_numbering_slot_should
105
+ def setup; @single = Sequencer::Sequence.new("/tmp", ["foo.tif"]); end
106
+
107
+ def test_report_a_pattern_that_is_the_name_as_filename
108
+ assert_equal 'foo.tif', @single.pattern
109
+ assert @single.single_file?
110
+ assert_equal 1, @single.expected_frames
111
+ assert_equal "#<foo.tif>", @single.inspect
100
112
  end
101
113
  end
102
114
 
103
- context "A Sequence created from a file that has no numbering slot should" do
104
- before { @single = Sequencer::Sequence.new("/tmp", ["foo.tif"]) }
115
+ class Sequencer_bulk_rename_should < Test::Unit::TestCase
116
+ def setup
117
+ emit_test_dirs
118
+ @with_gaps = Sequencer.from_single_file(TEST_DIR + "/sequence_and_sole_file/broken_seq.000245.tif")
119
+ end
120
+
121
+ def teardown
122
+ teardown_test_dirs
123
+ end
105
124
 
106
- specify "report a pattern that is the same as filename" do
107
- @single.pattern.should.equal "foo.tif"
108
- @single.should.be.single_file?
109
- @single.expected_frames.should.equal 1
110
- @single.inspect.should.equal "#<foo.tif>"
125
+ def test_return_a_new_Sequencer_with_right_parameters
126
+ res = @with_gaps.bulk_rename("another_base")
127
+ assert_equal @with_gaps.length, res.length
128
+ assert_equal @with_gaps.directory, res.directory
129
+ assert_equal "another_base.%03d.tif", res.pattern
130
+
131
+ assert File.exist?(res.to_paths[0])
132
+ assert File.exist?(res.to_paths[-1])
111
133
  end
112
134
  end
113
135
 
114
- context "A Sequence created from pad-numbered files should" do
115
- before do
136
+ class A_Sequence_created_from_pad_numbered_files_should < Test::Unit::TestCase
137
+ def setup
116
138
  emit_test_dirs
117
139
  @gapless = Sequencer.from_single_file(TEST_DIR + "/sequence_and_sole_file/seq1.000245.tif")
118
140
  @with_gaps = Sequencer.from_single_file(TEST_DIR + "/sequence_and_sole_file/broken_seq.000245.tif")
119
141
  @single = Sequencer.from_single_file(TEST_DIR + "/sequence_and_sole_file/single_file.002123154.tif")
120
142
  end
121
143
 
122
- after { teardown_test_dirs }
144
+ def teardown
145
+ teardown_test_dirs
146
+ end
123
147
 
124
- specify "initialize itself from one path to a file in the sequence without gaps" do
125
- @gapless.should.not.be.nil
126
- @gapless.should.be.kind_of(Sequencer::Sequence)
127
- @gapless.should.respond_to(:gaps?)
128
- @gapless.should.not.be.single_file?
148
+ def test_initialize_itself_from_one_path_to_a_file_in_the_sequence_without_gaps
149
+ assert_not_nil @gapless
150
+ assert_kind_of Sequencer::Sequence, @gapless
151
+ assert_respond_to @gapless, :gaps?
152
+ assert !@gapless.single_file?
129
153
 
130
- @gapless.should.blaming("this is a gapless sequence").not.be.gaps?
131
- @gapless.file_count.should.blaming("actual file count in sequence").equal(446)
132
- @gapless.length.should.blaming("actual file count in sequence").equal(446)
133
- @gapless.expected_frames.should.blaming("expected frame count in sequence").equal(446)
134
- @gapless.inspect.should.blaming("inspect itself").equal('#<seq1.[123..568].tif>')
135
- @gapless.pattern.should.equal 'seq1.%06d.tif'
154
+ assert !@gapless.gaps?, "this is a gapless sequence"
155
+ assert_equal 446, @gapless.file_count, "actual file count in sequence"
156
+ assert_equal 446, @gapless.length, "actual file count in sequence"
157
+ assert_equal 446, @gapless.expected_frames, "expected frame count in sequence"
158
+ assert_equal '#<seq1.[123..568].tif>', @gapless.inspect
136
159
 
137
160
  files = @gapless.to_a
138
- files.length.should.equal 446
139
- files[0].should.equal 'seq1.000123.tif'
161
+ assert_equal 446, files.length
162
+ assert_equal 'seq1.000123.tif', files[0]
140
163
 
141
164
  paths = @gapless.to_paths
142
- paths.length.should.equal 446
143
- paths[0].should.equal(File.dirname(__FILE__) + "/tmp/sequence_and_sole_file/seq1.000123.tif")
165
+ assert_equal 446, paths.length
166
+ assert_equal File.expand_path(File.dirname(__FILE__)) + "/tmp/sequence_and_sole_file/seq1.000123.tif", paths[0]
144
167
  end
145
168
 
146
- specify "initialize itself from one path to a file in the sequence with gaps" do
147
- @with_gaps.should.not.be.nil
148
- @with_gaps.should.be.kind_of(Sequencer::Sequence)
149
- @with_gaps.should.not.be.single_file?
169
+ def test_initialize_itself_from_one_path_to_a_file_in_the_sequence_with_gaps
170
+ assert_not_nil @with_gaps
171
+ assert_kind_of Sequencer::Sequence, @with_gaps
172
+ assert !@with_gaps.single_file?
150
173
 
151
- @with_gaps.should.be.gaps?
152
- @with_gaps.gap_count.should.equal 1
153
- @with_gaps.segment_count.should.equal 2
154
- @with_gaps.missing_frames.should.equal(9)
155
- @with_gaps.inspect.should.blaming("inspect itself").equal('#<broken_seq.[123..568, 578..702].tif>')
156
- @with_gaps.should.include("broken_seq.000123.tif")
157
- @with_gaps.should.not.include("bogus.123.tif")
174
+ assert @with_gaps.gaps?
175
+ assert_equal 1, @with_gaps.gap_count
176
+ assert_equal 2, @with_gaps.segment_count
177
+ assert_equal 9, @with_gaps.missing_frames
178
+ assert_equal '#<broken_seq.[123..568, 578..702].tif>', @with_gaps.inspect
179
+ assert @with_gaps.include?("broken_seq.000123.tif")
180
+ assert !@with_gaps.include?("bogus.123.tif")
158
181
  end
159
182
 
160
- specify "return subsequences without gaps" do
183
+ def test_return_subsequences_without_gaps
161
184
  subseqs = @with_gaps.to_sequences
162
- subseqs[0].should.be.kind_of(Sequencer::Sequence)
163
- subseqs[1].should.be.kind_of(Sequencer::Sequence)
185
+ assert_kind_of Sequencer::Sequence, subseqs[0]
186
+ assert_kind_of Sequencer::Sequence, subseqs[1]
164
187
 
165
188
  first_seq, second_seq = subseqs
166
- first_seq.first_frame_no.should.equal 123
167
- first_seq.last_frame_no.should.equal 568
168
- second_seq.first_frame_no.should.equal 578
169
- second_seq.last_frame_no.should.equal 702
189
+ assert_equal 123, first_seq.first_frame_no
190
+ assert_equal 568, first_seq.last_frame_no
191
+ assert_equal 578, second_seq.first_frame_no
192
+ assert_equal 702, second_seq.last_frame_no
170
193
 
171
- first_seq.directory.should.equal second_seq.directory
172
- first_seq.directory.should.equal @with_gaps.directory
194
+ assert_equal second_seq.directory, first_seq.directory
195
+ assert_equal @with_gaps.directory, first_seq.directory
173
196
  end
174
197
 
175
- specify "list all sequences in directory and subdirectories using the pattern" do
198
+ def test_list_all_sequences_in_directory_and_subdirectories_using_the_pattern
176
199
  s = Sequencer.from_glob(TEST_DIR + "/**/*.tif")
177
- inspected = '[#<single.tif>, #<seq1.[458..512].tif>, #<anotherS [228..312].tif>, #<in_subdir [445..471].tif>, #<seq1.[123..568].tif>, #<somefile.tif>, #<single_file.002123154.tif>, #<broken_seq.[123..568, 578..702].tif>]'
178
- s.inspect.should.equal inspected
179
- end
180
-
181
- specify "initialize itself from a single file" do
182
- @single.should.be.single_file?
183
- @single.inspect.should.equal '#<single_file.002123154.tif>'
184
- @single.should.not.be.gaps?
185
- @single.expected_frames.should.equal 1
186
- @single.file_count.should.equal 1
200
+ # Here we need to use a Set since Ruby does not
201
+ ref_set = Set.new([
202
+ "#<anotherS [228..312].tif>",
203
+ "#<seq1.[458..512].tif>",
204
+ "#<single.tif>",
205
+ "#<in_subdir [445..471].tif>",
206
+ "#<broken_seq.[123..568, 578..702].tif>",
207
+ "#<seq1.[123..568].tif>",
208
+ "#<single_file.002123154.tif>",
209
+ "#<somefile.tif>"
210
+ ])
211
+ output_sequences = Set.new(s.map{|sequence| sequence.inspect })
212
+ assert_equal ref_set, output_sequences
213
+ end
214
+
215
+ def test_initialize_itself_from_a_single_file
216
+ assert @single.single_file?
217
+ assert_equal '#<single_file.002123154.tif>', @single.inspect
218
+ assert !@single.gaps?
219
+ assert_equal 1, @single.expected_frames
220
+ assert_equal 1, @single.file_count
187
221
  end
188
222
 
189
223
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequencer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
5
- prerelease: false
6
- segments:
7
- - 1
8
- - 0
9
- - 3
10
- version: 1.0.3
4
+ prerelease:
5
+ version: 1.0.5
11
6
  platform: ruby
12
7
  authors:
13
8
  - Julik Tarkhanov
@@ -15,61 +10,45 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2010-10-26 00:00:00 +02:00
13
+ date: 2011-07-07 00:00:00 +02:00
19
14
  default_executable:
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
22
- name: test-spec
17
+ name: hoe
23
18
  prerelease: false
24
19
  requirement: &id001 !ruby/object:Gem::Requirement
25
20
  none: false
26
21
  requirements:
27
- - - ">="
22
+ - - ~>
28
23
  - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
24
+ version: "2.10"
33
25
  type: :development
34
26
  version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: hoe
37
- prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 21
44
- segments:
45
- - 2
46
- - 6
47
- - 1
48
- version: 2.6.1
49
- type: :development
50
- version_requirements: *id002
51
27
  description: Simplifies working with image sequences
52
28
  email:
53
29
  - me@julik.nl
54
30
  executables:
55
31
  - rseqls
56
32
  - rseqpad
33
+ - rseqrename
57
34
  extensions: []
58
35
 
59
36
  extra_rdoc_files:
60
37
  - History.txt
61
38
  - Manifest.txt
62
- - README.txt
39
+ - README.rdoc
63
40
  files:
64
41
  - .autotest
65
42
  - History.txt
66
43
  - Manifest.txt
67
- - README.txt
44
+ - README.rdoc
68
45
  - Rakefile
69
46
  - bin/rseqls
70
47
  - bin/rseqpad
48
+ - bin/rseqrename
71
49
  - lib/sequencer.rb
72
50
  - test/test_sequencer.rb
51
+ - .gemtest
73
52
  has_rdoc: true
74
53
  homepage: http://guerilla-di.org/sequencer
75
54
  licenses: []
@@ -77,7 +56,7 @@ licenses: []
77
56
  post_install_message:
78
57
  rdoc_options:
79
58
  - --main
80
- - README.txt
59
+ - README.rdoc
81
60
  require_paths:
82
61
  - lib
83
62
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -85,23 +64,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
64
  requirements:
86
65
  - - ">="
87
66
  - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
67
  version: "0"
92
68
  required_rubygems_version: !ruby/object:Gem::Requirement
93
69
  none: false
94
70
  requirements:
95
71
  - - ">="
96
72
  - !ruby/object:Gem::Version
97
- hash: 3
98
- segments:
99
- - 0
100
73
  version: "0"
101
74
  requirements: []
102
75
 
103
76
  rubyforge_project: sequencer
104
- rubygems_version: 1.3.7
77
+ rubygems_version: 1.6.2
105
78
  signing_key:
106
79
  specification_version: 3
107
80
  summary: Simplifies working with image sequences