sequencer 1.0.5 → 1.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.
- data/Gemfile +6 -0
- data/History.txt +10 -6
- data/README.rdoc +6 -6
- data/Rakefile +24 -7
- data/bin/rseqpad +8 -22
- data/lib/sequencer.rb +22 -6
- data/lib/sequencer/padder.rb +29 -0
- data/sequencer.gemspec +52 -0
- data/test/test_sequencer.rb +6 -0
- metadata +54 -51
- data/.autotest +0 -23
- data/.gemtest +0 -0
- data/Manifest.txt +0 -10
data/Gemfile
ADDED
data/History.txt
CHANGED
@@ -1,26 +1,30 @@
|
|
1
|
-
=== 1.0
|
1
|
+
=== 1.1.0
|
2
|
+
|
3
|
+
* Make Sequence comparable to allow for sorted and unique sequences
|
4
|
+
|
5
|
+
=== 1.0.5
|
2
6
|
|
3
7
|
* Dicking around with testing frameworks that become obsolete is the worst thing ever.
|
4
8
|
|
5
|
-
=== 1.0.4
|
9
|
+
=== 1.0.4
|
6
10
|
|
7
11
|
* Add rseqrename binary that batch-renames sequences
|
8
12
|
|
9
|
-
=== 1.0.3
|
13
|
+
=== 1.0.3
|
10
14
|
|
11
15
|
* Add rseqpad binary that zero-pads sequences
|
12
16
|
|
13
|
-
=== 1.0.2
|
17
|
+
=== 1.0.2
|
14
18
|
|
15
19
|
* Add Sequence#from_glob for scavenging all sequences from all subdirs
|
16
20
|
* Add Sequence#first_frame_no and Sequence#last_frame_no for first and last frame offset
|
17
21
|
* Add Sequence#to_sequences that returns the whole subsequences contained within a sequence
|
18
22
|
|
19
|
-
=== 1.0.1
|
23
|
+
=== 1.0.1
|
20
24
|
|
21
25
|
* Add Sequence#length, Sequence#to_a, Sequence#directory and Sequence#to_paths
|
22
26
|
|
23
|
-
=== 1.0.0
|
27
|
+
=== 1.0.0
|
24
28
|
|
25
29
|
* 1 major enhancement
|
26
30
|
|
data/README.rdoc
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
Sequencer is the swiss army knife of image sequence management for Ruby. It helps with things like
|
2
2
|
|
3
|
-
*
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
* Collapsing multibillion-files directory listings to sequence lists with sane names and sane string representations
|
4
|
+
* Detecting gaps in image sequences
|
5
|
+
* Renaming sequences for filename uniformity, number uniformity and so on
|
6
|
+
* Managing image sequences as whole units for media management
|
7
|
+
* ..and getting laid (sometimes)
|
8
8
|
|
9
9
|
== FEATURES:
|
10
10
|
|
data/Rakefile
CHANGED
@@ -1,13 +1,30 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
require 'rubygems'
|
3
|
-
require '
|
3
|
+
require 'jeweler'
|
4
4
|
require File.dirname(__FILE__) + "/lib/sequencer"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.version = Sequencer::VERSION
|
8
|
+
gem.name = "sequencer"
|
9
|
+
gem.summary = "Image sequence sorting, scanning and manipulation"
|
10
|
+
gem.email = "me@julik.nl"
|
11
|
+
gem.homepage = "http://guerilla-di.org/sequencer"
|
12
|
+
gem.authors = ["Julik Tarkhanov"]
|
13
|
+
gem.license = 'MIT'
|
14
|
+
gem.executables = %w( rseqls rseqpad rseqrename )
|
15
|
+
|
16
|
+
# Do not package invisibles
|
17
|
+
gem.files.exclude ".*"
|
11
18
|
end
|
12
19
|
|
13
|
-
|
20
|
+
Jeweler::RubygemsDotOrgTasks.new
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
desc "Run all tests"
|
24
|
+
Rake::TestTask.new("test") do |t|
|
25
|
+
t.libs << "test"
|
26
|
+
t.pattern = 'test/**/test_*.rb'
|
27
|
+
t.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
task :default => [ :test ]
|
data/bin/rseqpad
CHANGED
@@ -1,36 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require File.dirname(__FILE__) + "/../lib/sequencer"
|
4
|
+
require 'optparse'
|
5
|
+
$pad = nil
|
6
|
+
OptionParser.new do | op |
|
7
|
+
op.on(" -z", "--zeroes LENGTH", Integer, "Set the specific pad length (otherwise sequence length)"){|pad| $pad = pad }
|
8
|
+
end.parse!
|
4
9
|
|
5
10
|
d = ARGV.shift || Dir.pwd
|
6
11
|
|
7
12
|
renames = []
|
8
13
|
Sequencer.entries(d).each do | e |
|
9
14
|
next if e.length < 2
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
puts "Repadding sequence #{e} with #{padz} zeroes"
|
14
|
-
|
15
|
-
e.each do | f |
|
16
|
-
rep_name = f.gsub(/([\.\-\_]?)(\d+)\.(\w+)$/) do
|
17
|
-
".%0#{padz}d.%s" % [$2.to_i, $3]
|
18
|
-
end
|
19
|
-
# Now this is a replaced name
|
20
|
-
from_to = [File.join(e.directory, f), File.join(e.directory, rep_name)]
|
21
|
-
renames.push(from_to)
|
22
|
-
end
|
15
|
+
r = Sequencer::Padder.new(e, $pad)
|
16
|
+
renames += r.get_renames
|
23
17
|
end
|
24
18
|
|
25
|
-
|
26
|
-
destinations = renames.map{|e| e[1] }
|
27
|
-
|
28
|
-
if (destinations.uniq.length != destinations.length)
|
29
|
-
twice = destinations.length - destinations.uniq.length
|
30
|
-
$stderr.puts "Cannot rename - #{twice} files will overwrite each other or files will be renamed twice"
|
31
|
-
twice.each {|e| $stderr.puts e }
|
32
|
-
exit -1
|
33
|
-
end
|
19
|
+
Sequencer::Padder.check_renames_for_dupes(renames)
|
34
20
|
|
35
21
|
# And do the job
|
36
22
|
renames.each do | from, to |
|
data/lib/sequencer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Sequencer
|
2
|
-
VERSION = '1.0
|
2
|
+
VERSION = '1.1.0'
|
3
3
|
NUMBERS_AT_END = /(\d+)([^\d]+)?$/
|
4
4
|
|
5
5
|
extend self
|
@@ -82,7 +82,7 @@ module Sequencer
|
|
82
82
|
public
|
83
83
|
|
84
84
|
class Sequence
|
85
|
-
include Enumerable
|
85
|
+
include Enumerable, Comparable
|
86
86
|
attr_reader :pattern
|
87
87
|
attr_reader :directory
|
88
88
|
|
@@ -217,6 +217,18 @@ module Sequencer
|
|
217
217
|
map.merge(filename => (with_pattern % frame_no))
|
218
218
|
end
|
219
219
|
|
220
|
+
destination = into_directory || directory
|
221
|
+
|
222
|
+
# Ensure it's there
|
223
|
+
if (!File.exist?(destination))
|
224
|
+
raise "The destination #{destination} does not exist"
|
225
|
+
end
|
226
|
+
|
227
|
+
# Ensure it's a dir
|
228
|
+
if (!File.directory?(destination))
|
229
|
+
raise "The destination #{destination} is not a directory"
|
230
|
+
end
|
231
|
+
|
220
232
|
# Ensure we will not produce dupes
|
221
233
|
if (rename_map.values.uniq.length != rename_map.length)
|
222
234
|
raise "This would would produce non-unique files"
|
@@ -226,12 +238,10 @@ module Sequencer
|
|
226
238
|
raise "This would overwrite old files with the renamed ones (#{error[0..1]}.join(',')..)"
|
227
239
|
end
|
228
240
|
|
229
|
-
if (error = (Dir.entries(
|
241
|
+
if (error = (Dir.entries(destination) & rename_map.values)).any?
|
230
242
|
raise "Files that will be created by the rename are already in place (#{error[0..1]}.join(',')..)"
|
231
243
|
end
|
232
244
|
|
233
|
-
destination = into_directory || directory
|
234
|
-
|
235
245
|
rename_map.each_pair do | from_path, to_path |
|
236
246
|
src, dest = File.join(directory, from_path), File.join(destination, to_path)
|
237
247
|
File.rename(src, dest)
|
@@ -241,6 +251,10 @@ module Sequencer
|
|
241
251
|
self.class.new(destination, rename_map.values)
|
242
252
|
end
|
243
253
|
|
254
|
+
def <=>(another)
|
255
|
+
to_a <=> another.to_a
|
256
|
+
end
|
257
|
+
|
244
258
|
private
|
245
259
|
|
246
260
|
def natural_sort(ar)
|
@@ -263,7 +277,7 @@ module Sequencer
|
|
263
277
|
["%0#{$1.length}d", $2].join
|
264
278
|
end
|
265
279
|
|
266
|
-
# Look at the first file in the sequence.
|
280
|
+
# Look at the first file in the sequence.
|
267
281
|
lowest_padding = @filenames[0].scan(NUMBERS_AT_END).flatten.shift.length
|
268
282
|
if lowest_padding < highest_padding # Natural numbering
|
269
283
|
@pattern = @filenames[0].gsub(NUMBERS_AT_END) do
|
@@ -297,3 +311,5 @@ module Sequencer
|
|
297
311
|
end
|
298
312
|
|
299
313
|
end
|
314
|
+
|
315
|
+
require File.dirname(__FILE__) + "/sequencer/padder"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Sequencer::Padder
|
2
|
+
def initialize(with_sequence, pad_length = nil)
|
3
|
+
@sequence = with_sequence
|
4
|
+
@padz = (pad_length || e.length.to_s.length).to_i
|
5
|
+
end
|
6
|
+
|
7
|
+
# Return an array of tuples containing /source/file/path and /destination/file/path
|
8
|
+
# renames
|
9
|
+
def get_renames
|
10
|
+
@sequence.inject([]) do | renames, f |
|
11
|
+
rep_name = f.gsub(/([\.\-\_]?)(\d+)\.(\w+)$/) do
|
12
|
+
".%0#{@padz}d.%s" % [$2.to_i, $3]
|
13
|
+
end
|
14
|
+
# Now this is a replaced name
|
15
|
+
from_to = [File.join(e.directory, f), File.join(e.directory, rep_name)]
|
16
|
+
renames.push(from_to)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.check_renames_for_dupes(renames)
|
21
|
+
# Check for dupes
|
22
|
+
destinations = renames.map{|e| e[1] }
|
23
|
+
|
24
|
+
if (destinations.uniq.length != destinations.length)
|
25
|
+
twice = destinations - destinations.uniq
|
26
|
+
raise "Cannot rename - #{twice.join(', ')} will overwrite each other through mangled renames"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/sequencer.gemspec
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "sequencer"
|
8
|
+
s.version = "1.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Julik Tarkhanov"]
|
12
|
+
s.date = "2012-03-31"
|
13
|
+
s.email = "me@julik.nl"
|
14
|
+
s.executables = ["rseqls", "rseqpad", "rseqrename"]
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"Gemfile",
|
20
|
+
"History.txt",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"bin/rseqls",
|
24
|
+
"bin/rseqpad",
|
25
|
+
"bin/rseqrename",
|
26
|
+
"lib/sequencer.rb",
|
27
|
+
"lib/sequencer/padder.rb",
|
28
|
+
"sequencer.gemspec",
|
29
|
+
"test/test_sequencer.rb"
|
30
|
+
]
|
31
|
+
s.homepage = "http://guerilla-di.org/sequencer"
|
32
|
+
s.licenses = ["MIT"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = "1.8.15"
|
35
|
+
s.summary = "Image sequence sorting, scanning and manipulation"
|
36
|
+
|
37
|
+
if s.respond_to? :specification_version then
|
38
|
+
s.specification_version = 3
|
39
|
+
|
40
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
41
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
42
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
43
|
+
else
|
44
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
45
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
46
|
+
end
|
47
|
+
else
|
48
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
49
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/test/test_sequencer.rb
CHANGED
@@ -180,6 +180,12 @@ class A_Sequence_created_from_pad_numbered_files_should < Test::Unit::TestCase
|
|
180
180
|
assert !@with_gaps.include?("bogus.123.tif")
|
181
181
|
end
|
182
182
|
|
183
|
+
def test_equals_another
|
184
|
+
assert_not_nil @with_gaps
|
185
|
+
another = Sequencer.from_single_file(TEST_DIR + "/sequence_and_sole_file/broken_seq.000245.tif")
|
186
|
+
assert_equal @with_gaps, another
|
187
|
+
end
|
188
|
+
|
183
189
|
def test_return_subsequences_without_gaps
|
184
190
|
subseqs = @with_gaps.to_sequences
|
185
191
|
assert_kind_of Sequencer::Sequence, subseqs[0]
|
metadata
CHANGED
@@ -1,82 +1,85 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequencer
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
4
5
|
prerelease:
|
5
|
-
version: 1.0.5
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Julik Tarkhanov
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
date: 2012-03-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jeweler
|
16
|
+
requirement: &8997550 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
18
23
|
prerelease: false
|
19
|
-
|
24
|
+
version_requirements: *8997550
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &8995670 !ruby/object:Gem::Requirement
|
20
28
|
none: false
|
21
|
-
requirements:
|
22
|
-
- -
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version:
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
25
33
|
type: :development
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
executables:
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *8995670
|
36
|
+
description:
|
37
|
+
email: me@julik.nl
|
38
|
+
executables:
|
31
39
|
- rseqls
|
32
40
|
- rseqpad
|
33
41
|
- rseqrename
|
34
42
|
extensions: []
|
35
|
-
|
36
|
-
extra_rdoc_files:
|
37
|
-
- History.txt
|
38
|
-
- Manifest.txt
|
43
|
+
extra_rdoc_files:
|
39
44
|
- README.rdoc
|
40
|
-
files:
|
41
|
-
-
|
45
|
+
files:
|
46
|
+
- Gemfile
|
42
47
|
- History.txt
|
43
|
-
- Manifest.txt
|
44
48
|
- README.rdoc
|
45
49
|
- Rakefile
|
46
50
|
- bin/rseqls
|
47
51
|
- bin/rseqpad
|
48
52
|
- bin/rseqrename
|
49
53
|
- lib/sequencer.rb
|
54
|
+
- lib/sequencer/padder.rb
|
55
|
+
- sequencer.gemspec
|
50
56
|
- test/test_sequencer.rb
|
51
|
-
- .gemtest
|
52
|
-
has_rdoc: true
|
53
57
|
homepage: http://guerilla-di.org/sequencer
|
54
|
-
licenses:
|
55
|
-
|
58
|
+
licenses:
|
59
|
+
- MIT
|
56
60
|
post_install_message:
|
57
|
-
rdoc_options:
|
58
|
-
|
59
|
-
- README.rdoc
|
60
|
-
require_paths:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
61
63
|
- lib
|
62
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
65
|
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version:
|
68
|
-
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
hash: 65822483
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
74
|
none: false
|
70
|
-
requirements:
|
71
|
-
- -
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version:
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
74
79
|
requirements: []
|
75
|
-
|
76
|
-
|
77
|
-
rubygems_version: 1.6.2
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.15
|
78
82
|
signing_key:
|
79
83
|
specification_version: 3
|
80
|
-
summary:
|
81
|
-
test_files:
|
82
|
-
- test/test_sequencer.rb
|
84
|
+
summary: Image sequence sorting, scanning and manipulation
|
85
|
+
test_files: []
|
data/.autotest
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
|
3
|
-
require 'autotest/restart'
|
4
|
-
|
5
|
-
# Autotest.add_hook :initialize do |at|
|
6
|
-
# at.extra_files << "../some/external/dependency.rb"
|
7
|
-
#
|
8
|
-
# at.libs << ":../some/external"
|
9
|
-
#
|
10
|
-
# at.add_exception 'vendor'
|
11
|
-
#
|
12
|
-
# at.add_mapping(/dependency.rb/) do |f, _|
|
13
|
-
# at.files_matching(/test_.*rb$/)
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# %w(TestA TestB).each do |klass|
|
17
|
-
# at.extra_class_map[klass] = "test/test_misc.rb"
|
18
|
-
# end
|
19
|
-
# end
|
20
|
-
|
21
|
-
# Autotest.add_hook :run_command do |at|
|
22
|
-
# system "rake build"
|
23
|
-
# end
|
data/.gemtest
DELETED
File without changes
|