Skip to content

Commit

Permalink
Deprecate array and string type initialization
Browse files Browse the repository at this point in the history
- 2 deprecations:

  - Array-based MIME::Type initialization
  - String-based MIME::Type initialization

  Use of these these will result in deprecation warnings.

- Added `logger` to the gemspec to suppress a bundled gem warning with
  Ruby 3.3.5. This warning should not be showing up until Ruby 3.4.0 is
  released and will be suppressed in Ruby 3.3.6.
  • Loading branch information
halostatue committed Sep 18, 2024
1 parent e8d0b42 commit 0e9a0a0
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 106 deletions.
1 change: 1 addition & 0 deletions .hoerc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ exclude: !ruby/regexp '/
fasterer |
pullreview |
rubocop* |
standard* |
travis |
unused
)\.yml$
Expand Down
13 changes: 13 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 3.6 / 2024-09-19

- 2 deprecations:

- Array-based MIME::Type initialization
- String-based MIME::Type initialization

Use of these these will result in deprecation warnings.

- Added `logger` to the gemspec to suppress a bundled gem warning with Ruby
3.3.5. This warning should not be showing up until Ruby 3.4.0 is released and
will be suppressed in Ruby 3.3.6.

## 3.5.2 / 2024-01-02

There are no primary code changes, but we are releasing this as an update as
Expand Down
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ spec = Hoe.spec "mime-types" do
spec_extras[:metadata] = ->(val) { val["rubygems_mfa_required"] = "true" }

extra_deps << ["mime-types-data", "~> 3.2015"]
extra_deps << ["logger", ">= 0"]

extra_dev_deps << ["hoe", ">= 3.0", "< 5"]
extra_dev_deps << ["hoe-doofus", "~> 1.0"]
Expand Down
101 changes: 58 additions & 43 deletions lib/mime/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
module MIME
end

require "mime/types/deprecations"

