mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 15:41:43 +00:00 
			
		
		
		
	This new interface will also allow for future planned enhancements in control over the parser/generator without requiring any additional complexity in the parser/generator API. Patch reviewed by Éric Araujo and Barry Warsaw.
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Policy framework for the email package.
 | 
						|
 | 
						|
Allows fine grained feature control of how the package parses and emits data.
 | 
						|
"""
 | 
						|
 | 
						|
__all__ = [
 | 
						|
    'Policy',
 | 
						|
    'default',
 | 
						|
    'strict',
 | 
						|
    'SMTP',
 | 
						|
    'HTTP',
 | 
						|
    ]
 | 
						|
 | 
						|
 | 
						|
class _PolicyBase:
 | 
						|
 | 
						|
    """Policy Object basic framework.
 | 
						|
 | 
						|
    This class is useless unless subclassed.  A subclass should define
 | 
						|
    class attributes with defaults for any values that are to be
 | 
						|
    managed by the Policy object.  The constructor will then allow
 | 
						|
    non-default values to be set for these attributes at instance
 | 
						|
    creation time.  The instance will be callable, taking these same
 | 
						|
    attributes keyword arguments, and returning a new instance
 | 
						|
    identical to the called instance except for those values changed
 | 
						|
    by the keyword arguments.  Instances may be added, yielding new
 | 
						|
    instances with any non-default values from the right hand
 | 
						|
    operand overriding those in the left hand operand.  That is,
 | 
						|
 | 
						|
        A + B == A(<non-default values of B>)
 | 
						|
 | 
						|
    The repr of an instance can be used to reconstruct the object
 | 
						|
    if and only if the repr of the values can be used to reconstruct
 | 
						|
    those values.
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, **kw):
 | 
						|
        """Create new Policy, possibly overriding some defaults.
 | 
						|
 | 
						|
        See class docstring for a list of overridable attributes.
 | 
						|
 | 
						|
        """
 | 
						|
        for name, value in kw.items():
 | 
						|
            if hasattr(self, name):
 | 
						|
                super(_PolicyBase,self).__setattr__(name, value)
 | 
						|
            else:
 | 
						|
                raise TypeError(
 | 
						|
                    "{!r} is an invalid keyword argument for {}".format(
 | 
						|
                        name, self.__class__.__name__))
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        args = [ "{}={!r}".format(name, value)
 | 
						|
                 for name, value in self.__dict__.items() ]
 | 
						|
        return "{}({})".format(self.__class__.__name__, args if args else '')
 | 
						|
 | 
						|
    def clone(self, **kw):
 | 
						|
        """Return a new instance with specified attributes changed.
 | 
						|
 | 
						|
        The new instance has the same attribute values as the current object,
 | 
						|
        except for the changes passed in as keyword arguments.
 | 
						|
 | 
						|
        """
 | 
						|
        for attr, value in self.__dict__.items():
 | 
						|
            if attr not in kw:
 | 
						|
                kw[attr] = value
 | 
						|
        return self.__class__(**kw)
 | 
						|
 | 
						|
    def __setattr__(self, name, value):
 | 
						|
        if hasattr(self, name):
 | 
						|
            msg = "{!r} object attribute {!r} is read-only"
 | 
						|
        else:
 | 
						|
            msg = "{!r} object has no attribute {!r}"
 | 
						|
        raise AttributeError(msg.format(self.__class__.__name__, name))
 | 
						|
 | 
						|
    def __add__(self, other):
 | 
						|
        """Non-default values from right operand override those from left.
 | 
						|
 | 
						|
        The object returned is a new instance of the subclass.
 | 
						|
 | 
						|
        """
 | 
						|
        return self.clone(**other.__dict__)
 | 
						|
 | 
						|
 | 
						|
