mime-types 2.99.3 → 3.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.autotest +35 -0
  3. data/.gemtest +0 -0
  4. data/.gitignore +17 -0
  5. data/.hoerc +20 -0
  6. data/Code-of-Conduct.rdoc +27 -60
  7. data/Contributing.rdoc +0 -1
  8. data/History.rdoc +75 -36
  9. data/Licence.rdoc +2 -16
  10. data/Manifest.txt +10 -18
  11. data/README.rdoc +46 -46
  12. data/Rakefile +112 -58
  13. data/lib/mime-types.rb +0 -2
  14. data/lib/mime/type.rb +183 -415
  15. data/lib/mime/type/columnar.rb +27 -62
  16. data/lib/mime/types.rb +37 -135
  17. data/lib/mime/types/cache.rb +49 -73
  18. data/lib/mime/types/columnar.rb +42 -48
  19. data/lib/mime/types/container.rb +30 -0
  20. data/lib/mime/types/deprecations.rb +1 -22
  21. data/lib/mime/types/full.rb +17 -0
  22. data/lib/mime/types/loader.rb +10 -137
  23. data/lib/mime/types/logger.rb +2 -0
  24. data/lib/mime/types/registry.rb +81 -0
  25. data/support/benchmarks/load.rb +27 -26
  26. data/support/benchmarks/load_allocations.rb +14 -7
  27. data/support/benchmarks/object_counts.rb +6 -4
  28. data/support/profile/columnar.rb +5 -0
  29. data/support/profile/columnar_full.rb +5 -0
  30. data/support/profile/full.rb +5 -0
  31. data/test/minitest_helper.rb +3 -12
  32. data/test/test_mime_type.rb +461 -454
  33. data/test/test_mime_types.rb +126 -86
  34. data/test/test_mime_types_cache.rb +55 -45
  35. data/test/test_mime_types_class.rb +113 -97
  36. data/test/test_mime_types_lazy.rb +19 -23
  37. data/test/test_mime_types_loader.rb +5 -32
  38. metadata +67 -44
  39. data/History-Types.rdoc +0 -454
  40. data/data/mime-types.json +0 -1
  41. data/data/mime.content_type.column +0 -1980
  42. data/data/mime.docs.column +0 -1980
  43. data/data/mime.encoding.column +0 -1980
  44. data/data/mime.friendly.column +0 -1980
  45. data/data/mime.obsolete.column +0 -1980
  46. data/data/mime.registered.column +0 -1980
  47. data/data/mime.signature.column +0 -1980
  48. data/data/mime.use_instead.column +0 -1980
  49. data/data/mime.xrefs.column +0 -1980
  50. data/docs/COPYING.txt +0 -339
  51. data/docs/artistic.txt +0 -127
  52. data/lib/mime/types/loader_path.rb +0 -15
  53. data/support/apache_mime_types.rb +0 -108
  54. data/support/convert.rb +0 -158
  55. data/support/convert/columnar.rb +0 -88
  56. data/support/iana_registry.rb +0 -172
@@ -18,7 +18,7 @@ module MIME::Types::Columnar
18
18
  def self.extended(obj) # :nodoc:
19
19
  super
20
20
  obj.instance_variable_set(:@__mime_data__, [])
21
- obj.instance_variable_set(:@__attributes__, [])
21
+ obj.instance_variable_set(:@__files__, Set.new)
22
22
  end
23
23
 
24
24
  # Load the first column data file (type and extensions).
@@ -26,7 +26,10 @@ module MIME::Types::Columnar
26
26
  @__root__ = path
27
27
 
28
28
  each_file_line('content_type', false) do |line|
29
- content_type, *extensions = line.split
29
+ line = line.split
30
+ content_type = line.shift
31
+ extensions = line
32
+ # content_type, *extensions = line.split
30
33
 
31
34
  type = MIME::Type::Columnar.new(self, content_type, extensions)
32
35
  @__mime_data__ << type
