mime-types 2.5 → 2.6

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Contributing.rdoc +72 -20
  4. data/History-Types.rdoc +11 -0
  5. data/History.rdoc +31 -1
  6. data/Manifest.txt +18 -1
  7. data/README.rdoc +142 -61
  8. data/Rakefile +59 -91
  9. data/data/mime-types.json +1 -1
  10. data/data/mime.content_type.column +1907 -0
  11. data/data/mime.docs.column +1907 -0
  12. data/data/mime.encoding.column +1907 -0
  13. data/data/mime.friendly.column +1907 -0
  14. data/data/mime.obsolete.column +1907 -0
  15. data/data/mime.references.column +1907 -0
  16. data/data/mime.registered.column +1907 -0
  17. data/data/mime.signature.column +1907 -0
  18. data/data/mime.system.column +1907 -0
  19. data/data/mime.use_instead.column +1907 -0
  20. data/data/mime.xrefs.column +1907 -0
  21. data/lib/mime/type.rb +192 -119
  22. data/lib/mime/type/columnar.rb +112 -0
  23. data/lib/mime/types.rb +39 -25
  24. data/lib/mime/types/cache.rb +41 -35
  25. data/lib/mime/types/columnar.rb +160 -0
  26. data/lib/mime/types/deprecations.rb +53 -0
  27. data/lib/mime/types/loader.rb +60 -20
  28. data/lib/mime/types/loader_path.rb +2 -3
  29. data/lib/mime/types/logger.rb +35 -0
  30. data/support/apache_mime_types.rb +8 -1
  31. data/support/benchmarks/load.rb +17 -8
  32. data/support/benchmarks/load_allocations.rb +83 -0
  33. data/support/benchmarks/object_counts.rb +41 -0
  34. data/support/convert.rb +44 -24
  35. data/support/convert/columnar.rb +90 -0
  36. data/support/iana_registry.rb +18 -8
  37. data/test/fixture/json.json +1 -1
  38. data/test/fixture/yaml.yaml +3 -6
  39. data/test/minitest_helper.rb +9 -10
  40. data/test/test_mime_type.rb +126 -62
  41. data/test/test_mime_types.rb +15 -11
  42. data/test/test_mime_types_class.rb +16 -14
  43. data/test/test_mime_types_lazy.rb +7 -1
  44. data/test/test_mime_types_loader.rb +17 -8
  45. metadata +54 -12
  46. data/lib/mime.rb +0 -51
