(root)/
Python-3.12.0/
Lib/
email/
_policybase.py
       1  """Policy framework for the email package.
       2  
       3  Allows fine grained feature control of how the package parses and emits data.
       4  """
       5  
       6  import abc
       7  from email import header
       8  from email import charset as _charset
       9  from email.utils import _has_surrogates
      10  
      11  __all__ = [
      12      'Policy',
      13      'Compat32',
      14      'compat32',
      15      ]
      16  
      17  
      18  class ESC[4;38;5;81m_PolicyBase:
      19  
      20      """Policy Object basic framework.
      21  
      22      This class is useless unless subclassed.  A subclass should define
      23      class attributes with defaults for any values that are to be
      24      managed by the Policy object.  The constructor will then allow
      25      non-default values to be set for these attributes at instance
      26      creation time.  The instance will be callable, taking these same
      27      attributes keyword arguments, and returning a new instance
      28      identical to the called instance except for those values changed
      29      by the keyword arguments.  Instances may be added, yielding new
      30      instances with any non-default values from the right hand
      31      operand overriding those in the left hand operand.  That is,
      32  
      33          A + B == A(<non-default values of B>)
      34  
      35      The repr of an instance can be used to reconstruct the object
      36      if and only if the repr of the values can be used to reconstruct
      37      those values.
      38  
      39      """
      40  
      41      def __init__(self, **kw):
      42          """Create new Policy, possibly overriding some defaults.
      43  
      44          See class docstring for a list of overridable attributes.
      45  
      46          """
      47          for name, value in kw.items():
      48              if hasattr(self, name):
      49                  super(_PolicyBase,self).__setattr__(name, value)
      50              else:
      51                  raise TypeError(
      52                      "{!r} is an invalid keyword argument for {}".format(
      53                          name, self.__class__.__name__))
      54  
      55      def __repr__(self):
      56          args = [ "{}={!r}".format(name, value)
      57                   for name, value in self.__dict__.items() ]
      58          return "{}({})".format(self.__class__.__name__, ', '.join(args))
      59  
      60      def clone(self, **kw):
      61          """Return a new instance with specified attributes changed.
      62  
      63          The new instance has the same attribute values as the current object,
      64          except for the changes passed in as keyword arguments.
      65  
      66          """
      67          newpolicy = self.__class__.__new__(self.__class__)
      68          for attr, value in self.__dict__.items():
      69              object.__setattr__(newpolicy, attr, value)
      70          for attr, value in kw.items():
      71              if not hasattr(self, attr):
      72                  raise TypeError(
      73                      "{!r} is an invalid keyword argument for {}".format(
      74                          attr, self.__class__.__name__))
      75              object.__setattr__(newpolicy, attr, value)
      76          return newpolicy
      77  
      78      def __setattr__(self, name, value):
      79          if hasattr(self, name):
      80              msg = "{!r} object attribute {!r} is read-only"
      81          else:
      82              msg = "{!r} object has no attribute {!r}"
      83          raise AttributeError(msg.format(self.__class__.__name__, name))
      84  
      85      def __add__(self, other):
      86          """Non-default values from right operand override those from left.
      87  
      88          The object returned is a new instance of the subclass.
      89  
      90          """
      91          return self.clone(**other.__dict__)
      92  
      93  
      94  def _append_doc(doc, added_doc):
      95      doc = doc.rsplit('\n', 1)[0]
      96      added_doc = added_doc.split('\n', 1)[1]
      97      return doc + '\n' + added_doc
      98  
      99  def _extend_docstrings(cls):
     100      if cls.__doc__ and cls.__doc__.startswith('+'):
     101          cls.__doc__ = _append_doc(cls.__bases__[0].__doc__, cls.__doc__)
     102      for name, attr in cls.__dict__.items():
     103          if attr.__doc__ and attr.__doc__.startswith('+'):
     104              for c in (c for base in cls.__bases__ for c in base.mro()):
     105                  doc = getattr(getattr(c, name), '__doc__')
     106                  if doc:
     107                      attr.__doc__ = _append_doc(doc, attr.__doc__)
     108                      break
     109      return cls
     110  
     111  
     112  class ESC[4;38;5;81mPolicy(ESC[4;38;5;149m_PolicyBase, metaclass=ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mABCMeta):
     113  
     114      r"""Controls for how messages are interpreted and formatted.
     115  
     116      Most of the classes and many of the methods in the email package accept
     117      Policy objects as parameters.  A Policy object contains a set of values and
     118      functions that control how input is interpreted and how output is rendered.
     119      For example, the parameter 'raise_on_defect' controls whether or not an RFC
     120      violation results in an error being raised or not, while 'max_line_length'
     121      controls the maximum length of output lines when a Message is serialized.
     122  
     123      Any valid attribute may be overridden when a Policy is created by passing
     124      it as a keyword argument to the constructor.  Policy objects are immutable,
     125      but a new Policy object can be created with only certain values changed by
     126      calling the Policy instance with keyword arguments.  Policy objects can
     127      also be added, producing a new Policy object in which the non-default
     128      attributes set in the right hand operand overwrite those specified in the
     129      left operand.
     130  
     131      Settable attributes:
     132  
     133      raise_on_defect     -- If true, then defects should be raised as errors.
     134                             Default: False.
     135  
     136      linesep             -- string containing the value to use as separation
     137                             between output lines.  Default '\n'.
     138  
     139      cte_type            -- Type of allowed content transfer encodings
     140  
     141                             7bit  -- ASCII only
     142                             8bit  -- Content-Transfer-Encoding: 8bit is allowed
     143  
     144                             Default: 8bit.  Also controls the disposition of
     145                             (RFC invalid) binary data in headers; see the
     146                             documentation of the binary_fold method.
     147  
     148      max_line_length     -- maximum length of lines, excluding 'linesep',
     149                             during serialization.  None or 0 means no line
     150                             wrapping is done.  Default is 78.
     151  
     152      mangle_from_        -- a flag that, when True escapes From_ lines in the
     153                             body of the message by putting a `>' in front of
     154                             them. This is used when the message is being
     155                             serialized by a generator. Default: True.
     156  
     157      message_factory     -- the class to use to create new message objects.
     158                             If the value is None, the default is Message.
     159  
     160      """
     161  
     162      raise_on_defect = False
     163      linesep = '\n'
     164      cte_type = '8bit'
     165      max_line_length = 78
     166      mangle_from_ = False
     167      message_factory = None
     168  
     169      def handle_defect(self, obj, defect):
     170          """Based on policy, either raise defect or call register_defect.
     171  
     172              handle_defect(obj, defect)
     173  
     174          defect should be a Defect subclass, but in any case must be an
     175          Exception subclass.  obj is the object on which the defect should be
     176          registered if it is not raised.  If the raise_on_defect is True, the
     177          defect is raised as an error, otherwise the object and the defect are
     178          passed to register_defect.
     179  
     180          This method is intended to be called by parsers that discover defects.
     181          The email package parsers always call it with Defect instances.
     182  
     183          """
     184          if self.raise_on_defect:
     185              raise defect
     186          self.register_defect(obj, defect)
     187  
     188      def register_defect(self, obj, defect):
     189          """Record 'defect' on 'obj'.
     190  
     191          Called by handle_defect if raise_on_defect is False.  This method is
     192          part of the Policy API so that Policy subclasses can implement custom
     193          defect handling.  The default implementation calls the append method of
     194          the defects attribute of obj.  The objects used by the email package by
     195          default that get passed to this method will always have a defects
     196          attribute with an append method.
     197  
     198          """
     199          obj.defects.append(defect)
     200  
     201      def header_max_count(self, name):
     202          """Return the maximum allowed number of headers named 'name'.
     203  
     204          Called when a header is added to a Message object.  If the returned
     205          value is not 0 or None, and there are already a number of headers with
     206          the name 'name' equal to the value returned, a ValueError is raised.
     207  
     208          Because the default behavior of Message's __setitem__ is to append the
     209          value to the list of headers, it is easy to create duplicate headers
     210          without realizing it.  This method allows certain headers to be limited
     211          in the number of instances of that header that may be added to a
     212          Message programmatically.  (The limit is not observed by the parser,
     213          which will faithfully produce as many headers as exist in the message
     214          being parsed.)
     215  
     216          The default implementation returns None for all header names.
     217          """
     218          return None
     219  
     220      @abc.abstractmethod
     221      def header_source_parse(self, sourcelines):
     222          """Given a list of linesep terminated strings constituting the lines of
     223          a single header, return the (name, value) tuple that should be stored
     224          in the model.  The input lines should retain their terminating linesep
     225          characters.  The lines passed in by the email package may contain
     226          surrogateescaped binary data.
     227          """
     228          raise NotImplementedError
     229  
     230      @abc.abstractmethod
     231      def header_store_parse(self, name, value):
     232          """Given the header name and the value provided by the application
     233          program, return the (name, value) that should be stored in the model.
     234          """
     235          raise NotImplementedError
     236  
     237      @abc.abstractmethod
     238      def header_fetch_parse(self, name, value):
     239          """Given the header name and the value from the model, return the value
     240          to be returned to the application program that is requesting that
     241          header.  The value passed in by the email package may contain
     242          surrogateescaped binary data if the lines were parsed by a BytesParser.
     243          The returned value should not contain any surrogateescaped data.
     244  
     245          """
     246          raise NotImplementedError
     247  
     248      @abc.abstractmethod
     249      def fold(self, name, value):
     250          """Given the header name and the value from the model, return a string
     251          containing linesep characters that implement the folding of the header
     252          according to the policy controls.  The value passed in by the email
     253          package may contain surrogateescaped binary data if the lines were
     254          parsed by a BytesParser.  The returned value should not contain any
     255          surrogateescaped data.
     256  
     257          """
     258          raise NotImplementedError
     259  
     260      @abc.abstractmethod
     261      def fold_binary(self, name, value):
     262          """Given the header name and the value from the model, return binary
     263          data containing linesep characters that implement the folding of the
     264          header according to the policy controls.  The value passed in by the
     265          email package may contain surrogateescaped binary data.
     266  
     267          """
     268          raise NotImplementedError
     269  
     270  
     271  @_extend_docstrings
     272  class ESC[4;38;5;81mCompat32(ESC[4;38;5;149mPolicy):
     273  
     274      """+
     275      This particular policy is the backward compatibility Policy.  It
     276      replicates the behavior of the email package version 5.1.
     277      """
     278  
     279      mangle_from_ = True
     280  
     281      def _sanitize_header(self, name, value):
     282          # If the header value contains surrogates, return a Header using
     283          # the unknown-8bit charset to encode the bytes as encoded words.
     284          if not isinstance(value, str):
     285              # Assume it is already a header object
     286              return value
     287          if _has_surrogates(value):
     288              return header.Header(value, charset=_charset.UNKNOWN8BIT,
     289                                   header_name=name)
     290          else:
     291              return value
     292  
     293      def header_source_parse(self, sourcelines):
     294          """+
     295          The name is parsed as everything up to the ':' and returned unmodified.
     296          The value is determined by stripping leading whitespace off the
     297          remainder of the first line, joining all subsequent lines together, and
     298          stripping any trailing carriage return or linefeed characters.
     299  
     300          """
     301          name, value = sourcelines[0].split(':', 1)
     302          value = value.lstrip(' \t') + ''.join(sourcelines[1:])
     303          return (name, value.rstrip('\r\n'))
     304  
     305      def header_store_parse(self, name, value):
     306          """+
     307          The name and value are returned unmodified.
     308          """
     309          return (name, value)
     310  
     311      def header_fetch_parse(self, name, value):
     312          """+
     313          If the value contains binary data, it is converted into a Header object
     314          using the unknown-8bit charset.  Otherwise it is returned unmodified.
     315          """
     316          return self._sanitize_header(name, value)
     317  
     318      def fold(self, name, value):
     319          """+
     320          Headers are folded using the Header folding algorithm, which preserves
     321          existing line breaks in the value, and wraps each resulting line to the
     322          max_line_length.  Non-ASCII binary data are CTE encoded using the
     323          unknown-8bit charset.
     324  
     325          """
     326          return self._fold(name, value, sanitize=True)
     327  
     328      def fold_binary(self, name, value):
     329          """+
     330          Headers are folded using the Header folding algorithm, which preserves
     331          existing line breaks in the value, and wraps each resulting line to the
     332          max_line_length.  If cte_type is 7bit, non-ascii binary data is CTE
     333          encoded using the unknown-8bit charset.  Otherwise the original source
     334          header is used, with its existing line breaks and/or binary data.
     335  
     336          """
     337          folded = self._fold(name, value, sanitize=self.cte_type=='7bit')
     338          return folded.encode('ascii', 'surrogateescape')
     339  
     340      def _fold(self, name, value, sanitize):
     341          parts = []
     342          parts.append('%s: ' % name)
     343          if isinstance(value, str):
     344              if _has_surrogates(value):
     345                  if sanitize:
     346                      h = header.Header(value,
     347                                        charset=_charset.UNKNOWN8BIT,
     348                                        header_name=name)
     349                  else:
     350                      # If we have raw 8bit data in a byte string, we have no idea
     351                      # what the encoding is.  There is no safe way to split this
     352                      # string.  If it's ascii-subset, then we could do a normal
     353                      # ascii split, but if it's multibyte then we could break the
     354                      # string.  There's no way to know so the least harm seems to
     355                      # be to not split the string and risk it being too long.
     356                      parts.append(value)
     357                      h = None
     358              else:
     359                  h = header.Header(value, header_name=name)
     360          else:
     361              # Assume it is a Header-like object.
     362              h = value
     363          if h is not None:
     364              # The Header class interprets a value of None for maxlinelen as the
     365              # default value of 78, as recommended by RFC 2822.
     366              maxlinelen = 0
     367              if self.max_line_length is not None:
     368                  maxlinelen = self.max_line_length
     369              parts.append(h.encode(linesep=self.linesep, maxlinelen=maxlinelen))
     370          parts.append(self.linesep)
     371          return ''.join(parts)
     372  
     373  
     374  compat32 = Compat32()