file_pipeline 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 626e9aa686a528bc8bbcf08ba8a238cdfbae8d8b56918654cded4156964f831e
4
- data.tar.gz: ffa0eeb52c3af6789362d0886b6f90c1ae03e647f9a94e7323bfe8b9ae71149b
3
+ metadata.gz: 2669b6e193cbdf383b4db7bf1fe9e16a4519cefb152b394e34310ea9690d4ed6
4
+ data.tar.gz: 5c07a106071954420545dfec51b1110f71027614384e77d553f4132322848faa
5
5
  SHA512:
6
- metadata.gz: 577eeca6ca8df866f7521a534219290c3827208d28909c5b2cf1bab4f9dcaa33a5ac4cdd64860365eb4f49105208e95ce73951c24677b1f36563b3b9c8ef98d5
7
- data.tar.gz: a5ce5a25f0be6ee92f2afde5a7b37d52de0ede4063be0b0c1cbb919ba1a3a0bf81b2cdb05dfcde50f875ba9d16afa79865cbc3f69b552df72cf2d73207a324df
6
+ metadata.gz: b193249acfb972b2a0bc167728a2147d9e7c39e4469a4f3808ed9ff23b3db0cdbfa06000e3477a83058918a31174bad854821a95287abfb964965e6db02421d4
7
+ data.tar.gz: 265d513deaf12846e01c767c71a63c481bb0f21a8bc81d7b00e7ba2ea2291afb0c3d99cd9c3830fd37715772a8c807e3455fdfb3c4f14d558e5df5cc9ba52183
data/lib/file_pipeline.rb CHANGED
@@ -33,7 +33,7 @@ module FilePipeline
33
33
  def self.load(file_operation)
34
34
  const = file_operation.split('_').map(&:capitalize).join
35
35
  FilePipeline.load_file(file_operation) unless const_defined? const
36
- const_get 'FileOperations::' + const
36
+ const_get "FileOperations::#{const}"
37
37
  rescue NameError
38
38
  # TODO: implement autogenerating module names from file_operation src path
39
39
  const_get const
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'errors/failed_modification_error'
4
+ require_relative 'errors/misplaced_version_file_error'
4
5
  require_relative 'errors/missing_version_file_error'
5
6
  require_relative 'errors/source_directory_error'
6
7
  require_relative 'errors/source_file_error'
@@ -41,9 +41,9 @@ module FilePipeline
41
41
  # Appends the backtrace of the error that caused the exception to the
42
42
  # #default_message.
43
43
  def append_backtrace(str)
44
- return str + "\n" unless original_backtrace
44
+ return "#{str}\n" unless original_backtrace
45
45
 
46
- str + " Backtrace:\n#{original_backtrace}"
46
+ "#{str} Backtrace:\n#{original_backtrace}"
47
47
  end
48
48
 
49
49
  # Appends the message of the error that caused the exception to the
@@ -58,7 +58,7 @@ module FilePipeline
58
58
 
59
59
  # Returns a String with the #message for +self+.
60
60
  def default_message
61
- if info&.respond_to?(:operation) && info&.respond_to?(:log)
61
+ if info.respond_to?(:operation) && info.respond_to?(:log)
62
62
  msg = "#{info.operation&.name} with options"\
63
63
  " #{info.operation&.options} failed on #{@file}."
64
64
  append_error msg
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FilePipeline
4
+ module Errors
5
+ # Error class for exceptions that are raised when a new version is added,
6
+ # but the file is not in the VersionedFile's working directory.
7
+ class MisplacedVersionFileError < StandardError
8
+ # Path for of the misplaced file for the version.
9
+ attr_reader :file
10
+
11
+ # Path for the directory where the file should have been (the
12
+ # VersionedFile's working directory).
13
+ attr_reader :directory
14
+
15
+ def initialize(msg = nil, file: nil, directory: nil)
16
+ @file = file
17
+ @directory = directory
18
+ msg ||= default_message
19
+ super msg
20
+ end
21
+
22
+ private
23
+
24
+ def default_message
25
+ "File #{File.basename @file} was expected in #{@directory},"\
26
+ " but was in #{File.dirname @file}."
27
+ end
28
+ end
29
+ end
30
+ end
@@ -24,7 +24,7 @@ module FilePipeline
24
24
  end
25
25
 
26
26
  def self.strip_path(str) # :nodoc:
27
- str.sub(%r{ - \/?(\/|[-:.]+|\w+)+\.\w+$}, '')
27
+ str.sub(%r{ - /?(/|[-:.]+|\w+)+\.\w+$}, '')
28
28
  end
29
29
 
30
30
  # Redacts (deletes) all <tt>tags_to_delete</tt> in <tt>out_file</tt>.