@@ -0,0 +1,112 @@
1
+ require 'mime/type'
2
+
3
+ # A version of MIME::Type that works hand-in-hand with a MIME::Types::Columnar
4
+ # container to load data by columns.
5
+ #
6
+ # When a field is has not yet been loaded, that data will be loaded for all
7
+ # types in the container before forwarding the message to MIME::Type.
8
+ #
9
+ # More information can be found in MIME::Types::Columnar.
10
+ #
11
+ # MIME::Type::Columnar is *not* intended to be created except by
12
+ # MIME::Types::Columnar containers.
13
+ class MIME::Type::Columnar < MIME::Type
14
+ attr_writer :friendly # :nodoc:
15
+
16
+ def initialize(container, content_type, extensions) # :nodoc:
17
+ @container = container
18
+ self.content_type = content_type
19
+ self.extensions = extensions
20
+ end
21
+
22
+ def friendly(*) # :nodoc:
23
+ @container.send(:load_friendly) unless defined?(@friendly)
24
+ super if @friendly
25
+ end
26
+
27
+ def encoding # :nodoc:
28
+ @container.send(:load_encoding) unless defined?(@encoding)
29
+ @encoding
30
+ end
31
+
32
+ def docs # :nodoc:
33
+ @container.send(:load_docs) unless defined?(@docs)
34
+ @docs
35
+ end
36
+
37
+ def obsolete? # :nodoc:
38
+ @container.send(:load_obsolete) unless defined?(@obsolete)
39
+ super
40
+ end
41
+
42
+ def references(*) # :nodoc:
43
+ @container.send(:load_references) unless defined?(@references)
44
+ super if @references
45
+ end
46
+
47
+ def registered? # :nodoc:
48
+ @container.send(:load_registered) unless defined?(@registered)
49
+ super
50
+ end
51
+
52
+ def signature? # :nodoc:
53
+ @container.send(:load_signature) unless defined?(@signature)
54
+ super
55
+ end
56
+
57
+ def system?(*) # :nodoc:
58
+ @container.send(:load_system) unless defined?(@system)
59
+ super
60
+ end
61
+
62
+ def system # :nodoc:
63
+ @container.send(:load_system) unless defined?(@system)
64
+ @system
65
+ end
66
+
67
+ def xrefs # :nodoc:
68
+ @container.send(:load_xrefs) unless defined?(@xrefs)
69
+ @xrefs
70
+ end
71
+
72
+ def use_instead # :nodoc:
73
+ @container.send(:load_use_instead) unless defined?(@use_instead)
74
+ @use_instead
75
+ end
76
+
77
+ def binary? # :nodoc:
78
+ @container.send(:load_encoding) unless defined?(@encoding)
79
+ super
80
+ end
81
+
82
+ def to_a # :nodoc:
83
+ @container.send(:load_encoding) unless defined?(@encoding)
84
+ @container.send(:load_system) unless defined?(@system)
85
+ @container.send(:load_docs) unless defined?(@docs)
86
+ @container.send(:load_references) unless defined?(@references)
87
+ super
88
+ end
89
+
90
+ def to_hash # :nodoc:
91
+ @container.send(:load_encoding) unless defined?(@encoding)
92
+ @container.send(:load_system) unless defined?(@system)
93
+ @container.send(:load_docs) unless defined?(@docs)
94
+ @container.send(:load_references) unless defined?(@references)
95
+ super
96
+ end
97
+
98
+ def encode_with(coder) # :nodoc:
99
+ @container.send(:load_friendly) unless defined?(@friendly)
100
+ @container.send(:load_encoding) unless defined?(@encoding)
101
+ @container.send(:load_system) unless defined?(@system)
102
+ @container.send(:load_docs) unless defined?(@docs)
103
+ @container.send(:load_references) unless defined?(@references)
104
+ @container.send(:load_obsolete) unless defined?(@obsolete)
105
+ @container.send(:load_use_instead) unless defined?(@use_instead)
106
+ @container.send(:load_xrefs) unless defined?(@xrefs)
107
+ @container.send(:load_system) unless defined?(@system)
108
+ @container.send(:load_registered) unless defined?(@registered)
109
+ @container.send(:load_signature) unless defined?(@signature)
110
+ super
111
+ end
112
+ end
@@ -1,5 +1,6 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
2
 
3
+ require 'mime/types/deprecations'
3
4
  require 'mime/type'
4
5
  require 'mime/types/cache'
5
6
  require 'mime/types/loader'
@@ -75,18 +76,21 @@ class MIME::Types
75
76
  @data_version = VERSION.dup.freeze
76
77
  end
77
78
 
79
+ # This method is deprecated and will be removed in mime-types 3.0.
78
80
  def add_type_variant(mime_type) # :nodoc:
79
- MIME.deprecated(self, __method__, :private)
81
+ MIME::Types.deprecated(self, __method__, :private)
80
82
  add_type_variant!(mime_type)
81
83
  end
82
84
 
85
+ # This method is deprecated and will be removed in mime-types 3.0.
83
86
  def index_extensions(mime_type) # :nodoc:
84
- MIME.deprecated(self, __method__, :private)
87
+ MIME::Types.deprecated(self, __method__, :private)
85
88
  index_extensions!(mime_type)
86
89
  end
87
90
 
91
+ # This method is deprecated and will be removed in mime-types 3.0.
88
92
  def defined_types # :nodoc:
89
- MIME.deprecated(self, __method__)
93
+ MIME::Types.deprecated(self, __method__)
90
94
  @type_variants.values.flatten
91
95
  end
92
96
 
@@ -137,7 +141,7 @@ class MIME::Types
137
141
  # platform) is currently supported but deprecated.
138
142
  def [](type_id, flags = {})
139
143
  if flags[:platform]
140
- MIME.deprecated(self, __method__, "using the :platform flag")
144
+ MIME::Types.deprecated(self, __method__, 'using the :platform flag')
141
145
  end
142
146
 
143
147
  matches = case type_id
@@ -173,8 +177,7 @@ class MIME::Types
173
177
  }.compact.sort { |a, b| a.priority_compare(b) }.uniq
174
178
 
175
179
  if platform
176
- MIME.deprecated(self, __method__,
177
- "using the platform parameter")
180
+ MIME::Types.deprecated(self, __method__, 'using the platform parameter')
178
181
  types.select(&:platform?)
179
182
  else
180
183
  types
@@ -205,17 +208,18 @@ class MIME::Types
205
208
  end
