format_parser 0.21.1 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
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