@@ -41,10 +41,7 @@ module FilePipeline
41
41
  # Adds a file operation object #file_operations. The object must implement
42
42
  # a _run_ method (see FileOperations::FileOperation#run for details).
43
43
  def <<(file_operation_instance)
44
- unless file_operation_instance.respond_to? :run
45
- raise TypeError, 'File operations must implement a #run method'
46
- end
47
-
44
+ validate file_operation_instance
48
45
  @file_operations << file_operation_instance
49
46
  end
50
47
 
@@ -106,5 +103,15 @@ module FilePipeline
106
103
  operation.run version, directory, original
107
104
  end
108
105
  end
106
+
107
+ private
108
+
109
+ # Raises TypeError if <tt>file_operation_instance</tt> does not implement a
110
+ # #run method.
111
+ def validate(file_operation_instance)
112
+ return file_operation_instance if file_operation_instance.respond_to? :run
113
+
114
+ raise TypeError, 'File operations must implement a #run method'
115
+ end
109
116
  end
110
117
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'versions/validator'
3
4
  module FilePipeline
4
5
  # VersionedFile creates a directory where it stores any versions of _file_.
5
6
  class VersionedFile
@@ -81,14 +82,10 @@ module FilePipeline
81
82
  # <tt>version_info</tt> must be a path to an existing file or an array with
82
83
  # the path and optionally a FileOperations::Results instance:
83
84
  # <tt>['path/to/file', results_object]</tt>.
84
- # Will move the file to #directory if it is in another directory.
85
+ # Will raise MisplacedVersionFileError if it is in another directory.
85
86
  def <<(version_info)
86
- file, info = version_info
87
- if info&.failure
88
- raise Errors::FailedModificationError.new info: info, file: original
89
- end
90
-
91
- version = validate(file)
87
+ version, info = Versions::Validator[version_info, self]
88
+ version ||= @current
92
89
  @history[version] = info
93
90
  self
94
91
  rescue StandardError => e
@@ -146,7 +143,7 @@ module FilePipeline
146
143
  yield(self) if block_given?
147
144
  return original unless changed?
148
145
 
149
- filename = overwrite ? replacing_trarget : preserving_taget
146
+ filename = overwrite ? replacing_target : preserving_target
150
147
  FileUtils.rm original if overwrite
151
148
  @original = Versions.copy(current, original_dir, filename)
152
149
  ensure
@@ -167,10 +164,12 @@ module FilePipeline
167
164
  # than exif.
168
165
  #++
169
166
  def metadata(for_version: :current)
170
- if %i[current original].include? for_version
171
- file = public_send(for_version)
172
- end
173
- file ||= for_version
167
+ file = case for_version
168
+ when :current, :original
169
+ public_send for_version
170
+ else
171
+ for_version
172
+ end
174
173
  read_exif(file).first
175
174
  end
176
175
 
@@ -211,13 +210,13 @@ module FilePipeline
211
210
 
212
211
  # Returns the filename for a target file that will not overwrite the
213
212
  # original.
214
- def preserving_taget
215
- basename + '_' + target_suffix + current_extension
213
+ def preserving_target
214
+ "#{basename}_#{target_suffix}#{current_extension}"
216
215
  end
217
216
 
218
217
  # Returns the filename for a target file that will overwrite the
219
218
  # original.
220
- def replacing_trarget
219
+ def replacing_target
221
220
  basename + current_extension
222
221
  end
223
222
 
@@ -227,27 +226,13 @@ module FilePipeline
227
226
  history.clear!
228
227
  end
229
228
 
230
- # Validates if file exists and has been stored in #directory.
231
- def validate(file)
232
- return current unless file
233
-
234
- unless File.exist? file
235
- raise Errors::MissingVersionFileError.new file: file
236
- end
237
-
238
- return file if File.dirname(file) == directory
239
-
240
- Versions.move file, directory, File.basename(file)
241
- end
242
-
243
229
  # Creates the directory containing all version files. Directory name is
244
230
  # composed of the basename plus '_version'.
245
231
  #
246
232
  # Raises SystemCallError if the directory already exists.
247
233
  def workdir
248
- subdir = basename + '_versions'
249
234
  filedir = File.dirname(original)
250
- dirname = File.join filedir, subdir
235
+ dirname = File.join filedir, "#{basename}_versions"
251
236
  FileUtils.mkdir(dirname)
252
237
  File.path dirname