206
209
  end
207
210
 
208
- # Add a single MIME::Type object to the set of known types. If the type is
209
- # already known, a warning will be displayed. The +quiet+ parameter may be
210
- # a truthy value to suppress that warning.
211
- def add_type(mime_type, quiet = false)
212
- if !quiet and @type_variants[mime_type.simplified].include?(mime_type)
213
- warn('Type %s is already registered as a variant of %s.' %
214
- [ mime_type, mime_type.simplified ])
211
+ # Add a single MIME::Type object to the set of known types. If the +type+ is
212
+ # already known, a warning will be displayed. The +quiet+ parameter may be a
213
+ # truthy value to suppress that warning.
214
+ def add_type(type, quiet = false)
215
+ if !quiet and @type_variants[type.simplified].include?(type)
216
+ MIME::Types.logger.warn <<-warning
217
+ Type #{type} is already registered as a variant of #{type.simplified}.
218
+ warning
215
219
  end
216
220
 
217
- add_type_variant!(mime_type)
218
- index_extensions!(mime_type)
221
+ add_type_variant!(type)
222
+ index_extensions!(type)
219
223
  end
220
224
 
221
225
  class << self
@@ -223,9 +227,9 @@ class MIME::Types
223
227
 
224
228
  # Load MIME::Types from a v1 file registry.
225
229
  #
226
- # This method has been deprecated.
230
+ # This method has been deprecated and will be removed in mime-types 3.0.
227
231
  def load_from_file(filename)
228
- MIME.deprecated(self, __method__)
232
+ MIME::Types.deprecated(self, __method__)
229
233
  MIME::Types::Loader.load_from_v1(filename)
230
234
  end
231
235
 
@@ -260,8 +264,10 @@ class MIME::Types
260
264
  end
261
265
 
262
266
  # Returns the currently defined cache file, if any.
267
+ #
268
+ # This method has been deprecated and will be removed in mime-types 3.0.
263
269
  def cache_file
264
- MIME.deprecated(self, __method__)
270
+ MIME::Types.deprecated(self, __method__)
265
271
  ENV['RUBY_MIME_TYPES_CACHE']
266
272
  end
267
273
 
@@ -274,6 +280,7 @@ class MIME::Types
274
280
  end
275
281
 
276
282
  private
283
+
277
284
  def lazy_load?
278
285
  (lazy = ENV['RUBY_MIME_TYPES_LAZY_LOAD']) && (lazy != 'false')
279
286
  end
@@ -282,10 +289,16 @@ class MIME::Types
282
289
  (defined?(@__types__) and @__types__) or load_default_mime_types
283
290
  end
284
291
 
285
- def load_default_mime_types
292
+ unless private_method_defined?(:load_mode)
293
+ def load_mode
294
+ {}
295
+ end
296
+ end
297
+
298
+ def load_default_mime_types(mode = load_mode())
286
299
  @__types__ = MIME::Types::Cache.load
287
300
  unless @__types__
288
- @__types__ = MIME::Types::Loader.load
301
+ @__types__ = MIME::Types::Loader.load(mode)
289
302
  MIME::Types::Cache.save(@__types__)
290
303
  end
291
304
  @__types__
@@ -293,6 +306,7 @@ class MIME::Types
293
306
  end
294
307
 
295
308
  private
309
+
296
310
  def add_type_variant!(mime_type)
297
311
  @type_variants[mime_type.simplified] << mime_type
298
312
  end
@@ -302,17 +316,17 @@ class MIME::Types
302
316
  end
303
317
 
304
318
  def prune_matches(matches, flags)
305
- matches.delete_if { |e| not e.complete? } if flags[:complete]
306
- matches.delete_if { |e| not e.platform? } if flags[:platform]
307
- matches.delete_if { |e| not e.registered? } if flags[:registered]
319
+ matches.delete_if { |e| !e.complete? } if flags[:complete]
320
+ matches.delete_if { |e| !e.platform? } if flags[:platform]
321
+ matches.delete_if { |e| !e.registered? } if flags[:registered]
308
322
  matches
309
323
  end
310
324
 
311
325
  def match(pattern)
312
- @type_variants.select { |k, v| k =~ pattern }.values.flatten
326
+ @type_variants.select { |k, _| k =~ pattern }.values.flatten
313
327
  end
314
328
 
315
- load_default_mime_types unless lazy_load?
329
+ load_default_mime_types(load_mode) unless lazy_load?
316
330
  end