@@ -40,84 +43,81 @@ module MIME::Types::Columnar
40
43
 
41
44
  def each_file_line(name, lookup = true)
42
45
  LOAD_MUTEX.synchronize do
43
- next if @__attributes__.include?(name)
46
+ next if @__files__.include?(name)
44
47
 
45
- File.open(File.join(@__root__, "mime.#{name}.column"), 'r:UTF-8') do |f|
46
- i = -1
48
+ i = -1
49
+ column = File.join(@__root__, "mime.#{name}.column")
47
50
 
48
- f.each_line do |line|
49
- line.chomp!
51
+ IO.readlines(column, encoding: 'UTF-8'.freeze).each do |line|
52
+ line.chomp!
50
53
 
51
- if lookup
52
- type = @__mime_data__[i += 1] or next
53
- yield type, line
54
- else
55
- yield line
56
- end
54
+ if lookup
55
+ type = @__mime_data__[i += 1] or next
56
+ yield type, line
57
+ else
58
+ yield line
57
59
  end
58
60
  end
59
61
 
60
- @__attributes__ << name
62
+ @__files__ << name
61
63
  end
62
64
  end
63
65
 
64
66
  def load_encoding
65
- pool = {}
66
67
  each_file_line('encoding') do |type, line|
68
+ pool ||= {}
67
69
  line.freeze
68
- type.encoding = (pool[line] ||= line)
70
+ type.instance_variable_set(:@encoding, (pool[line] ||= line))
69
71
  end
70
72
  end
71
73
 
72
74
  def load_docs
73
75
  each_file_line('docs') do |type, line|
74
- type.docs = arr(line)
76
+ type.instance_variable_set(:@docs, opt(line))
75
77
  end
76
78
  end
77
79
 
78
- def load_obsolete
79
- each_file_line('obsolete') do |type, line|
80
- type.obsolete = bool(line)
80
+ def load_preferred_extension
81
+ each_file_line('pext') do |type, line|
82
+ type.instance_variable_set(:@preferred_extension, opt(line))
81
83
  end
82
84
  end
83
85
 
84
- def load_registered
85
- each_file_line('registered') do |type, line|
86
- type.registered = bool(line)
87
- end
88
- end
89
-
90
- def load_signature
91
- each_file_line('signature') do |type, line|
92
- type.signature = bool(line)
86
+ def load_flags
87
+ each_file_line('flags') do |type, line|
88
+ line = line.split
89
+ type.instance_variable_set(:@obsolete, flag(line.shift))
90
+ type.instance_variable_set(:@registered, flag(line.shift))
91
+ type.instance_variable_set(:@signature, flag(line.shift))
93
92
  end
94
93
  end
95
94
 
96
95
  def load_xrefs
97
- each_file_line('xrefs') { |type, line| type.xrefs = dict(line) }
96
+ each_file_line('xrefs') { |type, line|
97
+ type.instance_variable_set(:@xrefs, dict(line, array: true))
98
+ }
98
99
  end
99
100
 
100
101
  def load_friendly
101
102
  each_file_line('friendly') { |type, line|
102
- v = dict(line)
103
- type.friendly = v.empty? ? nil : v
103
+ type.instance_variable_set(:@friendly, dict(line))
104
104
  }
105
105
  end
106
106
 
107
107
  def load_use_instead
108
108
  each_file_line('use_instead') do |type, line|
109
- type.use_instead = (line unless line == '-'.freeze)
109
+ type.instance_variable_set(:@use_instead, opt(line))
110
110
  end
111
111
  end
112
112
 
113
- def dict(line)
113
+ def dict(line, array: false)
114
114
  if line == '-'.freeze
115
115
  {}
116
116
  else
117
117
  line.split('|'.freeze).each_with_object({}) { |l, h|
118
118
  k, v = l.split('^'.freeze)
119
- v = [ nil ] if v.empty?
120
- h[k] = v
119
+ v = nil if v.empty?
120
+ h[k] = array ? Array(v) : v
121
121
  }