# The definition of one MIME content-type.
#
# == Usage
# require 'mime/types'
# require "mime/types"
#
# plaintext = MIME::Types['text/plain'] # => [ text/plain ]
# plaintext = MIME::Types["text/plain"] # => [ text/plain ]
# text = plaintext.first
# puts text.media_type # => 'text'
# puts text.sub_type # => 'plain'
# puts text.media_type # => "text"
# puts text.sub_type # => "plain"
#
# puts text.extensions.join(' ') # => 'txt asc c cc h hh cpp hpp dat hlp'
# puts text.preferred_extension # => 'txt'
# puts text.friendly # => 'Text Document'
# puts text.i18n_key # => 'text.plain'
# puts text.extensions.join(" ") # => "txt asc c cc h hh cpp hpp dat hlp"
# puts text.preferred_extension # => "txt"
# puts text.friendly # => "Text Document"
# puts text.i18n_key # => "text.plain"
#
# puts text.encoding # => quoted-printable
# puts text.default_encoding # => quoted-printable
Expand All @@ -28,45 +30,45 @@ module MIME
# puts text.provisional? # => false
# puts text.complete? # => true
#
# puts text # => 'text/plain'
# puts text # => "text/plain"
#
# puts text == 'text/plain' # => true
# puts 'text/plain' == text # => true
# puts text == 'text/x-plain' # => false
# puts 'text/x-plain' == text # => false
# puts text == "text/plain" # => true
# puts "text/plain" == text # => true
# puts text == "text/x-plain" # => false
# puts "text/x-plain" == text # => false
#
# puts MIME::Type.simplified('x-appl/x-zip') # => 'x-appl/x-zip'
# puts MIME::Type.i18n_key('x-appl/x-zip') # => 'x-appl.x-zip'
# puts MIME::Type.simplified("x-appl/x-zip") # => "x-appl/x-zip"
# puts MIME::Type.i18n_key("x-appl/x-zip") # => "x-appl.x-zip"
#
# puts text.like?('text/x-plain') # => true
# puts text.like?(MIME::Type.new('x-text/x-plain')) # => true
# puts text.like?("text/x-plain") # => true
# puts text.like?(MIME::Type.new("content-type" => "x-text/x-plain")) # => true
#
# puts text.xrefs.inspect # => { "rfc" => [ "rfc2046", "rfc3676", "rfc5147" ] }
# puts text.xref_urls # => [ "http://www.iana.org/go/rfc2046",
# # "http://www.iana.org/go/rfc3676",
# # "http://www.iana.org/go/rfc5147" ]
#
# xtext = MIME::Type.new('x-text/x-plain')
# puts xtext.media_type # => 'text'
# puts xtext.raw_media_type # => 'x-text'
# puts xtext.sub_type # => 'plain'
# puts xtext.raw_sub_type # => 'x-plain'
# xtext = MIME::Type.new("x-text/x-plain")
# puts xtext.media_type # => "text"
# puts xtext.raw_media_type # => "x-text"
# puts xtext.sub_type # => "plain"
# puts xtext.raw_sub_type # => "x-plain"
# puts xtext.complete? # => false
#
# puts MIME::Types.any? { |type| type.content_type == 'text/plain' } # => true
# puts MIME::Types.any? { |type| type.content_type == "text/plain" } # => true
# puts MIME::Types.all?(&:registered?) # => false
#
# # Various string representations of MIME types
# qcelp = MIME::Types['audio/QCELP'].first # => audio/QCELP
# puts qcelp.content_type # => 'audio/QCELP'
# puts qcelp.simplified # => 'audio/qcelp'
# qcelp = MIME::Types["audio/QCELP"].first # => audio/QCELP
# puts qcelp.content_type # => "audio/QCELP"
# puts qcelp.simplified # => "audio/qcelp"
#
# xwingz = MIME::Types['application/x-Wingz'].first # => application/x-Wingz
# puts xwingz.content_type # => 'application/x-Wingz'
# puts xwingz.simplified # => 'application/x-wingz'
# xwingz = MIME::Types["application/x-Wingz"].first # => application/x-Wingz
# puts xwingz.content_type # => "application/x-Wingz"
# puts xwingz.simplified # => "application/x-wingz"
class MIME::Type
# Reflects a MIME content-type specification that is not correctly
# formatted (it isn't +type+/+subtype+).
# formatted (it is not +type+/+subtype+).
class InvalidContentType < ArgumentError
# :stopdoc:
def initialize(type_string)
Expand All @@ -93,14 +95,20 @@ def to_s
end

# The released version of the mime-types library.
VERSION = "3.5.2"
VERSION = "3.6"

include Comparable