317
331
 
318
332
  # vim: ft=ruby
@@ -1,6 +1,8 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
2
 
3
3
  class MIME::Types
4
+ Cache = Struct.new(:version, :data) # :nodoc:
5
+
4
6
  # Caching of MIME::Types registries is advisable if you will be loading
5
7
  # the default registry relatively frequently. With the class methods on
6
8
  # MIME::Types::Cache, any MIME::Types registry can be marshaled quickly
@@ -8,46 +10,50 @@ class MIME::Types
8
10
  #
9
11
  # The cache is invalidated on a per-version basis; a cache file for
10
12
  # version 2.0 will not be reused with version 2.0.1.
11
- Cache = Struct.new(:version, :data)
12
-
13
- class << Cache
14
- # Attempts to load the cache from the file provided as a parameter or in
15
- # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the
16
- # file does not exist, if the file cannot be loaded, or if the data in
17
- # the cache version is different than this version.
18
- def load(cache_file = nil)
19
- cache_file = cache_file || ENV['RUBY_MIME_TYPES_CACHE']
20
- return nil unless cache_file and File.exist?(cache_file)
13
+ class Cache
14
+ class << self
15
+ # Attempts to load the cache from the file provided as a parameter or in
16
+ # the environment variable +RUBY_MIME_TYPES_CACHE+. Returns +nil+ if the
17
+ # file does not exist, if the file cannot be loaded, or if the data in
18
+ # the cache version is different than this version.
19
+ def load(cache_file = nil)
20
+ cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
21
+ return nil unless cache_file and File.exist?(cache_file)
21
22
 
22
- cache = Marshal.load(File.binread(cache_file))
23
- if cache.version == MIME::Types::VERSION
24
- Marshal.load(cache.data)
25
- else
26
- warn "Could not load MIME::Types cache: invalid version"
27
- nil
23
+ cache = Marshal.load(File.binread(cache_file))
24
+ if cache.version == MIME::Types::VERSION
25
+ Marshal.load(cache.data)
26
+ else
27
+ MIME::Types.logger.warn <<-warning.chomp
28
+ Could not load MIME::Types cache: invalid version
29
+ warning
30
+ nil
31
+ end
32
+ rescue => e
33
+ MIME::Types.logger.warn <<-warning.chomp
34
+ Could not load MIME::Types cache: #{e}
35
+ warning
36
+ return nil
28
37
  end
29
- rescue => e
30
- warn "Could not load MIME::Types cache: #{e}"
31
- return nil
32
- end
33
38
 
34
- # Attempts to save the types provided to the cache file provided.
35
- #
36
- # If +types+ is not provided or is +nil+, the cache will contain the
37
- # current MIME::Types default registry.
38
- #
39
- # If +cache_file+ is not provided or is +nil+, the cache will be written
40
- # to the file specified in the environment variable
41
- # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
42
- # directly or through the environment, this method will return +nil+
43
- def save(types = nil, cache_file = nil)
44
- cache_file = cache_file || ENV['RUBY_MIME_TYPES_CACHE']
45
- return nil unless cache_file
39
+ # Attempts to save the types provided to the cache file provided.
40
+ #
41
+ # If +types+ is not provided or is +nil+, the cache will contain the
42
+ # current MIME::Types default registry.
43
+ #
44
+ # If +cache_file+ is not provided or is +nil+, the cache will be written
45
+ # to the file specified in the environment variable
46
+ # +RUBY_MIME_TYPES_CACHE+. If there is no cache file specified either
47
+ # directly or through the environment, this method will return +nil+
48
+ def save(types = nil, cache_file = nil)
49
+ cache_file ||= ENV['RUBY_MIME_TYPES_CACHE']
50
+ return nil unless cache_file
46
51
 
47
- types = types || MIME::Types.send(:__types__)
52
+ types ||= MIME::Types.send(:__types__)
48
53
 
49
- File.open(cache_file, 'wb') do |f|
50
- f.write(Marshal.dump(new(types.data_version, Marshal.dump(types))))
54
+ File.open(cache_file, 'wb') do |f|
55
+ f.write(Marshal.dump(new(types.data_version, Marshal.dump(types))))
56
+ end
51
57
  end
52
58
  end
53
59
  end
