format_parser 0.21.1 → 0.22.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 916f22d0efd27a6e32065b50c51a4a482664c344669aa1f9586769ccf2be7b06
4
- data.tar.gz: 3fd1b2ba7285ca69bb8d4c14c9f83e4001b55fee7e85332d97cbdbd36620597f
3
+ metadata.gz: 13d1f2a3748d62b027f80b1d6c46f8d087ddfc9cbeadeb62b330fa397797b847
4
+ data.tar.gz: eea08816482a939538aa1400ba6ca29af864f33ac12d960cbad8806d0e13a9c8
5
5
  SHA512:
6
- metadata.gz: df680824b240f15df52fbc6c14d44f9b5fb99a93fb69cf191db6027a9871115f5e3e5bbaec48751853683b01b8e87b4266b0bbfb23700901910f2ce0f8da1137
7
- data.tar.gz: d944a5db3fb2e1d06435b10bfc6aa0651312b45393180b08cf7a7f0b6237a0804b90a216cdeaf770e50de1af5bf31234f987e6fabc0e72bcb682e59a87cf2e7a
6
+ metadata.gz: d21c310453155285236e3469ad9980df4d408b00b989fa5a9ed330f39c0c4f5a65ebfb84a79d7f9d7c9761c9dbf27958b8b44a5e8176f79cbf340b011279a0c0
7
+ data.tar.gz: 0e8949ac9c1ac6624f27539fe33f52c28c7e5b9c2cce83d9c752372653e35c0231d9a087cff88c9ea87585eaa7dcd8d6878a1345b5b914554d4a5691f11dce60
data/.gitignore CHANGED
@@ -58,3 +58,6 @@ Gemfile.lock
58
58
 
59
59
  # OSX Files
60
60
  .DS_Store
61
+
62
+ # rspec examples
63
+ spec/examples.txt
@@ -1,3 +1,6 @@
1
+ ## 0.22.0
2
+ * Adds option `stringify_keys: true` to #as_json methods (fix #151)
3
+
1
4
  ## 0.21.1
2
5
  * MPEG: Ensure parsing does not inadvertently return an Integer instead of Result|nil
3
6
  * MPEG: Scan further into the MPEG file than previously (scan 32 1KB chunks)
data/README.md CHANGED
@@ -75,6 +75,17 @@ img_info = FormatParser.parse(File.open("myimage.jpg", "rb"))
75
75
  JSON.pretty_generate(img_info) #=> ...