122
122
  end
123
123
  end
@@ -130,19 +130,13 @@ module MIME::Types::Columnar
130
130
  end
131
131
  end
132
132
 
133
- def bool(line)
134
- line == '1'.freeze ? true : false
133
+ def opt(line)
134
+ line unless line == '-'.freeze
135
135
  end
136
- end
137
136
 
138
- unless MIME::Types.private_method_defined?(:load_mode)
139
- class << MIME::Types
140
- private
141
-
142
- def load_mode
143
- { columnar: true }
144
- end
137
+ def flag(line)
138
+ line == '1'.freeze ? true : false
145
139
  end
146
-
147
- require 'mime/types'
148
140
  end
141
+
142
+ require 'mime/types' unless defined?(MIME::Types::VERSION)
@@ -0,0 +1,30 @@
1
+ require 'set'
2
+
3
+ # MIME::Types requires a container Hash with a default values for keys
4
+ # resulting in an empty array (<tt>[]</tt>), but this cannot be dumped through
5
+ # Marshal because of the presence of that default Proc. This class exists
6
+ # solely to satisfy that need.
7
+ class MIME::Types::Container < Hash # :nodoc:
8
+ def initialize
9
+ super
10
+ self.default_proc = ->(h, k) { h[k] = Set.new }
11
+ end
12
+
13
+ def marshal_dump
14
+ {}.merge(self)
15
+ end
16
+
17
+ def marshal_load(hash)
18
+ self.default_proc = ->(h, k) { h[k] = Set.new }
19
+ merge!(hash)
20
+ end
21
+
22
+ def encode_with(coder)
23
+ each { |k, v| coder[k] = v.to_a }
24
+ end
25
+
26
+ def init_with(coder)
27
+ self.default_proc = ->(h, k) { h[k] = Set.new }
28
+ coder.map.each { |k, v| self[k] = Set[*v] }
29
+ end
30
+ end
@@ -4,6 +4,7 @@ require 'mime/types/logger'
4
4
 
5
5
  # The namespace for MIME applications, tools, and libraries.
6
6
  module MIME
7
+ ##
7
8
  class Types
8
9
  # Used to mark a method as deprecated in the mime-types interface.
9
10
  def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
@@ -28,26 +29,4 @@ module MIME
28
29
  block.call if block
29
30
  end
30
31
  end
31
-
32
- class << self
33
- # MIME::InvalidContentType was moved to MIME::Type::InvalidContentType.
34
- # Provide a single warning about this fact in the interim.
35
- def const_missing(name) # :nodoc:
36
- case name.to_s
37
- when 'InvalidContentType'
38
- warn_about_moved_constants(name)
39
- MIME::Type.const_get(name.to_sym)
40
- else
41
- super
42
- end
43
- end
44
-
45
- private
46
-
47
- def warn_about_moved_constants(name)
48
- MIME::Types.logger.warn <<-warning.chomp
49
- #{caller[1]}: MIME::#{name} is deprecated. Use MIME::Type::#{name} instead.
50
- warning
51
- end
52
- end
53
32
  end
@@ -0,0 +1,17 @@
1
+ ##
2
+ module MIME
3
+ ##
4
+ class Types
5
+ unless private_method_defined?(:load_mode)
6
+ class << self
7
+ private
8
+
9
+ def load_mode
10
+ { columnar: false }
11
+ end
12
+ end
13
+
14
+ require 'mime/types'
15
+ end
16
+ end
17
+ end
@@ -1,9 +1,11 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
2
 
3
+ ##
3
4
  module MIME; end
5
+ ##
4
6
  class MIME::Types; end
5
7
 
6
- require 'mime/types/loader_path'
8
+ require 'mime/types/data'
7
9
 
8
10
  # This class is responsible for initializing the MIME::Types registry from
9
11
  # the data files supplied with the mime-types library.