@@ -0,0 +1,160 @@
1
+ module MIME
2
+ class Types
3
+ end
4
+ end
5
+
6
+ require 'mime/type/columnar'
7
+
8
+ # MIME::Types::Columnar is used to extend a MIME::Types container to load data
9
+ # by columns instead of from JSON or YAML. Column loads of MIME types loaded
10
+ # through the columnar store are synchronized with a Mutex.
11
+ #
12
+ # MIME::Types::Columnar is not intended to be used directly, but will be added
13
+ # to an instance of MIME::Types when it is loaded with
14
+ # MIME::Types::Loader#load_columnar.
15
+ module MIME::Types::Columnar
16
+ LOAD_MUTEX = Mutex.new # :nodoc:
17
+
18
+ def self.extended(obj) # :nodoc:
19
+ super
20
+ obj.instance_variable_set(:@__mime_data__, [])
21
+ obj.instance_variable_set(:@__attributes__, [])
22
+ end
23
+
24
+ # Load the first column data file (type and extensions).
25
+ def load_base_data(path) #:nodoc:
26
+ @__root__ = path
27
+
28
+ each_file_line('content_type', false) do |line|
29
+ content_type, extensions = line.split
30
+
31
+ type = MIME::Type::Columnar.new(self, content_type, extensions)
32
+ @__mime_data__ << type
33
+ add(type)
34
+ end
35
+
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def each_file_line(name, lookup = true)
42
+ LOAD_MUTEX.synchronize do
43
+ next if @__attributes__.include?(name)
44
+
45
+ File.open(File.join(@__root__, "mime.#{name}.column"), 'r:UTF-8') do |f|
46
+ i = -1
47
+
48
+ f.each_line do |line|
49
+ line.chomp!
50
+
51
+ if lookup
52
+ type = @__mime_data__[i += 1] or next
53
+ yield type, line
54
+ else
55
+ yield line
56
+ end
57
+ end
58
+ end
59
+
60
+ @__attributes__ << name
61
+ end
62
+ end
63
+
64
+ def load_encoding
65
+ pool = {}
66
+ each_file_line('encoding') do |type, line|
67
+ line.freeze
68
+ type.encoding = (pool[line] ||= line)
69
+ end
70
+ end
71
+
72
+ def load_docs
73
+ each_file_line('docs') do |type, line|
74
+ type.docs = arr(line)
75
+ end
76
+ end
77
+
78
+ def load_obsolete
79
+ each_file_line('obsolete') do |type, line|
80
+ type.obsolete = bool(line)
81
+ end
82
+ end
83
+
84
+ def load_references
85
+ each_file_line('references') do |type, line|
86
+ type.instance_variable_set(:@references, arr(line))
87
+ end
88
+ end
89
+
90
+ def load_registered
91
+ each_file_line('registered') do |type, line|
92
+ type.registered = bool(line)
93
+ end
94
+ end
95
+
96
+ def load_signature
97
+ each_file_line('signature') do |type, line|
98
+ type.signature = bool(line)
99
+ end
100
+ end
101
+
102
+ def load_system
103
+ each_file_line('system') do |type, line|
104
+ type.system = (line unless line == '-'.freeze)
105
+ end
106
+ end
107
+
108
+ def load_xrefs
109
+ each_file_line('xrefs') { |type, line| type.xrefs = dict(line) }
110
+ end
111
+
112
+ def load_friendly
113
+ each_file_line('friendly') { |type, line|
114
+ v = dict(line)
115
+ type.friendly = v.empty? ? nil : v
116
+ }
117
+ end
118
+
119
+ def load_use_instead
120
+ each_file_line('use_instead') do |type, line|
121
+ type.use_instad = (line unless line == '-'.freeze)
122
+ end
123
+ end
124
+
125
+ def dict(line)
126
+ if line == '-'.freeze
127
+ {}
128
+ else
129
+ line.split('|'.freeze).each_with_object({}) { |h, l|
130
+ k, v = l.split('^'.freeze)
131
+ v = [ nil ] if v.empty?
132
+ h[k] = v
133
+ }
134
+ end
135
+ end
136
+
137
+ def arr(line)
138
+ if line == '-'.freeze
139
+ []
140
+ else
141
+ line.split('|'.freeze).flatten.compact.uniq
142
+ end
143
+ end
144
+
145
+ def bool(line)
146
+ line == '1'.freeze ? true : false
147
+ end
148
+ end
149
+
150
+ unless MIME::Types.private_method_defined?(:load_mode)
151
+ class << MIME::Types
152
+ private
153
+
154
+ def load_mode
155
+ { columnar: true }
156
+ end
157
+ end
158
+
159
+ require 'mime/types'
160
+ end