253
238
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FilePipeline
4
+ module Versions
5
+ # Validator objects verify the version file and results returned by a
6
+ # FileOperation.
7
+ #
8
+ # They will validate:
9
+ # - that the version file existst
10
+ # - that it is in the correct directory
11
+ # - that the file operation has not returned any failures
12
+ class Validator
13
+ extend Forwardable
14
+
15
+ # File for the version that resulted from a FileOperation.
16
+ attr_reader :file
17
+
18
+ # FileOperation::Results object.
19
+ attr_reader :info
20
+
21
+ # Returns a new instance.
22
+ #
23
+ # ===== Arguments
24
+ #
25
+ # * <tt>version_info</tt> - path to an existing file or an array with the
26
+ # path and optionally a FileOperations::Results instance.
27
+ # * +directory+ - directory where the file is expected (the working
28
+ # directory of a VersionedFile).
29
+ # * +filename+ - name of the file to be returned if the file operation was
30
+ # was non-modifying (usually the VersionedFile#original).
31
+ def initialize(version_info, directory, filename)
32
+ @file, @info = [version_info].flatten
33
+ @directory = directory
34
+ @filename = filename
35
+ end
36
+
37
+ # Validates file, directory, and info for <tt>version_info</tt> in the
38
+ # context of <tt>versioned_file</tt>.
39
+ #
40
+ # ===== Arguments
41
+ #
42
+ # * <tt>version_info</tt> - path to an existing file or an array with the
43
+ # path and optionally a FileOperations::Results instance.
44
+ # * <tt>versioned_file</tt> - an object that responds to #original and
45
+ # returns a file path, and #directory and returns a directory path.
46
+ def self.[](version_info, versioned_file)
47
+ new(version_info, versioned_file.directory, versioned_file.original)
48
+ .validate_info
49
+ .validate_file
50
+ .validate_directory
51
+ .then { |validator| [validator.file, validator.info] }
52
+ end
53
+
54
+ # Returns +true+ when there is no file for the version (result of a
55
+ # non-modifying file operation), +false+ otherwise.
56
+ def unmodified?
57
+ @file.nil?
58
+ end
59
+
60
+ # Raises MisplacedVersionFileError if #file is not in #directory.
61
+ def validate_directory
62
+ return self if unmodified? || File.dirname(@file) == @directory
63
+
64
+ raise Errors::MisplacedVersionFileError.new file: @file,
65
+ directory: @directory
66
+ end
67
+
68
+ # Raises MissingVersionFileError if #file does not exist on the file
69
+ # system.
70
+ def validate_file
71
+ return self if unmodified? || File.exist?(@file)
72
+
73
+ raise Errors::MissingVersionFileError.new file: @file
74
+ end
75
+
76
+ # Raises FailedModificationError if the file operation generatint the
77
+ # #info failed.
78
+ def validate_info
79
+ return self unless @info&.failure
80
+
81
+ raise Errors::FailedModificationError.new info: @info, file: @filename
82
+ end
83
+ end
84
+ end
85
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file_pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Stein
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-26 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_exiftool
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.14.0
19
+ version: 0.16.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.14.0
26
+ version: 0.16.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ruby-vips
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -50,6 +50,7 @@ files:
50
50
  - lib/file_pipeline.rb
51
51
  - lib/file_pipeline/errors.rb
52
52
  - lib/file_pipeline/errors/failed_modification_error.rb
53
+ - lib/file_pipeline/errors/misplaced_version_file_error.rb
53
54
  - lib/file_pipeline/errors/missing_version_file_error.rb
54
55
  - lib/file_pipeline/errors/source_directory_error.rb
55
56
  - lib/file_pipeline/errors/source_file_error.rb
@@ -68,11 +69,12 @@ files:
68
69
  - lib/file_pipeline/versioned_file.rb
69
70
  - lib/file_pipeline/versions.rb
70
71
  - lib/file_pipeline/versions/history.rb
72
+ - lib/file_pipeline/versions/validator.rb
71
73
  homepage: https://github.com/loveablelobster/file_pipeline
72
74
  licenses:
73
75
  - MIT
74
76
  metadata: {}
75
- post_install_message:
77
+ post_install_message:
76
78
  rdoc_options: []
77
79
  require_paths:
78
80
  - lib
@@ -80,15 +82,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
82
  requirements:
81
83
  - - ">="
82
84
  - !ruby/object:Gem::Version
83
- version: '2.7'
85
+ version: '3.0'
84
86
  required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  requirements:
86
88
  - - ">="
87
89
  - !ruby/object:Gem::Version
88
90
  version: '0'
89
91
  requirements: []
90
- rubygems_version: 3.1.2
91
- signing_key:
92
+ rubygems_version: 3.2.3
93
+ signing_key:
92
94
  specification_version: 4
93
95
  summary: Nondestructive file processing with a defined batch
94
96
  test_files: []