# :stopdoc:
# TODO verify mime-type character restrictions; I am pretty sure that this is
# too wide open.
MEDIA_TYPE_RE = %r{([-\w.+]+)/([-\w.+]*)}.freeze
# Full conformance with RFC 6838 §4.2 (the recommendation for < 64 characters is not
# enforced or reported because MIME::Types mostly deals with registered data). RFC 4288
# §4.2 does not restrict the first character to alphanumeric, but the total length of
# each part is limited to 127 characters. RFCC 2045 §5.1 does not restrict the character
# composition except for whitespace, but MIME::Type was always more strict than this.
restricted_name_first = "[0-9a-zA-Z]"
restricted_name_chars = "[-!#{$&}^_.+0-9a-zA-Z]{0,126}"
restricted_name = "#{restricted_name_first}#{restricted_name_chars}"
MEDIA_TYPE_RE = %r{(#{restricted_name})/(#{restricted_name})}.freeze
I18N_RE = /[^[:alnum:]]/.freeze
BINARY_ENCODINGS = %w[base64 8bit].freeze
ASCII_ENCODINGS = %w[7bit quoted-printable].freeze
Expand All @@ -110,12 +118,15 @@ def to_s
:ASCII_ENCODINGS

# Builds a MIME::Type object from the +content_type+, a MIME Content Type
# value (e.g., 'text/plain' or 'application/x-eruby'). The constructed object
# value (e.g., "text/plain" or "application/x-eruby"). The constructed object
# is yielded to an optional block for additional configuration, such as
# associating extensions and encoding information.
#
# * When provided a Hash or a MIME::Type, the MIME::Type will be
# constructed with #init_with.
#
# There are two deprecated initialization forms:
#
# * When provided an Array, the MIME::Type will be constructed using
# the first element as the content type and the remaining flattened
# elements as extensions.
Expand All @@ -132,11 +143,13 @@ def initialize(content_type) # :yields: self
when Hash
init_with(content_type)
when Array
MIME::Types.deprecated(MIME::Type, {new: "when called with an Array"}, "")
self.content_type = content_type.shift
self.extensions = content_type.flatten
when MIME::Type
init_with(content_type.to_h)
else
MIME::Types.deprecated(MIME::Type, {new: "when called with a String"}, "")
self.content_type = content_type
end

Expand Down Expand Up @@ -181,7 +194,7 @@ def <=>(other)
# comparisons involved are:
#
# 1. self.simplified <=> other.simplified (ensures that we
# don't try to compare different types)
# do not try to compare different types)
# 2. IANA-registered definitions < other definitions.
# 3. Complete definitions < incomplete definitions.
# 4. Current definitions < obsolete definitions.
Expand Down Expand Up @@ -243,7 +256,7 @@ def eql?(other)
# +a.simplified+.
#
# Presumably, if <code>a.simplified <=> b.simplified</code> is +0+, then
# +a.simplified+ has the same hash as +b.simplified+. So we assume it's
# +a.simplified+ has the same hash as +b.simplified+. So we assume it is
# suitable for #hash to delegate to #simplified in service of the #eql?
# invariant.
def hash
Expand Down Expand Up @@ -319,7 +332,7 @@ def add_extensions(*extensions)
# exceptions defined, the first extension will be used.
#
# When setting #preferred_extensions, if #extensions does not contain this
# extension, this will be added to #xtensions.
# extension, this will be added to #extensions.
#
# :attr_accessor: preferred_extension

Expand All @@ -330,7 +343,9 @@ def preferred_extension

##
def preferred_extension=(value) # :nodoc:
add_extensions(value) if value
if value
add_extensions(value)
end
@preferred_extension = value
end

Expand All @@ -343,7 +358,7 @@ def preferred_extension=(value) # :nodoc:
# provided is invalid.
#
# If the encoding is not provided on construction, this will be either
# 'quoted-printable' (for text/* media types) and 'base64' for eveything
# "quoted-printable" (for text/* media types) and "base64" for eveything
# else.
#
# :attr_accessor: encoding
Expand Down Expand Up @@ -393,7 +408,7 @@ def use_instead
#
# call-seq:
# text_plain.friendly # => "Text File"
# text_plain.friendly('en') # => "Text File"
# text_plain.friendly("en") # => "Text File"
def friendly(lang = "en")
@friendly ||= {}

Expand Down Expand Up @@ -486,7 +501,7 @@ def to_s
# Returns the MIME::Type as a string for implicit conversions. This allows
# MIME::Type objects to appear on either side of a comparison.
#
# 'text/plain' == MIME::Type.new('text/plain')
# "text/plain" == MIME::Type.new("content-type" => "text/plain")
def to_str
content_type
end
Expand Down Expand Up @@ -627,7 +642,7 @@ def intern_string(string)
-string
end
else
# MRI 2.2 and older don't have a method for string interning,
# MRI 2.2 and older do not have a method for string interning,
# so we simply freeze them for keeping a similar interface
def intern_string(string)
string.freeze
Expand Down
4 changes: 2 additions & 2 deletions lib/mime/types/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

# MIME::Types requires a serializable keyed container that returns an empty Set
# on a key miss. Hash#default_value cannot be used because, while it traverses
# the Marshal format correctly, it won't survive any other serialization
# the Marshal format correctly, it will not survive any other serialization
# format (plus, a default of a mutable object resuls in a shared mess).
# Hash#default_proc cannot be used without a wrapper because it prevents
# Marshal serialization (and doesn't survive the round-trip).
# Marshal serialization (and does not survive the round-trip).
class MIME::Types::Container # :nodoc:
extend Forwardable

Expand Down
15 changes: 11 additions & 4 deletions lib/mime/types/deprecations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,24 @@ def self.deprecated(klass, sym, message = nil, &block) # :nodoc:
klass = klass.class
"#"
end

sym, pre_message = sym.shift if sym.is_a?(Hash)
pre_message = " #{pre_message}" if pre_message

message =
case message
when :private, :protected
"and will be #{message}"
" and will be made #{message}"
when nil
"and will be removed"
" and will be removed"
when ""
nil
else
message
" #{message}"
end

MIME::Types.logger.debug <<-WARNING.chomp.strip
#{caller(2..2).first}: #{klass}#{level}#{sym} is deprecated #{message}.
#{caller(2..2).first}: #{klass}#{level}#{sym}#{pre_message} is deprecated#{message}.
WARNING

return unless block
Expand Down
2 changes: 1 addition & 1 deletion lib/mime/types/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class MIME::Types; end
#
# The Loader will use one of the following paths:
# 1. The +path+ provided in its constructor argument;
# 2. The value of ENV['RUBY_MIME_TYPES_DATA']; or
# 2. The value of ENV["RUBY_MIME_TYPES_DATA"]; or
# 3. The value of MIME::Types::Data::PATH.
#
# When #load is called, the +path+ will be searched recursively for all YAML
Expand Down
11 changes: 6 additions & 5 deletions mime-types.gemspec
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# -*- encoding: utf-8 -*-
# stub: mime-types 3.5.2 ruby lib
# stub: mime-types 3.6 ruby lib

Gem::Specification.new do |s|
s.name = "mime-types".freeze
s.version = "3.5.2".freeze
s.version = "3.6".freeze

s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.metadata = { "bug_tracker_uri" => "https://github.com/mime-types/ruby-mime-types/issues", "changelog_uri" => "https://github.com/mime-types/ruby-mime-types/blob/master/History.md", "homepage_uri" => "https://github.com/mime-types/ruby-mime-types/", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/mime-types/ruby-mime-types/" } if s.respond_to? :metadata=
s.require_paths = ["lib".freeze]
s.authors = ["Austin Ziegler".freeze]
s.date = "2024-01-02"
s.date = "2024-09-18"
s.description = "The mime-types library provides a library and registry for information about\nMIME content type definitions. It can be used to determine defined filename\nextensions for MIME types, or to use filename extensions to look up the likely\nMIME type definitions.\n\nVersion 3.0 is a major release that requires Ruby 2.0 compatibility and removes\ndeprecated functions. The columnar registry format introduced in 2.6 has been\nmade the primary format; the registry data has been extracted from this library\nand put into {mime-types-data}[https://github.com/mime-types/mime-types-data].\nAdditionally, mime-types is now licensed exclusively under the MIT licence and\nthere is a code of conduct in effect. There are a number of other smaller\nchanges described in the History file.".freeze
s.email = ["[email protected]".freeze]
s.extra_rdoc_files = ["Code-of-Conduct.md".freeze, "Contributing.md".freeze, "History.md".freeze, "Licence.md".freeze, "Manifest.txt".freeze, "README.rdoc".freeze]
Expand All @@ -18,13 +18,14 @@ Gem::Specification.new do |s|
s.licenses = ["MIT".freeze]
s.rdoc_options = ["--main".freeze, "README.rdoc".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.0".freeze)
s.rubygems_version = "3.5.3".freeze
s.rubygems_version = "3.5.16".freeze
s.summary = "The mime-types library provides a library and registry for information about MIME content type definitions".freeze

s.specification_version = 4

s.add_runtime_dependency(%q<mime-types-data>.freeze, ["~> 3.2015".freeze])
s.add_development_dependency(%q<minitest>.freeze, ["~> 5.20".freeze])
s.add_runtime_dependency(%q<logger>.freeze, [">= 0".freeze])
s.add_development_dependency(%q<minitest>.freeze, ["~> 5.25".freeze])
s.add_development_dependency(%q<hoe>.freeze, [">= 3.0".freeze, "< 5".freeze])
s.add_development_dependency(%q<hoe-doofus>.freeze, ["~> 1.0".freeze])
s.add_development_dependency(%q<hoe-gemspec2>.freeze, ["~> 1.1".freeze])
Expand Down
Loading

0 comments on commit 0e9a0a0

Please sign in to comment.