multi_exiftool 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.
Files changed (40) hide show
  1. data/CHANGELOG +1 -1
  2. data/LICENSE +21 -0
  3. data/Manifest +16 -23
  4. data/README +77 -16
  5. data/Rakefile +17 -38
  6. data/examples/01_simple_reading.rb +13 -0
  7. data/examples/02_simple_writing.rb +19 -0
  8. data/examples/03_reading_using_groups.rb +28 -0
  9. data/lib/multi_exiftool.rb +6 -38
  10. data/lib/multi_exiftool/executable.rb +67 -0
  11. data/lib/multi_exiftool/reader.rb +60 -0
  12. data/lib/multi_exiftool/values.rb +60 -0
  13. data/lib/multi_exiftool/writer.rb +55 -0
  14. data/multi_exiftool.gemspec +25 -16
  15. data/test/helper.rb +27 -0
  16. data/test/test_reader.rb +135 -0
  17. data/test/test_values.rb +75 -0
  18. data/test/test_values_using_groups.rb +61 -0
  19. data/test/test_writer.rb +102 -0
  20. metadata +49 -47
  21. data/COPYING +0 -165
  22. data/data/fixtures/read_non_existing_file.stderr +0 -1
  23. data/data/fixtures/read_non_existing_file.stdout +0 -0
  24. data/data/fixtures/read_one_file.stderr +0 -0
  25. data/data/fixtures/read_one_file.stdout +0 -92
  26. data/data/fixtures/read_two_files.stderr +0 -0
  27. data/data/fixtures/read_two_files.stdout +0 -212
  28. data/data/regression/read_command.rb +0 -12
  29. data/data/regression/read_command.rb.out +0 -16
  30. data/data/regression/write_command.rb +0 -16
  31. data/data/regression/write_command.rb.out +0 -40
  32. data/lib/multi_exiftool/command_generator.rb +0 -68
  33. data/lib/multi_exiftool/parser.rb +0 -43
  34. data/lib/multi_exiftool/read_object.rb +0 -57
  35. data/script/colorize.rb +0 -6
  36. data/script/generate_fixture.rb +0 -27
  37. data/test/test_command_generator.rb +0 -89
  38. data/test/test_helper.rb +0 -44
  39. data/test/test_parser.rb +0 -51
  40. data/test/test_read_object.rb +0 -36
data/CHANGELOG CHANGED
@@ -1 +1 @@
1
- v0.0.1 experimental
1
+ v0.1.0 First public release.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009-2010 Jan Friedrich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Manifest CHANGED
@@ -1,25 +1,18 @@
1
- Rakefile
1
+ CHANGELOG
2
+ LICENSE
2
3
  Manifest
3
- test/test_command_generator.rb
4
- test/test_helper.rb
5
- test/test_parser.rb
6
- test/test_read_object.rb
7
- lib/multi_exiftool.rb
8
- lib/multi_exiftool/parser.rb
9
- lib/multi_exiftool/command_generator.rb
10
- lib/multi_exiftool/read_object.rb
11
4
  README
12
- data/fixtures/read_non_existing_file.stderr
13
- data/fixtures/read_non_existing_file.stdout
14
- data/fixtures/read_two_files.stderr
15
- data/fixtures/read_one_file.stderr
16
- data/fixtures/read_one_file.stdout
17
- data/fixtures/read_two_files.stdout
18
- data/regression/read_command.rb
19
- data/regression/read_command.rb.out
20
- data/regression/write_command.rb
21
- data/regression/write_command.rb.out
22
- script/generate_fixture.rb
23
- script/colorize.rb
24
- CHANGELOG
25
- COPYING
5
+ Rakefile
6
+ examples/01_simple_reading.rb
7
+ examples/02_simple_writing.rb
8
+ examples/03_reading_using_groups.rb
9
+ lib/multi_exiftool.rb
10
+ lib/multi_exiftool/executable.rb
11
+ lib/multi_exiftool/reader.rb
12
+ lib/multi_exiftool/values.rb
13
+ lib/multi_exiftool/writer.rb
14
+ test/helper.rb
15
+ test/test_reader.rb
16
+ test/test_values.rb
17
+ test/test_values_using_groups.rb
18
+ test/test_writer.rb
data/README CHANGED
@@ -1,29 +1,90 @@
1
- = MULTI EXIFTOOL
2
- Jan Friedrich
3
- http://multi_exiftool.rubyforge.org
1
+ = MultiExiftool
4
2
 