@@ -11,7 +13,7 @@ require 'mime/types/loader_path'
11
13
  # The Loader will use one of the following paths:
12
14
  # 1. The +path+ provided in its constructor argument;
13
15
  # 2. The value of ENV['RUBY_MIME_TYPES_DATA']; or
14
- # 3. The value of MIME::Types::Loader::PATH.
16
+ # 3. The value of MIME::Types::Data::PATH.
15
17
  #
16
18
  # When #load is called, the +path+ will be searched recursively for all YAML
17
19
  # (.yml or .yaml) files. By convention, there is one file for each media
@@ -24,9 +26,9 @@ class MIME::Types::Loader
24
26
  attr_reader :container
25
27
 
26
28
  # Creates a Loader object that can be used to load MIME::Types registries
27
- # into memory, using YAML, JSON, or v1 registry format loaders.
29
+ # into memory, using YAML, JSON, or Columnar registry format loaders.
28
30
  def initialize(path = nil, container = nil)
29
- path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Loader::PATH
31
+ path = path || ENV['RUBY_MIME_TYPES_DATA'] || MIME::Types::Data::PATH
30
32
  @container = container || MIME::Types.new
31
33
  @path = File.expand_path(path)
32
34
  # begin
@@ -41,8 +43,7 @@ class MIME::Types::Loader
41
43
  # It is expected that the YAML objects contained within the registry array
42
44
  # will be tagged as <tt>!ruby/object:MIME::Type</tt>.
43
45
  #
44
- # Note that the YAML format is about 2½ times *slower* than either the v1
45
- # format or the JSON format.
46
+ # Note that the YAML format is about 2½ times *slower* than the JSON format.
46
47
  #
47
48
  # NOTE: The purpose of this format is purely for maintenance reasons.
48
49
  def load_yaml
@@ -89,122 +90,19 @@ class MIME::Types::Loader
89
90
  end
90
91
  end
91
92
 
92
- # Loads a MIME::Types registry from files found in +path+ that are in the
93
- # v1 data format. The file search for this will exclude both JSON
94
- # (<tt>*.json</tt>) and YAML (<tt>*.yml</tt> or <tt>*.yaml</tt>) files.
95
- #
96
- # This method has been deprecated and will be removed from mime-types 3.0.
97
- def load_v1
98
- MIME::Types.deprecated(self.class, __method__)
99
- Dir[v1_path].sort.each do |f|
100
- next if f =~ /\.(?:ya?ml|json|column)$/
101
- container.add(self.class.load_from_v1(f, true), true)
102
- end
103
- container
104
- end
105
-
106
- # Raised when a V1 format file is discovered. This exception will be removed
107
- # for mime-types 3.0.
108
- BadV1Format = Class.new(Exception)
109
-
110
93
  class << self
111
94
  # Loads the default MIME::Type registry.
112
95
  def load(options = { columnar: false })
113
96
  new.load(options)
114
97
  end
115
98
 