76
76
  ```
77
77
 
78
+ To convert the result to a Hash or a structure suitable for JSON serialization
79
+
80
+ ```ruby
81
+ img_info = FormatParser.parse(File.open("myimage.jpg", "rb"))
82
+ img_info.as_json
83
+
84
+ # it's also possible to convert all keys to string
85
+ img_info.as_json(stringify_keys: true)
86
+ ```
87
+
88
+
78
89
  ## Creating your own parsers
79
90
 
80
91
  See the [section on writing parsers in CONTRIBUTING.md](CONTRIBUTING.md#so-you-want-to-contribute-a-new-parser)
@@ -188,7 +199,7 @@ Unless specified otherwise in this section the fixture files are MIT licensed an
188
199
 
189
200
  ## Copyright
190
201
 
191
- Copyright (c) 2019 WeTransfer.
202
+ Copyright (c) 2020 WeTransfer.
192
203
 
193
204
  `format_parser` is distributed under the conditions of the [Hippocratic License](https://firstdonoharm.dev/version/1/2/license.html)
194
205
  - See LICENSE.txt for further details.
@@ -39,7 +39,6 @@ Gem::Specification.new do |spec|
39
39
  spec.add_development_dependency 'rspec', '~> 3.0'
40
40
  spec.add_development_dependency 'rake', '~> 12'
41
41
  spec.add_development_dependency 'simplecov', '~> 0.15'
42
- spec.add_development_dependency 'pry', '~> 0.11'
43
42
  spec.add_development_dependency 'yard', '~> 0.9'
44
43
  spec.add_development_dependency 'wetransfer_style', '0.5.0'
45
44
  spec.add_development_dependency 'parallel_tests'
@@ -15,7 +15,12 @@ module FormatParser::AttributesJSON
15
15
 
16
16
  # Implements a sane default `as_json` for an object
17
17
  # that accessors defined
18
- def as_json(root: false)
18
+ #
19
+ # @param root[Bool] if true, it surrounds the result in a hash with a key
20
+ # `format_parser_file_info`
21
+ # @param stringify_keys[Bool] if true, it transforms all the hash keys to a string.
22
+ # The default value is false for backward compatibility
23
+ def as_json(root: false, stringify_keys: false, **)
19
24
  h = {}
20
25
  h['nature'] = nature if respond_to?(:nature) # Needed for file info structs
21
26
  methods.grep(/\w\=$/).each_with_object(h) do |attr_writer_method_name, h|
@@ -27,6 +32,9 @@ module FormatParser::AttributesJSON
27
32
  sanitized_value = _sanitize_json_value(unwrapped_attribute_value)
28
33
  h[reader_method_name] = sanitized_value
29
34
  end
35
+
36
+ h = FormatParser::HashUtils.deep_transform_keys(h, &:to_s) if stringify_keys
37
+
30
38
  if root
31
39
  {'format_parser_file_info' => h}
32
40
  else
@@ -5,6 +5,7 @@ require 'measurometer'
5
5
  # top-level methods of the library.
6
6
  module FormatParser
7
7
  require_relative 'format_parser/version'
8
+ require_relative 'hash_utils'
8
9
  require_relative 'attributes_json'
9
10
  require_relative 'image'
10
11
  require_relative 'audio'
@@ -1,3 +1,3 @@
1
1
  module FormatParser
2
- VERSION = '0.21.1'
2
+ VERSION = '0.22.0'
3
3
  end
@@ -0,0 +1,19 @@
1
+ # based on https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/keys.rb#L116
2
+ # I chose to copy this method instead of adding activesupport as a dependency
3
+ # because we want to have the least number of dependencies
4
+ module FormatParser
5
+ class HashUtils
6
+ def self.deep_transform_keys(object, &block)
7
+ case object
8
+ when Hash
9
+ object.each_with_object({}) do |(key, value), result|
10
+ result[yield(key)] = deep_transform_keys(value, &block)
11
+ end
12
+ when Array
13
+ object.map { |e| deep_transform_keys(e, &block) }
14
+ else
15
+ object
16
+ end
17
+ end
18
+ end
19
+ end
@@ -47,10 +47,6 @@ class FormatParser::MP3Parser
47
47
  h[k] = value if value
48
48
  end
49
49
  end
50
-
51
- def as_json(*)
52
- to_h
53
- end
54
50
  end
55
51
 
56
52
  def likely_match?(filename)
@@ -140,4 +140,30 @@ describe FormatParser::AttributesJSON do
140
140
  JSON.pretty_generate(object_with_attributes_module)
141
141
  }.to raise_error(/structure too deep/)
142
142
  end
143
+
144
+ it 'converts all hash keys to string when stringify_keys: true' do
145
+ fixture_path = fixtures_dir + '/ZIP/arch_few_entries.zip'
146
+ fi_io = File.open(fixture_path, 'rb')
147
+
148
+ result = FormatParser::ZIPParser.new.call(fi_io).as_json(stringify_keys: true)
149
+
150
+ result['entries'].each do |entry|
151
+ entry.each do |key, _value|
152
+ expect(key).to be_a(String)
153
+ end
154
+ end
155
+ end
156
+
157
+ it 'does not convert hash keys to string when stringify_keys: false' do
158
+ fixture_path = fixtures_dir + '/ZIP/arch_few_entries.zip'
159
+ fi_io = File.open(fixture_path, 'rb')
160
+
161
+ result = FormatParser::ZIPParser.new.call(fi_io).as_json
162
+
163
+ result['entries'].each do |entry|
164
+ entry.each do |key, _value|
165
+ expect(key).to be_a(Symbol)
166
+ end
167
+ end
168
+ end
143
169
  end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe FormatParser::HashUtils do
4
+ describe '.deep_transform_keys' do
5
+ it 'transforms all the keys in a hash' do
6
+ hash = { aa: 1, 'bb' => 2 }
7
+ result = described_class.deep_transform_keys(hash, &:to_s)
8
+
9
+ expect(result).to eq('aa' => 1, 'bb' => 2)
10
+ end
11
+
12
+ it 'transforms all the keys in a array of hashes' do
13
+ array = [{ aa: 1, bb: 2 }, { cc: 3, dd: [{c: 2, d: 3}] }]
14
+ result = described_class.deep_transform_keys(array, &:to_s)
15
+
16
+ expect(result).to eq(
17
+ [{'aa' => 1, 'bb' => 2}, {'cc' => 3, 'dd' => [{'c' => 2, 'd' => 3}]}]
18
+ )
19
+ end
20
+
21
+ it 'transforms all the keys in a hash recursively' do
22
+ hash = { aa: 1, bb: { cc: 22, dd: 3 } }
23
+ result = described_class.deep_transform_keys(hash, &:to_s)
24
+
25
+ expect(result).to eq('aa' => 1, 'bb' => { 'cc' => 22, 'dd' => 3})
26
+ end
27
+
28
+ it 'does nothing for an non array/hash object' do
29
+ object = Object.new
30
+ result = described_class.deep_transform_keys(object, &:to_s)
31
+
32
+ expect(result).to eq(object)
33
+ end
34
+
35
+ it 'returns the last value if different keys are transformed into the same one' do
36
+ hash = { aa: 0, 'bb' => 2, bb: 1 }
37
+ result = described_class.deep_transform_keys(hash, &:to_s)
38
+
39
+ expect(result).to eq('aa' => 0, 'bb' => 1)
40
+ end
41
+ end
42
+ end
@@ -110,4 +110,32 @@ describe FormatParser::MP3Parser do
110
110
  subject.call(StringIO.new(''))
111
111
  }.to raise_error(FormatParser::IOUtils::InvalidRead)
112
112
  end
113
+
114
+ describe '#as_json' do
115
+ it 'converts all hash keys to string when stringify_keys: true' do
116
+ fpath = fixtures_dir + '/MP3/Cassy.mp3'
117
+ result = subject.call(File.open(fpath, 'rb')).as_json(stringify_keys: true)
118
+
119
+ expect(
120
+ result['intrinsics'].keys.map(&:class).uniq
121
+ ).to eq([String])
122
+
123
+ expect(
124
+ result['intrinsics']['id3tags'].map(&:class).uniq
125
+ ).to eq([ID3Tag::Tag])
126
+ end
127
+
128
+ it 'does not convert the hash keys to string when stringify_keys: false' do
129
+ fpath = fixtures_dir + '/MP3/Cassy.mp3'
130
+ result = subject.call(File.open(fpath, 'rb')).as_json
131
+
132
+ expect(
133
+ result['intrinsics'].keys.map(&:class).uniq
134
+ ).to eq([Symbol])
135
+
136
+ expect(
137
+ result['intrinsics'][:id3tags].map(&:class).uniq
138
+ ).to eq([ID3Tag::Tag])
139
+ end
140
+ end
113
141
  end
@@ -8,7 +8,6 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
8
 
9
9
  require 'rspec'
10
10
  require 'format_parser'
11
- require 'pry'
12
11
 
13
12
  module SpecHelpers
14
13
  def fixtures_dir
@@ -19,6 +18,8 @@ end
19
18
  RSpec.configure do |c|
20
19
  c.include SpecHelpers
21
20
  c.extend SpecHelpers # makes fixtures_dir available for example groups too
21
+ # https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
22
+ c.example_status_persistence_file_path = 'spec/examples.txt'
22
23
  end
23
24
 
24
25
  RSpec.shared_examples 'an IO object compatible with IOConstraint' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: format_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.1
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noah Berman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-04-20 00:00:00.000000000 Z
12
+ date: 2020-07-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ks
@@ -135,20 +135,6 @@ dependencies:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0.15'
138
- - !ruby/object:Gem::Dependency
139
- name: pry
140
- requirement: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '0.11'
145
- type: :development
146
- prerelease: false
147
- version_requirements: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - "~>"
150
- - !ruby/object:Gem::Version
151
- version: '0.11'
152
138
  - !ruby/object:Gem::Dependency
153
139
  name: yard
154
140
  requirement: !ruby/object:Gem::Requirement
@@ -223,6 +209,7 @@ files:
223
209
  - lib/document.rb
224
210
  - lib/format_parser.rb
225
211
  - lib/format_parser/version.rb
212
+ - lib/hash_utils.rb
226
213
  - lib/image.rb
227
214
  - lib/io_constraint.rb
228
215
  - lib/io_utils.rb
@@ -260,6 +247,7 @@ files:
260
247
  - spec/file_information_spec.rb
261
248
  - spec/format_parser_inspect_spec.rb
262
249
  - spec/format_parser_spec.rb
250
+ - spec/hash_utils_spec.rb
263
251
  - spec/io_utils_spec.rb
264
252
  - spec/parsers/aiff_parser_spec.rb
265
253
  - spec/parsers/bmp_parser_spec.rb
@@ -305,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
305
293
  - !ruby/object:Gem::Version
306
294
  version: '0'
307
295
  requirements: []
308
- rubygems_version: 3.0.3
296
+ rubygems_version: 3.1.4
309
297
  signing_key:
310
298
  specification_version: 4
311
299
  summary: A library for efficient parsing of file metadata