class Policy(_PolicyBase):
 | 
						|
 | 
						|
    """Controls for how messages are interpreted and formatted.
 | 
						|
 | 
						|
    Most of the classes and many of the methods in the email package
 | 
						|
    accept Policy objects as parameters.  A Policy object contains a set
 | 
						|
    of values and functions that control how input is interpreted and how
 | 
						|
    output is rendered.  For example, the parameter 'raise_on_defect'
 | 
						|
    controls whether or not an RFC violation throws an error or not,
 | 
						|
    while 'max_line_length' controls the maximum length of output lines
 | 
						|
    when a Message is serialized.
 | 
						|
 | 
						|
    Any valid attribute may be overridden when a Policy is created by
 | 
						|
    passing it as a keyword argument to the constructor.  Policy
 | 
						|
    objects are immutable, but a new Policy object can be created
 | 
						|
    with only certain values changed by calling the Policy instance
 | 
						|
    with keyword arguments.  Policy objects can also be added,
 | 
						|
    producing a new Policy object in which the non-default attributes
 | 
						|
    set in the right hand operand overwrite those specified in the
 | 
						|
    left operand.
 | 
						|
 | 
						|
    Settable attributes:
 | 
						|
 | 
						|
    raise_on_defect     -- If true, then defects should be raised
 | 
						|
                           as errors.  Default False.
 | 
						|
 | 
						|
    linesep             -- string containing the value to use as
 | 
						|
                           separation between output lines.  Default '\n'.
 | 
						|
 | 
						|
    must_be_7bit        -- output must contain only 7bit clean data.
 | 
						|
                           Default False.
 | 
						|
 | 
						|
    max_line_length     -- maximum length of lines, excluding 'linesep',
 | 
						|
                           during serialization.  None means no line
 | 
						|
                           wrapping is done.  Default is 78.
 | 
						|
 | 
						|
    Methods:
 | 
						|
 | 
						|
    register_defect(obj, defect)
 | 
						|
        defect is a Defect instance.  The default implementation appends defect
 | 
						|
        to the objs 'defects' attribute.
 | 
						|
 | 
						|
    handle_defect(obj, defect)
 | 
						|
        intended to be called by parser code that finds a defect.  If
 | 
						|
        raise_on_defect is True, defect is raised as an error, otherwise
 | 
						|
        register_defect is called.
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    raise_on_defect = False
 | 
						|
    linesep = '\n'
 | 
						|
    must_be_7bit = False
 | 
						|
    max_line_length = 78
 | 
						|
 | 
						|
    def handle_defect(self, obj, defect):
 | 
						|
        """Based on policy, either raise defect or call register_defect.
 | 
						|
 | 
						|
            handle_defect(obj, defect)
 | 
						|
 | 
						|
        defect should be a Defect subclass, but in any case must be an
 | 
						|
        Exception subclass.  obj is the object on which the defect should be
 | 
						|
        registered if it is not raised.  If the raise_on_defect is True, the
 | 
						|
        defect is raised as an error, otherwise the object and the defect are
 | 
						|
        passed to register_defect.
 | 
						|
 | 
						|
        This class is intended to be called by parsers that discover defects,
 | 
						|
        and will not be called from code using the library unless that code is
 | 
						|
        implementing an alternate parser.
 | 
						|
 | 
						|
        """
 | 
						|
        if self.raise_on_defect:
 | 
						|
            raise defect
 | 
						|
        self.register_defect(obj, defect)
 | 
						|
 | 
						|
    def register_defect(self, obj, defect):
 | 
						|
        """Record 'defect' on 'obj'.
 | 
						|
 | 
						|
        Called by handle_defect if raise_on_defect is False.  This method is
 | 
						|
        part of the Policy API so that Policy subclasses can implement custom
 | 
						|
        defect handling.  The default implementation calls the append method
 | 
						|
        of the defects attribute of obj.
 | 
						|
 | 
						|
        """
 | 
						|
        obj.defects.append(defect)
 | 
						|
 | 
						|
 | 
						|
default = Policy()
 | 
						|
strict = default.clone(raise_on_defect=True)
 | 
						|
SMTP = default.clone(linesep='\r\n')
 | 
						|
HTTP = default.clone(linesep='\r\n', max_line_length=None)
 |