116
- # Build the type list from a file in the format:
117
- #
118
- # [*][!][os:]mt/st[<ws>@ext][<ws>:enc][<ws>'url-list][<ws>=docs]
119
- #
120
- # == *
121
- # An unofficial MIME type. This should be used if and only if the MIME type
122
- # is not properly specified (that is, not under either x-type or
123
- # vnd.name.type).
124
- #
125
- # == !
126
- # An obsolete MIME type. May be used with an unofficial MIME type.
127
- #
128
- # == os:
129
- # Platform-specific MIME type definition.
130
- #
131
- # == mt
132
- # The media type.
133
- #
134
- # == st
135
- # The media subtype.
136
- #
137
- # == <ws>@ext
138
- # The list of comma-separated extensions.
139
- #
140
- # == <ws>:enc
141
- # The encoding.
142
- #
143
- # == <ws>'url-list
144
- # The list of comma-separated URLs.
145
- #
146
- # == <ws>=docs
147
- # The documentation string.
148
- #
149
- # That is, everything except the media type and the subtype is optional. The
150
- # more information that's available, though, the richer the values that can
151
- # be provided.
152
- #
153
- # This method has been deprecated and will be removed in mime-types 3.0.
154
- def load_from_v1(filename, __internal__ = false)
155
- MIME::Types.deprecated(self.class, __method__) unless __internal__
156
- data = read_file(filename).split($/)
157
- mime = MIME::Types.new
158
- data.each_with_index { |line, index|
159
- item = line.chomp.strip
160
- next if item.empty?
161
-
162
- m = V1_FORMAT.match(item)
163
-
164
- unless m
165
- MIME::Types.logger.warn <<-EOS
166
- #{filename}:#{index + 1}: Parsing error in v1 MIME type definition.
167
- => #{line}
168
- EOS
169
- fail BadV1Format, line
170
- end
171
-
172
- unregistered, obsolete, _, mediatype, subtype, extensions, encoding,
173
- urls, docs, _ = *m.captures
174
-
175
- next if mediatype.nil?
176
-
177
- extensions &&= extensions.split(/,/)
178
- urls &&= urls.split(/,/)
179
-
180
- if docs.nil?
181
- use_instead = nil
182
- else
183
- use_instead = docs.scan(%r{use-instead:(\S+)}).flatten.first
184
- docs = docs.gsub(%r{use-instead:\S+}, '').squeeze(' \t')
185
- end
186
-
187
- mime_type = MIME::Type.new("#{mediatype}/#{subtype}") do |t|
188
- t.extensions = extensions
189
- t.encoding = encoding
190
- t.obsolete = obsolete
191
- t.registered = false if unregistered
192
- t.use_instead = use_instead
193
- t.docs = docs
194
- end
195
-
196
- mime.add_type(mime_type, true)
197
- }
198
- mime
199
- end
200
-
201
99
  # Loads MIME::Types from a single YAML file.
202
100
  #
203
101
  # It is expected that the YAML objects contained within the registry
204
102
  # array will be tagged as <tt>!ruby/object:MIME::Type</tt>.
205
103
  #
206
- # Note that the YAML format is about 2½ times *slower* than either the v1
207
- # format or the JSON format.
104
+ # Note that the YAML format is about 2½ times *slower* than the JSON
105
+ # format.
208
106
  #
209
107
  # NOTE: The purpose of this format is purely for maintenance reasons.
210
108
  def load_from_yaml(filename)
@@ -230,7 +128,7 @@ class MIME::Types::Loader
230
128
  private
231
129
 
232
130
  def read_file(filename)
233
- File.open(filename, 'r:UTF-8:-') { |f| f.read }
131
+ File.open(filename, 'r:UTF-8:-', &:read)
234
132
  end
235
133
  end
236
134
 
@@ -247,29 +145,4 @@ class MIME::Types::Loader
247
145
  def columnar_path
248
146
  File.join(path, '*.column')
249
147
  end
250
-
251
- def v1_path
252
- File.join(path, '*')
253
- end
254
-
255
- # The regular expression used to match a v1-format file-based MIME type
256
- # definition.
257
- #
258
- # This constant has been deprecated and will be removed in mime-types 3.0.
259
- V1_FORMAT = # :nodoc:
260
- %r{\A\s*
261
- ([*])? # 0: Unregistered?
262
- (!)? # 1: Obsolete?
263
- (?:(\w+):)? # 2: Platform marker
264
- ([-\w.+]+)/([-\w.+]*) # 3, 4: Media Type
265
- (?:\s+@(\S+))? # 5: Extensions
266
- (?:\s+:(base64|7bit|8bit|quoted\-printable))? # 6: Encoding
267
- (?:\s+'(\S+))? # 7: URL list
268
- (?:\s+=(.+))? # 8: Documentation
269
- (?:\s*([#].*)?)? # Comments
270
- \s*
271
- \z
272
- }x
273
-
274
- private_constant :V1_FORMAT if respond_to? :private_constant
275
148
  end