[Python-checkins] CVS: python/dist/src/Lib/email Message.py,1.1,1.2

Barry Warsaw bwarsaw@users.sourceforge.net
Tue, 25 Sep 2001 22:41:54 -0700


Update of /cvsroot/python/python/dist/src/Lib/email
In directory usw-pr-cvs1:/tmp/cvs-serv28509

Modified Files:
	Message.py 
Log Message:
has_key(): Implement in terms of get().

get_type(): Use a compiled regular expression, which can be shared.

_get_params_preserve(): A helper method which extracts the header's
    parameter list preserving value quoting.  I'm not sure that this
    needs to be a public method.  It's necessary because we want
    get_param() and friends to return the unquoted parameter value,
    however we want the quote-preserved form for set_boundary().

get_params(), get_param(), set_boundary(): Implement in terms of
    _get_params_preserve(). 

walk(): Yield ourself first, then recurse over our subparts (if any).


Index: Message.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/email/Message.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** Message.py	2001/09/23 03:17:28	1.1
--- Message.py	2001/09/26 05:41:51	1.2
***************
*** 13,22 ****
  from types import ListType
  
- SEMISPACE = '; '
- 
  # Intrapackage imports
  import Errors
  import Utils
  
  
  
--- 13,23 ----
  from types import ListType
  
  # Intrapackage imports
  import Errors
  import Utils
  
+ SEMISPACE = '; '
+ paramre = re.compile(r';\s*')
+ 
  
  
***************
*** 136,140 ****
      #
      def __len__(self):
!         """Get the total number of headers, including duplicates."""
          return len(self._headers)
  
--- 137,141 ----
      #
      def __len__(self):
!         """Return the total number of headers, including duplicates."""
          return len(self._headers)
  
***************
*** 175,179 ****
      def has_key(self, name):
          """Return true if the message contains the header."""
!         return self[name] <> None
  
      def keys(self):
--- 176,181 ----
      def has_key(self, name):
          """Return true if the message contains the header."""
!         missing = []
!         return self.get(name, missing) is not missing
  
      def keys(self):
***************
*** 268,272 ****
          if value is missing:
              return failobj
!         return re.split(r';\s+', value)[0].lower()
  
      def get_main_type(self, failobj=None):
--- 270,274 ----
          if value is missing:
              return failobj
!         return paramre.split(value)[0].lower()
  
      def get_main_type(self, failobj=None):
***************
*** 292,298 ****
--- 294,324 ----
          return failobj
  
+     def _get_params_preserve(self, failobj, header):
+         # Like get_params() but preserves the quoting of values.  BAW:
+         # should this be part of the public interface?
+         missing = []
+         value = self.get(header, missing)
+         if value is missing:
+             return failobj
+         params = []
+         for p in paramre.split(value):
+             try:
+                 name, val = p.split('=', 1)
+             except ValueError:
+                 # Must have been a bare attribute
+                 name = p
+                 val = ''
+             params.append((name, val))
+         return params
+ 
      def get_params(self, failobj=None, header='content-type'):
          """Return the message's Content-Type: parameters, as a list.
  
+         The elements of the returned list are 2-tuples of key/value pairs, as
+         split on the `=' sign.  The left hand side of the `=' is the key,
+         while the right hand side is the value.  If there is no `=' sign in
+         the parameter the value is the empty string.  The value is always
+         unquoted.
+ 
          Optional failobj is the object to return if there is no Content-Type:
          header.  Optional header is the header to search instead of
***************
*** 300,307 ****
          """
          missing = []
!         value = self.get(header, missing)
!         if value is missing:
              return failobj
!         return re.split(r';\s+', value)[1:]
  
      def get_param(self, param, failobj=None, header='content-type'):
--- 326,333 ----
          """
          missing = []
!         params = self._get_params_preserve(missing, header)
!         if params is missing:
              return failobj
!         return [(k, Utils.unquote(v)) for k, v in params]
  
      def get_param(self, param, failobj=None, header='content-type'):
***************
*** 311,329 ****
          header.  Optional header is the header to search instead of
          Content-Type:
          """
!         param = param.lower()
!         missing = []
!         params = self.get_params(missing, header=header)
!         if params is missing:
              return failobj
!         for p in params:
!             try:
!                 name, val = p.split('=', 1)
!             except ValueError:
!                 # Must have been a bare attribute
!                 name = p
!                 val = ''
!             if name.lower() == param:
!                 return Utils.unquote(val)
          return failobj
  
--- 337,349 ----
          header.  Optional header is the header to search instead of
          Content-Type:
+ 
+         Parameter keys are always compared case insensitively.  Values are
+         always unquoted.
          """
!         if not self.has_key(header):
              return failobj
!         for k, v in self._get_params_preserve(failobj, header):
!             if k.lower() == param.lower():
!                 return Utils.unquote(v)
          return failobj
  
***************
*** 362,367 ****
          HeaderParseError is raised if the message has no Content-Type: header.
          """
!         params = self.get_params()
!         if not params:
              # There was no Content-Type: header, and we don't know what type
              # to set it to, so raise an exception.
--- 382,388 ----
          HeaderParseError is raised if the message has no Content-Type: header.
          """
!         missing = []
!         params = self._get_params_preserve(missing, 'content-type')
!         if params is missing:
              # There was no Content-Type: header, and we don't know what type
              # to set it to, so raise an exception.
***************
*** 369,390 ****
          newparams = []
          foundp = 0
!         for p in params:
!             if p.lower().startswith('boundary='):
!                 newparams.append('boundary="%s"' % boundary)
                  foundp = 1
              else:
!                 newparams.append(p)
          if not foundp:
              # The original Content-Type: header had no boundary attribute.
              # Tack one one the end.  BAW: should we raise an exception
              # instead???
!             newparams.append('boundary="%s"' % boundary)
          # Replace the existing Content-Type: header with the new value
          newheaders = []
          for h, v in self._headers:
              if h.lower() == 'content-type':
!                 value = v.split(';', 1)[0]
!                 newparams.insert(0, value)
!                 newheaders.append((h, SEMISPACE.join(newparams)))
              else:
                  newheaders.append((h, v))
--- 390,416 ----
          newparams = []
          foundp = 0
!         for pk, pv in params:
!             if pk.lower() == 'boundary':
!                 newparams.append(('boundary', '"%s"' % boundary))
                  foundp = 1
              else:
!                 newparams.append((pk, pv))
          if not foundp:
              # The original Content-Type: header had no boundary attribute.
              # Tack one one the end.  BAW: should we raise an exception
              # instead???
!             newparams.append(('boundary', '"%s"' % boundary))
          # Replace the existing Content-Type: header with the new value
          newheaders = []
          for h, v in self._headers:
              if h.lower() == 'content-type':
!                 parts = []
!                 for k, v in newparams:
!                     if v == '':
!                         parts.append(k)
!                     else:
!                         parts.append('%s=%s' % (k, v))
!                 newheaders.append((h, SEMISPACE.join(parts)))
! 
              else:
                  newheaders.append((h, v))
***************
*** 397,406 ****
          generator.
          """
          if self.is_multipart():
              for subpart in self.get_payload():
                  for subsubpart in subpart.walk():
                      yield subsubpart
-         else:
-             yield self
  
      def get_charsets(self, failobj=None):
--- 423,431 ----
          generator.
          """
+         yield self
          if self.is_multipart():
              for subpart in self.get_payload():
                  for subsubpart in subpart.walk():
                      yield subsubpart
  
      def get_charsets(self, failobj=None):