5
- == DESCRIPTION:
3
+ == Description
6
4
 
7
- FIXME (describe your package)
5
+ This library is wrapper for the Exiftool command-line application
6
+ (http://www.sno.phy.queensu.ca/~phil/exiftool) written by Phil Harvey.
7
+ It is designed for dealing with multiple files at once by creating
8
+ commands to call exiftool with various arguments, call it and parsing
9
+ the results.
8
10
 
9
- == FEATURES/PROBLEMS:
11
+ == Examples
10
12
 
11
- * FIXME (list of features or problems)
13
+ === Reading
12
14
 
13
- == SYNOPSIS:
15
+ require 'multi_exiftool'
14
16
 
15
- FIXME (code sample of usage)
17
+ reader = MultiExiftool::Reader.new
18
+ reader.filenames = Dir['*.jpg']
19
+ results = reader.read
20
+ results.each do |values|
21
+ puts "#{values.file_name}: #{values.comment}"
22
+ end
16
23
 
17
- == REQUIREMENTS:
24
+ === Writing
18
25
 
19
- * FIXME (list of requirements)
26
+ require 'multi_exiftool'
27
+
28
+ writer = MultiExiftool::Writer.new
29
+ writer.filenames = Dir['*.jpg']
30
+ writer.values = {creator: 'Jan Friedrich', copyright: 'Public Domain'}
31
+ if writer.write
32
+ puts 'ok'
33
+ else
34
+ puts writer.errors.join
35
+ end
20
36
 
21
- == INSTALL:
37
+ === Further Examples
22
38
 
23
- * FIXME (sudo gem install, anything else)
39
+ See the examples in the examples directory.
24
40
 
25
- == LICENSE:
26
41
 
27
- GNU Lesser General Public License (LGPL)
42
+ == Requirements
43
+
44
+ - Ruby 1.9.1 or higher
45
+ - An installation of the Exiftool command-line application.
46
+ Instructions for installation you can find under
47
+ http://www.sno.phy.queensu.ca/~phil/exiftool/install.html .
48
+
49
+ == Installation
50
+
51
+ First you need Exiftool (see under Requirements above). Then you can simply
52
+ install the gem with
53
+ gem install multi_exiftool
54
+
55
+ == Contribution
56
+
57
+ The code is also hostet in a git repository on Gitorious at
58
+ http://gitorious.org/multi_exiftool
59
+ or
60
+ http://github.com/janfri/multi_exiftool-redesign
61
+ feel free to contribute!
62
+
63
+ == Author
64
+
65
+ Jan Friedrich (janfri26 AT gmail DOT com)
66
+
67
+ == Copyright / License
68
+
69
+ The MIT License
70
+
71
+ Copyright (c) 2009-2010 Jan Friedrich
72
+
73
+ Permission is hereby granted, free of charge, to any person obtaining a copy
74
+ of this software and associated documentation files (the "Software"), to deal
75
+ in the Software without restriction, including without limitation the rights
76
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77
+ copies of the Software, and to permit persons to whom the Software is
78
+ furnished to do so, subject to the following conditions:
79
+
80
+ The above copyright notice and this permission notice shall be included in
81
+ all copies or substantial portions of the Software.
82
+
83
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
88
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
89
+ THE SOFTWARE.
28
90
 
29
- See file COPYING.txt for more details.
data/Rakefile CHANGED
@@ -1,43 +1,22 @@
1
1
  require 'echoe'
2
2
 
3
- Echoe.new 'multi_exiftool' do |p|
3
+ Echoe.new('multi_exiftool') do |p|
4
4
  p.author = 'Jan Friedrich'
5
- p.email = 'janfri.rubyforge@gmail.com'
6
- p.project = 'multiexiftool'
7
- p.url = 'http://multiexiftool.rubyforge.org'
8
- p.development_dependencies = ['yact']
9
- end
10
-
11
- namespace :reg do
12
-
13
- ROOT_DIR = File.dirname(__FILE__)
14
- SCRIPT_DIR = File.join(ROOT_DIR, 'script')
15
- DATA_DIR = File.join(ROOT_DIR, %w(data regression))
16
- RB_FILES = File.join(DATA_DIR, '*.rb')
17
-
18
- desc 'Generate regression data'
19
- task :generate
20
-
21
- def target src
22
- src + '.out'
5
+ p.email = 'janfri26@gmail.com'
6
+ p.summary = 'This library is wrapper for the Exiftool command-line application (http://www.sno.phy.queensu.ca/~phil/exiftool).'
7
+ p.description = 'This library is wrapper for the Exiftool command-line application (http://www.sno.phy.queensu.ca/~phil/exiftool) written by Phil Harvey. It is designed for dealing with multiple files at once by creating commands to call exiftool with various arguments, call it and parsing the results.'
8
+ p.ruby_version = '>=1.9.1'
9
+ p.url = 'http://rubyforge.org/projects/multiexiftool'
10
+ p.install_message = %q{
11
+ +-----------------------------------------------------------------------+
12
+ | Please ensure you have installed exiftool version 7.65 or higher and |
13
+ | it's found in your PATH (Try "exiftool -ver" on your commandline). |
14
+ | For more details see |
15
+ | http://www.sno.phy.queensu.ca/~phil/exiftool/install.html |
16
+ +-----------------------------------------------------------------------+
17
+ }
18
+ p.development_dependencies = ['contest']
19
+ p.eval = proc do
20
+ self.requirements << 'exiftool, version 7.65 or higher'
23
21
  end
24
-
25
- FileList[RB_FILES].each do |src|
26
- target = target(src)
27
- file target => src do |t|
28
- sh "ruby #{t.prerequisites.first} > #{t.name}"
29
- end
30
-
31
- task :generate => target
32
- end
33
-
34
- desc 'Running regression tests'
35
- task :test => :generate do
36
- FileList[RB_FILES].each do |src|
37
- target = target(src)
38
- puts '-' * 8 << File.basename(src)
39
- sh "ruby #{src} | wdiff -n #{target} - | #{File.join(SCRIPT_DIR, 'colorize.rb')}"# ; echo x >/dev/null"
40
- end
41
- end
42
-
43
22
  end
@@ -0,0 +1,13 @@
1
+ require 'multi_exiftool'
2
+
3
+ if ARGV.empty?
4
+ $stderr.puts 'No filenames given.'
5
+ exit -1
6
+ end
7
+
8
+ reader = MultiExiftool::Reader.new
9
+ reader.filenames = ARGV
10
+ results = reader.read
11
+ results.each do |values|
12
+ puts "#{values.file_name}: #{values.comment}"
13
+ end
@@ -0,0 +1,19 @@
1
+ require 'multi_exiftool'
2
+
3
+ if ARGV.empty?
4
+ $stderr.puts 'No filenames given.'
5
+ exit -1
6
+ end
7
+
8
+ puts 'Please enter a comment for the given files:'
9
+ comment = $stdin.gets.chomp
10
+
11
+ writer = MultiExiftool::Writer.new
12
+ writer.filenames = ARGV
13
+ writer.overwrite_original = true
14
+ writer.values = {comment: comment}
15
+ if writer.write
16
+ puts 'ok'
17
+ else
18
+ puts writer.errors.join
19
+ end
@@ -0,0 +1,28 @@
1
+ require 'multi_exiftool'
2
+
3
+ if ARGV.empty?
4
+ $stderr.puts 'No filenames given.'
5
+ exit -1
6
+ end
7
+
8
+ reader = MultiExiftool::Reader.new
9
+ reader.filenames = ARGV
10
+ reader.group = 0
11
+ results = reader.read
12
+ results.each do |values|
13
+ # direct access
14
+ puts values.file.filename
15
+ # access via block without parameter
16
+ values.iptc do
17
+ self.keywords do
18
+ puts " Keywords (IPCT): #{Array(self).join(', ')}"
19
+ end
20
+ end
21
+ # access via block with parameter
22
+ values.xmp do |xmp|
23
+ xmp.keywords do |kw|
24
+ puts " Keywords (XMP): #{Array(kw).join(', ')}"
25
+ end
26
+ end
27
+ end
28
+
@@ -1,43 +1,11 @@
1
- require 'multi_exiftool/command_generator'
2
- require 'multi_exiftool/parser'
3
- require 'multi_exiftool/read_object'
4
- require 'open3'
5
- require 'ostruct'
6
- require 'logger'
7
-
8
- # monkey patching --- the save way :D
9
- class OpenStruct
10
- unless self.new.respond_to? :to_hash
11
- def to_hash
12
- @table
13
- end
14
- end
15
- end
1
+ # coding: utf-8
2
+ require_relative 'multi_exiftool/values'
3
+ require_relative 'multi_exiftool/reader'
4
+ require_relative 'multi_exiftool/writer'
16
5
 
17
6
  module MultiExiftool
18
7
 
19
- class << self
20
-
21
- attr_accessor :logger
22
-
23
- def read *filenames
24
- cmd = CommandGenerator.read_command *filenames
25
- stdin, stdout, stderr = Open3.popen3(cmd)
26
- result = Parser.parse(stdout, stderr)
27
- result.map {|r| ReadObject.new(r.data)}
28
- end
29
-
30
-
31
- def write change_set, *filenames
32
- cmd = CommandGenerator.write_command change_set, *filenames
33
- @logger.debug cmd
34
- stdin, stdout, stderr = Open3.popen3(cmd)
35
- result = Parser.parse(stdout, stderr)
36
- result.inject(true) {|r| r.errors.empty?}
37
- end
38
-
39
- end
40
-
41
- @logger = Logger.new nil
8
+ class Error < ::StandardError; end
42
9
 
43
10
  end
11
+
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ require 'open3'
3
+ require 'shellwords'
4
+
5
+ module MultiExiftool
6
+
7
+ # Mixin for Reader and Writer.
8
+ module Executable
9
+
10
+ attr_accessor :exiftool_command, :errors, :numerical
11
+ attr_writer :options, :filenames
12
+
13
+ def initialize
14
+ @exiftool_command = 'exiftool'
15
+ @options = {}
16
+ end
17
+
18
+ def options
19
+ opts = @options.dup
20
+ opts[:n] = true if @numerical
21
+ opts
22
+ end
23
+
24
+ def filenames
25
+ Array(@filenames)
26
+ end
27
+
28
+ def execute # :nodoc:
29
+ prepare_execution
30
+ execute_command
31
+ parse_results
32
+ end
33
+
34
+ private
35
+
36
+ def escape str
37
+ Shellwords.escape(str)
38
+ end
39
+
40
+ def escaped_filenames
41
+ raise MultiExiftool::Error.new('No filenames.') if filenames.empty?
42
+ @filenames.map { |fn| Shellwords.escape(fn) }
43
+ end
44
+
45
+ def options_args
46
+ opts = options
47
+ return [] if opts.empty?
48
+ opts.map do |opt, val|
49
+ if val == true
50
+ "-#{opt}"
51
+ else
52
+ "-#{opt} #{val}"
53
+ end
54
+ end
55
+ end
56
+
57
+ def prepare_execution
58
+ @errors = []
59
+ end
60
+
61
+ def execute_command
62
+ stdin, @stdout, @stderr = Open3.popen3(command)
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,60 @@
1
+ # coding: utf-8
2
+ require_relative 'executable'
3
+ require 'json'
4
+
5
+ module MultiExiftool
6
+
7
+ # Handle reading of metadata via exiftool.
8
+ # Composing the command for the command-line executing it and parsing
9
+ # the results as well as possible errors.
10
+ class Reader
11
+
12
+ MANDATORY_ARGS = %w(-J)
13
+
14
+ attr_accessor :tags, :group
15
+
16
+ include Executable
17
+
18
+ # Options to use with the exiftool command.
19
+ def options
20
+ opts = super
21
+ if @group
22
+ opts["g#{@group}"] = true
23
+ end
24
+ opts
25
+ end
26
+
27
+ # Getting the command for the command-line which would be executed
28
+ # when calling #read. It could be useful for logging, debugging or
29
+ # maybe even for creating a batch-file with exiftool command to be
30
+ # processed.
31
+ def command
32
+ cmd = [exiftool_command]
33
+ cmd << MANDATORY_ARGS
34
+ cmd << options_args
35
+ cmd << tags_args
36
+ cmd << escaped_filenames
37
+ cmd.flatten.join(' ')
38
+ end
39
+
40
+ alias read execute # :nodoc:
41
+
42
+ private
43
+
44
+ def tags_args
45
+ return [] unless @tags
46
+ @tags.map {|tag| "-#{tag}"}
47
+ end
48
+
49
+ def parse_results
50
+ stdout = @stdout.read
51
+ @errors = @stderr.readlines
52
+ json = JSON.parse(stdout)
53
+ json.map {|values| Values.new(values)}
54
+ rescue JSON::ParserError
55
+ return []
56
+ end
57
+
58
+ end
59
+
60
+ end