code: def deprecated(removal_version, hint_message=None, subject=None, ensure_stderr=False):
    
    validate_deprecation_semver(removal_version, 'removal version')
    def decorator(func):
      if not inspect.isfunction(func):
        raise BadDecoratorNestingError('The @deprecated decorator must be applied innermost of all '
                                       'decorators.')
  
      func_full_name = '{}.{}'.format(func.__module__, func.__name__)
  
      @wraps(func)
      def wrapper(*args, **kwargs):
        warn_or_error(removal_version, subject or func_full_name, hint_message,
                      ensure_stderr=ensure_stderr)
        return func(*args, **kwargs)
      return wrapper
    return decorator
docs: Marks a function or method as deprecated.
  
    A removal version must be supplied and it must be greater than the current 'pantsbuild.pants'
    version.
  
    When choosing a removal version there is a natural tension between the code-base, which benefits
    from short deprecation cycles, and the user-base which may prefer to deal with deprecations less
    frequently.  As a rule of thumb, if the hint message can fully convey corrective action
    succinctly and you judge the impact to be on the small side (effects custom tasks as opposed to
    effecting BUILD files), lean towards the next release version as the removal version; otherwise,
    consider initiating a discussion to win consensus on a reasonable removal version.
  
    :param str removal_version: The pantsbuild.pants version which will remove the deprecated
                                function.
    :param str hint_message: An optional hint pointing to alternatives to the deprecation.
    :param str subject: The name of the subject that has been deprecated for logging clarity. Defaults
                        to the name of the decorated function/method.
    :param bool ensure_stderr: Forwarded to `ensure_stderr` in warn_or_error().
    :raises DeprecationApplicationError if the @deprecation is applied improperly.