final executable
BIN
build/exe.win-amd64-3.7/VCRUNTIME140.dll
Normal file
7
build/exe.win-amd64-3.7/colours.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# colours variables
|
||||||
|
|
||||||
|
WHITE=(245, 245, 245)
|
||||||
|
BLACK=(10, 10, 10)
|
||||||
|
RED=(245, 0, 0)
|
||||||
|
BLUE=(0, 0, 245)
|
||||||
|
BGCOLOR=(87,156,135)
|
32
build/exe.win-amd64-3.7/config.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Config variables
|
||||||
|
import pygame
|
||||||
|
from pygame.locals import *
|
||||||
|
|
||||||
|
# Runtime settings
|
||||||
|
WINDOW_WIDTH = 720
|
||||||
|
WINDOW_HEIGHT = 1000
|
||||||
|
FPS = 30
|
||||||
|
WIN_NAME = "Kostschevsky's shooter"
|
||||||
|
|
||||||
|
PLAYER_HP=100
|
||||||
|
|
||||||
|
# Controls
|
||||||
|
|
||||||
|
# player 1
|
||||||
|
P1_UP=pygame.K_w
|
||||||
|
P1_DOWN=pygame.K_s
|
||||||
|
P1_RIGHT=pygame.K_d
|
||||||
|
P1_LEFT=pygame.K_a
|
||||||
|
P1_SHOOT=pygame.K_LCTRL
|
||||||
|
|
||||||
|
# player 2
|
||||||
|
P2_UP=pygame.K_UP
|
||||||
|
P2_DOWN=pygame.K_DOWN
|
||||||
|
P2_RIGHT=pygame.K_RIGHT
|
||||||
|
P2_LEFT=pygame.K_LEFT
|
||||||
|
P2_SHOOT=pygame.K_RCTRL
|
||||||
|
|
||||||
|
# bullets
|
||||||
|
BULLET_SPEED=20
|
||||||
|
SHOOT_SPEED=200
|
||||||
|
BULLET_DMG=20
|
BIN
build/exe.win-amd64-3.7/data/graphics/bg.png
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
build/exe.win-amd64-3.7/data/graphics/bullet.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
build/exe.win-amd64-3.7/data/graphics/end0.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
build/exe.win-amd64-3.7/data/graphics/endp1.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
build/exe.win-amd64-3.7/data/graphics/endp2.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
build/exe.win-amd64-3.7/data/graphics/p1.png
Normal file
After Width: | Height: | Size: 211 B |
BIN
build/exe.win-amd64-3.7/data/graphics/p2.png
Normal file
After Width: | Height: | Size: 239 B |
BIN
build/exe.win-amd64-3.7/data/graphics/splash.png
Normal file
After Width: | Height: | Size: 26 KiB |
134
build/exe.win-amd64-3.7/events.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import os, sys
|
||||||
|
import pygame
|
||||||
|
from pygame.locals import *
|
||||||
|
|
||||||
|
from sprites import *
|
||||||
|
from config import *
|
||||||
|
|
||||||
|
mainloop=True
|
||||||
|
running=True
|
||||||
|
players=[]
|
||||||
|
|
||||||
|
p1_group=pygame.sprite.Group()
|
||||||
|
p2_group=pygame.sprite.Group()
|
||||||
|
p1_bullet=[]
|
||||||
|
p2_bullet=[]
|
||||||
|
|
||||||
|
p1_bullet_group=pygame.sprite.Group()
|
||||||
|
p2_bullet_group=pygame.sprite.Group()
|
||||||
|
|
||||||
|
clock=pygame.time.Clock()
|
||||||
|
clock.tick()
|
||||||
|
timer1=1000
|
||||||
|
clock2=pygame.time.Clock()
|
||||||
|
clock2.tick()
|
||||||
|
timer2=1000
|
||||||
|
|
||||||
|
bars=[]
|
||||||
|
|
||||||
|
def events():
|
||||||
|
global running
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
pygame.quit()
|
||||||
|
sys.exit()
|
||||||
|
#running=False
|
||||||
|
|
||||||
|
def collision_check(p):
|
||||||
|
# collision between players
|
||||||
|
if players[0].rect.colliderect(players[1].rect):
|
||||||
|
if p==1:
|
||||||
|
players[0].colliding=True
|
||||||
|
direction=players[1].facing
|
||||||
|
players[0].image=pygame.transform.rotate(players[0].image, players[0].facing*90-((direction+2)%4)*90)
|
||||||
|
players[0].facing=(direction+2)%4
|
||||||
|
return True
|
||||||
|
elif p==0:
|
||||||
|
players[1].colliding=True
|
||||||
|
direction=players[0].facing
|
||||||
|
players[1].image=pygame.transform.rotate(players[1].image, players[1].facing*90-((direction+2)%4)*90)
|
||||||
|
players[1].facing=(direction+2)%4
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
players[0].colliding=True
|
||||||
|
players[1].colliding=True
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def bullethits():
|
||||||
|
hits1=pygame.sprite.groupcollide(p2_group, p1_bullet_group, False, True)
|
||||||
|
hits2=pygame.sprite.groupcollide(p1_group, p2_bullet_group, False, True)
|
||||||
|
if hits1:
|
||||||
|
players[1].gothit()
|
||||||
|
bars[1].gothit()
|
||||||
|
if hits2:
|
||||||
|
players[0].gothit()
|
||||||
|
bars[0].gothit()
|
||||||
|
|
||||||
|
def player1_input(keys):
|
||||||
|
if keys[P1_SHOOT]:
|
||||||
|
global timer1
|
||||||
|
p1_bullet.append(Bullet('bullet', players[0].pos.x, players[0].pos.y, players[0].facing))
|
||||||
|
if timer1>SHOOT_SPEED:
|
||||||
|
p1_bullet_group.add(p1_bullet[-1])
|
||||||
|
all_sprites.add(p1_bullet[-1])
|
||||||
|
p1_bullet[-1].direction=players[0].facing
|
||||||
|
p1_bullet[-1].shoot()
|
||||||
|
timer1=clock.tick()
|
||||||
|
else:
|
||||||
|
del p1_bullet[-1]
|
||||||
|
if not (keys[P1_UP] or keys[P1_DOWN] or keys[P1_RIGHT] or keys[P1_LEFT]):
|
||||||
|
players[0].stopmoving()
|
||||||
|
elif not collision_check(0):
|
||||||
|
if keys[P1_RIGHT]:
|
||||||
|
players[0].moveright()
|
||||||
|
if keys[P1_LEFT]:
|
||||||
|
players[0].moveleft()
|
||||||
|
if keys[P1_UP]:
|
||||||
|
players[0].moveup()
|
||||||
|
if keys[P1_DOWN]:
|
||||||
|
players[0].movedown()
|
||||||
|
|
||||||
|
def player2_input(keys):
|
||||||
|
if keys[P2_SHOOT]:
|
||||||
|
global timer2
|
||||||
|
p2_bullet.append(Bullet('bullet', players[1].pos.x, players[1].pos.y, players[1].facing))
|
||||||
|
if timer2>SHOOT_SPEED:
|
||||||
|
p2_bullet_group.add(p2_bullet[-1])
|
||||||
|
all_sprites.add(p2_bullet[-1])
|
||||||
|
p2_bullet[-1].direction=players[1].facing
|
||||||
|
p2_bullet[-1].shoot()
|
||||||
|
timer2=clock.tick()
|
||||||
|
else:
|
||||||
|
del p2_bullet[-1]
|
||||||
|
if not (keys[P2_UP] or keys[P2_DOWN] or keys[P2_RIGHT] or keys[P2_LEFT]):
|
||||||
|
players[1].stopmoving()
|
||||||
|
elif not collision_check(1):
|
||||||
|
if keys[P2_RIGHT]:
|
||||||
|
players[1].moveright()
|
||||||
|
if keys[P2_LEFT]:
|
||||||
|
players[1].moveleft()
|
||||||
|
if keys[P2_UP]:
|
||||||
|
players[1].moveup()
|
||||||
|
if keys[P2_DOWN]:
|
||||||
|
players[1].movedown()
|
||||||
|
def dead():
|
||||||
|
if players[0].alive and players[1].alive:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def event_handler():
|
||||||
|
global timer1
|
||||||
|
global timer2
|
||||||
|
events()
|
||||||
|
keys=pygame.key.get_pressed()
|
||||||
|
collision_check(-1)
|
||||||
|
bullethits()
|
||||||
|
timer1+=clock.tick()
|
||||||
|
timer2+=clock2.tick()
|
||||||
|
player1_input(keys)
|
||||||
|
player2_input(keys)
|
||||||
|
|
||||||
|
|
BIN
build/exe.win-amd64-3.7/lib/VCRUNTIME140.dll
Normal file
BIN
build/exe.win-amd64-3.7/lib/_bz2.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_contextvars.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_ctypes.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_decimal.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_elementtree.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_hashlib.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_lzma.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_multiprocessing.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_queue.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_socket.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_ssl.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_testcapi.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_tkinter.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/_win32sysloader.pyd
Normal file
BIN
build/exe.win-amd64-3.7/lib/collections/__init__.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/collections/abc.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/__init__.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/_aix.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/_endian.pyc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Files in this directory come from Bob Ippolito's py2app.
|
||||||
|
|
||||||
|
License: Any components of the py2app suite may be distributed under
|
||||||
|
the MIT or PSF open source licenses.
|
||||||
|
|
||||||
|
This is version 1.0, SVN revision 789, from 2006/01/25.
|
||||||
|
The main repository is http://svn.red-bean.com/bob/macholib/trunk/macholib/
|
BIN
build/exe.win-amd64-3.7/lib/ctypes/macholib/__init__.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/macholib/dyld.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/macholib/dylib.pyc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
|
@ -0,0 +1 @@
|
|||||||
|
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
|
BIN
build/exe.win-amd64-3.7/lib/ctypes/macholib/framework.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/util.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/ctypes/wintypes.pyc
Normal file
13
build/exe.win-amd64-3.7/lib/distutils/README
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This directory contains the Distutils package.
|
||||||
|
|
||||||
|
There's a full documentation available at:
|
||||||
|
|
||||||
|
http://docs.python.org/distutils/
|
||||||
|
|
||||||
|
The Distutils-SIG web page is also a good starting point:
|
||||||
|
|
||||||
|
http://www.python.org/sigs/distutils-sig/
|
||||||
|
|
||||||
|
WARNING : Distutils must remain compatible with 2.3
|
||||||
|
|
||||||
|
$Id$
|
BIN
build/exe.win-amd64-3.7/lib/distutils/__init__.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/ccompiler.pyc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""distutils.command.x
|
||||||
|
|
||||||
|
Implements the Distutils 'x' command.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# created 2000/mm/dd, John Doe
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from distutils.core import Command
|
||||||
|
|
||||||
|
|
||||||
|
class x(Command):
|
||||||
|
|
||||||
|
# Brief (40-50 characters) description of the command
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
# List of option tuples: long name, short name (None if no short
|
||||||
|
# name), and help string.
|
||||||
|
user_options = [('', '',
|
||||||
|
""),
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
self. = None
|
||||||
|
self. = None
|
||||||
|
self. = None
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
if self.x is None:
|
||||||
|
self.x =
|
||||||
|
|
||||||
|
def run(self):
|
BIN
build/exe.win-amd64-3.7/lib/distutils/command/wininst-10.0.exe
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/command/wininst-14.0.exe
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/command/wininst-6.0.exe
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/command/wininst-7.1.exe
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/command/wininst-8.0.exe
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/command/wininst-9.0.exe
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/debug.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/dep_util.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/dir_util.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/errors.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/fancy_getopt.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/file_util.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/filelist.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/log.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/spawn.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/sysconfig.pyc
Normal file
67
build/exe.win-amd64-3.7/lib/distutils/tests/Setup.sample
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Setup file from the pygame project
|
||||||
|
|
||||||
|
#--StartConfig
|
||||||
|
SDL = -I/usr/include/SDL -D_REENTRANT -lSDL
|
||||||
|
FONT = -lSDL_ttf
|
||||||
|
IMAGE = -lSDL_image
|
||||||
|
MIXER = -lSDL_mixer
|
||||||
|
SMPEG = -lsmpeg
|
||||||
|
PNG = -lpng
|
||||||
|
JPEG = -ljpeg
|
||||||
|
SCRAP = -lX11
|
||||||
|
PORTMIDI = -lportmidi
|
||||||
|
PORTTIME = -lporttime
|
||||||
|
#--EndConfig
|
||||||
|
|
||||||
|
#DEBUG = -C-W -C-Wall
|
||||||
|
DEBUG =
|
||||||
|
|
||||||
|
#the following modules are optional. you will want to compile
|
||||||
|
#everything you can, but you can ignore ones you don't have
|
||||||
|
#dependencies for, just comment them out
|
||||||
|
|
||||||
|
imageext src/imageext.c $(SDL) $(IMAGE) $(PNG) $(JPEG) $(DEBUG)
|
||||||
|
font src/font.c $(SDL) $(FONT) $(DEBUG)
|
||||||
|
mixer src/mixer.c $(SDL) $(MIXER) $(DEBUG)
|
||||||
|
mixer_music src/music.c $(SDL) $(MIXER) $(DEBUG)
|
||||||
|
_numericsurfarray src/_numericsurfarray.c $(SDL) $(DEBUG)
|
||||||
|
_numericsndarray src/_numericsndarray.c $(SDL) $(MIXER) $(DEBUG)
|
||||||
|
movie src/movie.c $(SDL) $(SMPEG) $(DEBUG)
|
||||||
|
scrap src/scrap.c $(SDL) $(SCRAP) $(DEBUG)
|
||||||
|
_camera src/_camera.c src/camera_v4l2.c src/camera_v4l.c $(SDL) $(DEBUG)
|
||||||
|
pypm src/pypm.c $(SDL) $(PORTMIDI) $(PORTTIME) $(DEBUG)
|
||||||
|
|
||||||
|
GFX = src/SDL_gfx/SDL_gfxPrimitives.c
|
||||||
|
#GFX = src/SDL_gfx/SDL_gfxBlitFunc.c src/SDL_gfx/SDL_gfxPrimitives.c
|
||||||
|
gfxdraw src/gfxdraw.c $(SDL) $(GFX) $(DEBUG)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#these modules are required for pygame to run. they only require
|
||||||
|
#SDL as a dependency. these should not be altered
|
||||||
|
|
||||||
|
base src/base.c $(SDL) $(DEBUG)
|
||||||
|
cdrom src/cdrom.c $(SDL) $(DEBUG)
|
||||||
|
color src/color.c $(SDL) $(DEBUG)
|
||||||
|
constants src/constants.c $(SDL) $(DEBUG)
|
||||||
|
display src/display.c $(SDL) $(DEBUG)
|
||||||
|
event src/event.c $(SDL) $(DEBUG)
|
||||||
|
fastevent src/fastevent.c src/fastevents.c $(SDL) $(DEBUG)
|
||||||
|
key src/key.c $(SDL) $(DEBUG)
|
||||||
|
mouse src/mouse.c $(SDL) $(DEBUG)
|
||||||
|
rect src/rect.c $(SDL) $(DEBUG)
|
||||||
|
rwobject src/rwobject.c $(SDL) $(DEBUG)
|
||||||
|
surface src/surface.c src/alphablit.c src/surface_fill.c $(SDL) $(DEBUG)
|
||||||
|
surflock src/surflock.c $(SDL) $(DEBUG)
|
||||||
|
time src/time.c $(SDL) $(DEBUG)
|
||||||
|
joystick src/joystick.c $(SDL) $(DEBUG)
|
||||||
|
draw src/draw.c $(SDL) $(DEBUG)
|
||||||
|
image src/image.c $(SDL) $(DEBUG)
|
||||||
|
overlay src/overlay.c $(SDL) $(DEBUG)
|
||||||
|
transform src/transform.c src/rotozoom.c src/scale2x.c src/scale_mmx.c $(SDL) $(DEBUG)
|
||||||
|
mask src/mask.c src/bitmask.c $(SDL) $(DEBUG)
|
||||||
|
bufferproxy src/bufferproxy.c $(SDL) $(DEBUG)
|
||||||
|
pixelarray src/pixelarray.c $(SDL) $(DEBUG)
|
||||||
|
_arraysurfarray src/_arraysurfarray.c $(SDL) $(DEBUG)
|
||||||
|
|
||||||
|
|
BIN
build/exe.win-amd64-3.7/lib/distutils/text_file.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/distutils/util.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/email/__init__.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/email/_encoded_words.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/email/_header_value_parser.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/email/_parseaddr.pyc
Normal file
BIN
build/exe.win-amd64-3.7/lib/email/_policybase.pyc
Normal file
216
build/exe.win-amd64-3.7/lib/email/architecture.rst
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
:mod:`email` Package Architecture
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
The email package consists of three major components:
|
||||||
|
|
||||||
|
Model
|
||||||
|
An object structure that represents an email message, and provides an
|
||||||
|
API for creating, querying, and modifying a message.
|
||||||
|
|
||||||
|
Parser
|
||||||
|
Takes a sequence of characters or bytes and produces a model of the
|
||||||
|
email message represented by those characters or bytes.
|
||||||
|
|
||||||
|
Generator
|
||||||
|
Takes a model and turns it into a sequence of characters or bytes. The
|
||||||
|
sequence can either be intended for human consumption (a printable
|
||||||
|
unicode string) or bytes suitable for transmission over the wire. In
|
||||||
|
the latter case all data is properly encoded using the content transfer
|
||||||
|
encodings specified by the relevant RFCs.
|
||||||
|
|
||||||
|
Conceptually the package is organized around the model. The model provides both
|
||||||
|
"external" APIs intended for use by application programs using the library,
|
||||||
|
and "internal" APIs intended for use by the Parser and Generator components.
|
||||||
|
This division is intentionally a bit fuzzy; the API described by this
|
||||||
|
documentation is all a public, stable API. This allows for an application
|
||||||
|
with special needs to implement its own parser and/or generator.
|
||||||
|
|
||||||
|
In addition to the three major functional components, there is a third key
|
||||||
|
component to the architecture:
|
||||||
|
|
||||||
|
Policy
|
||||||
|
An object that specifies various behavioral settings and carries
|
||||||
|
implementations of various behavior-controlling methods.
|
||||||
|
|
||||||
|
The Policy framework provides a simple and convenient way to control the
|
||||||
|
behavior of the library, making it possible for the library to be used in a
|
||||||
|
very flexible fashion while leveraging the common code required to parse,
|
||||||
|
represent, and generate message-like objects. For example, in addition to the
|
||||||
|
default :rfc:`5322` email message policy, we also have a policy that manages
|
||||||
|
HTTP headers in a fashion compliant with :rfc:`2616`. Individual policy
|
||||||
|
controls, such as the maximum line length produced by the generator, can also
|
||||||
|
be controlled individually to meet specialized application requirements.
|
||||||
|
|
||||||
|
|
||||||
|
The Model
|
||||||
|
---------
|
||||||
|
|
||||||
|
The message model is implemented by the :class:`~email.message.Message` class.
|
||||||
|
The model divides a message into the two fundamental parts discussed by the
|
||||||
|
RFC: the header section and the body. The `Message` object acts as a
|
||||||
|
pseudo-dictionary of named headers. Its dictionary interface provides
|
||||||
|
convenient access to individual headers by name. However, all headers are kept
|
||||||
|
internally in an ordered list, so that the information about the order of the
|
||||||
|
headers in the original message is preserved.
|
||||||
|
|
||||||
|
The `Message` object also has a `payload` that holds the body. A `payload` can
|
||||||
|
be one of two things: data, or a list of `Message` objects. The latter is used
|
||||||
|
to represent a multipart MIME message. Lists can be nested arbitrarily deeply
|
||||||
|
in order to represent the message, with all terminal leaves having non-list
|
||||||
|
data payloads.
|
||||||
|
|
||||||
|
|
||||||
|
Message Lifecycle
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The general lifecycle of a message is:
|
||||||
|
|
||||||
|
Creation
|
||||||
|
A `Message` object can be created by a Parser, or it can be
|
||||||
|
instantiated as an empty message by an application.
|
||||||
|
|
||||||
|
Manipulation
|
||||||
|
The application may examine one or more headers, and/or the
|
||||||
|
payload, and it may modify one or more headers and/or
|
||||||
|
the payload. This may be done on the top level `Message`
|
||||||
|
object, or on any sub-object.
|
||||||
|
|
||||||
|
Finalization
|
||||||
|
The Model is converted into a unicode or binary stream,
|
||||||
|
or the model is discarded.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Header Policy Control During Lifecycle
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
One of the major controls exerted by the Policy is the management of headers
|
||||||
|
during the `Message` lifecycle. Most applications don't need to be aware of
|
||||||
|
this.
|
||||||
|
|
||||||
|
A header enters the model in one of two ways: via a Parser, or by being set to
|
||||||
|
a specific value by an application program after the Model already exists.
|
||||||
|
Similarly, a header exits the model in one of two ways: by being serialized by
|
||||||
|
a Generator, or by being retrieved from a Model by an application program. The
|
||||||
|
Policy object provides hooks for all four of these pathways.
|
||||||
|
|
||||||
|
The model storage for headers is a list of (name, value) tuples.
|
||||||
|
|
||||||
|
The Parser identifies headers during parsing, and passes them to the
|
||||||
|
:meth:`~email.policy.Policy.header_source_parse` method of the Policy. The
|
||||||
|
result of that method is the (name, value) tuple to be stored in the model.
|
||||||
|
|
||||||
|
When an application program supplies a header value (for example, through the
|
||||||
|
`Message` object `__setitem__` interface), the name and the value are passed to
|
||||||
|
the :meth:`~email.policy.Policy.header_store_parse` method of the Policy, which
|
||||||
|
returns the (name, value) tuple to be stored in the model.
|
||||||
|
|
||||||
|
When an application program retrieves a header (through any of the dict or list
|
||||||
|
interfaces of `Message`), the name and value are passed to the
|
||||||
|
:meth:`~email.policy.Policy.header_fetch_parse` method of the Policy to
|
||||||
|
obtain the value returned to the application.
|
||||||
|
|
||||||
|
When a Generator requests a header during serialization, the name and value are
|
||||||
|
passed to the :meth:`~email.policy.Policy.fold` method of the Policy, which
|
||||||
|
returns a string containing line breaks in the appropriate places. The
|
||||||
|
:meth:`~email.policy.Policy.cte_type` Policy control determines whether or
|
||||||
|
not Content Transfer Encoding is performed on the data in the header. There is
|
||||||
|
also a :meth:`~email.policy.Policy.binary_fold` method for use by generators
|
||||||
|
that produce binary output, which returns the folded header as binary data,
|
||||||
|
possibly folded at different places than the corresponding string would be.
|
||||||
|
|
||||||
|
|
||||||
|
Handling Binary Data
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
In an ideal world all message data would conform to the RFCs, meaning that the
|
||||||
|
parser could decode the message into the idealized unicode message that the
|
||||||
|
sender originally wrote. In the real world, the email package must also be
|
||||||
|
able to deal with badly formatted messages, including messages containing
|
||||||
|
non-ASCII characters that either have no indicated character set or are not
|
||||||
|
valid characters in the indicated character set.
|
||||||
|
|
||||||
|
Since email messages are *primarily* text data, and operations on message data
|
||||||
|
are primarily text operations (except for binary payloads of course), the model
|
||||||
|
stores all text data as unicode strings. Un-decodable binary inside text
|
||||||
|
data is handled by using the `surrogateescape` error handler of the ASCII
|
||||||
|
codec. As with the binary filenames the error handler was introduced to
|
||||||
|
handle, this allows the email package to "carry" the binary data received
|
||||||
|
during parsing along until the output stage, at which time it is regenerated
|
||||||
|
in its original form.
|
||||||
|
|
||||||
|
This carried binary data is almost entirely an implementation detail. The one
|
||||||
|
place where it is visible in the API is in the "internal" API. A Parser must
|
||||||
|
do the `surrogateescape` encoding of binary input data, and pass that data to
|
||||||
|
the appropriate Policy method. The "internal" interface used by the Generator
|
||||||
|
to access header values preserves the `surrogateescaped` bytes. All other
|
||||||
|
interfaces convert the binary data either back into bytes or into a safe form
|
||||||
|
(losing information in some cases).
|
||||||
|
|
||||||
|
|
||||||
|
Backward Compatibility
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The :class:`~email.policy.Policy.Compat32` Policy provides backward
|
||||||
|
compatibility with version 5.1 of the email package. It does this via the
|
||||||
|
following implementation of the four+1 Policy methods described above:
|
||||||
|
|
||||||
|
header_source_parse
|
||||||
|
Splits the first line on the colon to obtain the name, discards any spaces
|
||||||
|
after the colon, and joins the remainder of the line with all of the
|
||||||
|
remaining lines, preserving the linesep characters to obtain the value.
|
||||||
|
Trailing carriage return and/or linefeed characters are stripped from the
|
||||||
|
resulting value string.
|
||||||
|
|
||||||
|
header_store_parse
|
||||||
|
Returns the name and value exactly as received from the application.
|
||||||
|
|
||||||
|
header_fetch_parse
|
||||||
|
If the value contains any `surrogateescaped` binary data, return the value
|
||||||
|
as a :class:`~email.header.Header` object, using the character set
|
||||||
|
`unknown-8bit`. Otherwise just returns the value.
|
||||||
|
|
||||||
|
fold
|
||||||
|
Uses :class:`~email.header.Header`'s folding to fold headers in the
|
||||||
|
same way the email5.1 generator did.
|
||||||
|
|
||||||
|
binary_fold
|
||||||
|
Same as fold, but encodes to 'ascii'.
|
||||||
|
|
||||||
|
|
||||||
|
New Algorithm
|
||||||
|
-------------
|
||||||
|
|
||||||
|
header_source_parse
|
||||||
|
Same as legacy behavior.
|
||||||
|
|
||||||
|
header_store_parse
|
||||||
|
Same as legacy behavior.
|
||||||
|
|
||||||
|
header_fetch_parse
|
||||||
|
If the value is already a header object, returns it. Otherwise, parses the
|
||||||
|
value using the new parser, and returns the resulting object as the value.
|
||||||
|
`surrogateescaped` bytes get turned into unicode unknown character code
|
||||||
|
points.
|
||||||
|
|
||||||
|
fold
|
||||||
|
Uses the new header folding algorithm, respecting the policy settings.
|
||||||
|
surrogateescaped bytes are encoded using the ``unknown-8bit`` charset for
|
||||||
|
``cte_type=7bit`` or ``8bit``. Returns a string.
|
||||||
|
|
||||||
|
At some point there will also be a ``cte_type=unicode``, and for that
|
||||||
|
policy fold will serialize the idealized unicode message with RFC-like
|
||||||
|
folding, converting any surrogateescaped bytes into the unicode
|
||||||
|
unknown character glyph.
|
||||||
|
|
||||||
|
binary_fold
|
||||||
|
Uses the new header folding algorithm, respecting the policy settings.
|
||||||
|
surrogateescaped bytes are encoded using the `unknown-8bit` charset for
|
||||||
|
``cte_type=7bit``, and get turned back into bytes for ``cte_type=8bit``.
|
||||||
|
Returns bytes.
|
||||||
|
|
||||||
|
At some point there will also be a ``cte_type=unicode``, and for that
|
||||||
|
policy binary_fold will serialize the message according to :rfc:``5335``.
|