Grammalecte  Hex Artifact Content

Artifact 0fd84d167524c44af037ab0c173d5f9e81e713dbbd7d4e54a9a91e4e7354f5d0:


0000: 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 70  #!/usr/bin/env p
0010: 79 74 68 6f 6e 0a 23 20 2d 2a 2d 20 63 6f 64 69  ython.# -*- codi
0020: 6e 67 3a 20 75 74 66 2d 38 20 2d 2a 2d 0a 22 22  ng: utf-8 -*-.""
0030: 22 0a 42 6f 74 74 6c 65 20 69 73 20 61 20 66 61  ".Bottle is a fa
0040: 73 74 20 61 6e 64 20 73 69 6d 70 6c 65 20 6d 69  st and simple mi
0050: 63 72 6f 2d 66 72 61 6d 65 77 6f 72 6b 20 66 6f  cro-framework fo
0060: 72 20 73 6d 61 6c 6c 20 77 65 62 20 61 70 70 6c  r small web appl
0070: 69 63 61 74 69 6f 6e 73 2e 20 49 74 0a 6f 66 66  ications. It.off
0080: 65 72 73 20 72 65 71 75 65 73 74 20 64 69 73 70  ers request disp
0090: 61 74 63 68 69 6e 67 20 28 52 6f 75 74 65 73 29  atching (Routes)
00a0: 20 77 69 74 68 20 75 72 6c 20 70 61 72 61 6d 65   with url parame
00b0: 74 65 72 20 73 75 70 70 6f 72 74 2c 20 74 65 6d  ter support, tem
00c0: 70 6c 61 74 65 73 2c 0a 61 20 62 75 69 6c 74 2d  plates,.a built-
00d0: 69 6e 20 48 54 54 50 20 53 65 72 76 65 72 20 61  in HTTP Server a
00e0: 6e 64 20 61 64 61 70 74 65 72 73 20 66 6f 72 20  nd adapters for 
00f0: 6d 61 6e 79 20 74 68 69 72 64 20 70 61 72 74 79  many third party
0100: 20 57 53 47 49 2f 48 54 54 50 2d 73 65 72 76 65   WSGI/HTTP-serve
0110: 72 20 61 6e 64 0a 74 65 6d 70 6c 61 74 65 20 65  r and.template e
0120: 6e 67 69 6e 65 73 20 2d 20 61 6c 6c 20 69 6e 20  ngines - all in 
0130: 61 20 73 69 6e 67 6c 65 20 66 69 6c 65 20 61 6e  a single file an
0140: 64 20 77 69 74 68 20 6e 6f 20 64 65 70 65 6e 64  d with no depend
0150: 65 6e 63 69 65 73 20 6f 74 68 65 72 20 74 68 61  encies other tha
0160: 6e 20 74 68 65 0a 50 79 74 68 6f 6e 20 53 74 61  n the.Python Sta
0170: 6e 64 61 72 64 20 4c 69 62 72 61 72 79 2e 0a 0a  ndard Library...
0180: 48 6f 6d 65 70 61 67 65 20 61 6e 64 20 64 6f 63  Homepage and doc
0190: 75 6d 65 6e 74 61 74 69 6f 6e 3a 20 68 74 74 70  umentation: http
01a0: 3a 2f 2f 62 6f 74 74 6c 65 70 79 2e 6f 72 67 2f  ://bottlepy.org/
01b0: 0a 0a 43 6f 70 79 72 69 67 68 74 20 28 63 29 20  ..Copyright (c) 
01c0: 32 30 31 36 2c 20 4d 61 72 63 65 6c 20 48 65 6c  2016, Marcel Hel
01d0: 6c 6b 61 6d 70 2e 0a 4c 69 63 65 6e 73 65 3a 20  lkamp..License: 
01e0: 4d 49 54 20 28 73 65 65 20 4c 49 43 45 4e 53 45  MIT (see LICENSE
01f0: 20 66 6f 72 20 64 65 74 61 69 6c 73 29 0a 22 22   for details).""
0200: 22 0a 0a 66 72 6f 6d 20 5f 5f 66 75 74 75 72 65  "..from __future
0210: 5f 5f 20 69 6d 70 6f 72 74 20 77 69 74 68 5f 73  __ import with_s
0220: 74 61 74 65 6d 65 6e 74 0a 0a 5f 5f 61 75 74 68  tatement..__auth
0230: 6f 72 5f 5f 20 3d 20 27 4d 61 72 63 65 6c 20 48  or__ = 'Marcel H
0240: 65 6c 6c 6b 61 6d 70 27 0a 5f 5f 76 65 72 73 69  ellkamp'.__versi
0250: 6f 6e 5f 5f 20 3d 20 27 30 2e 31 32 2e 31 33 27  on__ = '0.12.13'
0260: 0a 5f 5f 6c 69 63 65 6e 73 65 5f 5f 20 3d 20 27  .__license__ = '
0270: 4d 49 54 27 0a 0a 23 20 54 68 65 20 67 65 76 65  MIT'..# The geve
0280: 6e 74 20 73 65 72 76 65 72 20 61 64 61 70 74 65  nt server adapte
0290: 72 20 6e 65 65 64 73 20 74 6f 20 70 61 74 63 68  r needs to patch
02a0: 20 73 6f 6d 65 20 6d 6f 64 75 6c 65 73 20 62 65   some modules be
02b0: 66 6f 72 65 20 74 68 65 79 20 61 72 65 20 69 6d  fore they are im
02c0: 70 6f 72 74 65 64 0a 23 20 54 68 69 73 20 69 73  ported.# This is
02d0: 20 77 68 79 20 77 65 20 70 61 72 73 65 20 74 68   why we parse th
02e0: 65 20 63 6f 6d 6d 61 6e 64 6c 69 6e 65 20 70 61  e commandline pa
02f0: 72 61 6d 65 74 65 72 73 20 68 65 72 65 20 62 75  rameters here bu
0300: 74 20 68 61 6e 64 6c 65 20 74 68 65 6d 20 6c 61  t handle them la
0310: 74 65 72 0a 69 66 20 5f 5f 6e 61 6d 65 5f 5f 20  ter.if __name__ 
0320: 3d 3d 20 27 5f 5f 6d 61 69 6e 5f 5f 27 3a 0a 20  == '__main__':. 
0330: 20 20 20 66 72 6f 6d 20 6f 70 74 70 61 72 73 65     from optparse
0340: 20 69 6d 70 6f 72 74 20 4f 70 74 69 6f 6e 50 61   import OptionPa
0350: 72 73 65 72 0a 20 20 20 20 5f 63 6d 64 5f 70 61  rser.    _cmd_pa
0360: 72 73 65 72 20 3d 20 4f 70 74 69 6f 6e 50 61 72  rser = OptionPar
0370: 73 65 72 28 75 73 61 67 65 3d 22 75 73 61 67 65  ser(usage="usage
0380: 3a 20 25 70 72 6f 67 20 5b 6f 70 74 69 6f 6e 73  : %prog [options
0390: 5d 20 70 61 63 6b 61 67 65 2e 6d 6f 64 75 6c 65  ] package.module
03a0: 3a 61 70 70 22 29 0a 20 20 20 20 5f 6f 70 74 20  :app").    _opt 
03b0: 3d 20 5f 63 6d 64 5f 70 61 72 73 65 72 2e 61 64  = _cmd_parser.ad
03c0: 64 5f 6f 70 74 69 6f 6e 0a 20 20 20 20 5f 6f 70  d_option.    _op
03d0: 74 28 22 2d 2d 76 65 72 73 69 6f 6e 22 2c 20 61  t("--version", a
03e0: 63 74 69 6f 6e 3d 22 73 74 6f 72 65 5f 74 72 75  ction="store_tru
03f0: 65 22 2c 20 68 65 6c 70 3d 22 73 68 6f 77 20 76  e", help="show v
0400: 65 72 73 69 6f 6e 20 6e 75 6d 62 65 72 2e 22 29  ersion number.")
0410: 0a 20 20 20 20 5f 6f 70 74 28 22 2d 62 22 2c 20  .    _opt("-b", 
0420: 22 2d 2d 62 69 6e 64 22 2c 20 6d 65 74 61 76 61  "--bind", metava
0430: 72 3d 22 41 44 44 52 45 53 53 22 2c 20 68 65 6c  r="ADDRESS", hel
0440: 70 3d 22 62 69 6e 64 20 73 6f 63 6b 65 74 20 74  p="bind socket t
0450: 6f 20 41 44 44 52 45 53 53 2e 22 29 0a 20 20 20  o ADDRESS.").   
0460: 20 5f 6f 70 74 28 22 2d 73 22 2c 20 22 2d 2d 73   _opt("-s", "--s
0470: 65 72 76 65 72 22 2c 20 64 65 66 61 75 6c 74 3d  erver", default=
0480: 27 77 73 67 69 72 65 66 27 2c 20 68 65 6c 70 3d  'wsgiref', help=
0490: 22 75 73 65 20 53 45 52 56 45 52 20 61 73 20 62  "use SERVER as b
04a0: 61 63 6b 65 6e 64 2e 22 29 0a 20 20 20 20 5f 6f  ackend.").    _o
04b0: 70 74 28 22 2d 70 22 2c 20 22 2d 2d 70 6c 75 67  pt("-p", "--plug
04c0: 69 6e 22 2c 20 61 63 74 69 6f 6e 3d 22 61 70 70  in", action="app
04d0: 65 6e 64 22 2c 20 68 65 6c 70 3d 22 69 6e 73 74  end", help="inst
04e0: 61 6c 6c 20 61 64 64 69 74 69 6f 6e 61 6c 20 70  all additional p
04f0: 6c 75 67 69 6e 2f 73 2e 22 29 0a 20 20 20 20 5f  lugin/s.").    _
0500: 6f 70 74 28 22 2d 2d 64 65 62 75 67 22 2c 20 61  opt("--debug", a
0510: 63 74 69 6f 6e 3d 22 73 74 6f 72 65 5f 74 72 75  ction="store_tru
0520: 65 22 2c 20 68 65 6c 70 3d 22 73 74 61 72 74 20  e", help="start 
0530: 73 65 72 76 65 72 20 69 6e 20 64 65 62 75 67 20  server in debug 
0540: 6d 6f 64 65 2e 22 29 0a 20 20 20 20 5f 6f 70 74  mode.").    _opt
0550: 28 22 2d 2d 72 65 6c 6f 61 64 22 2c 20 61 63 74  ("--reload", act
0560: 69 6f 6e 3d 22 73 74 6f 72 65 5f 74 72 75 65 22  ion="store_true"
0570: 2c 20 68 65 6c 70 3d 22 61 75 74 6f 2d 72 65 6c  , help="auto-rel
0580: 6f 61 64 20 6f 6e 20 66 69 6c 65 20 63 68 61 6e  oad on file chan
0590: 67 65 73 2e 22 29 0a 20 20 20 20 5f 63 6d 64 5f  ges.").    _cmd_
05a0: 6f 70 74 69 6f 6e 73 2c 20 5f 63 6d 64 5f 61 72  options, _cmd_ar
05b0: 67 73 20 3d 20 5f 63 6d 64 5f 70 61 72 73 65 72  gs = _cmd_parser
05c0: 2e 70 61 72 73 65 5f 61 72 67 73 28 29 0a 20 20  .parse_args().  
05d0: 20 20 69 66 20 5f 63 6d 64 5f 6f 70 74 69 6f 6e    if _cmd_option
05e0: 73 2e 73 65 72 76 65 72 20 61 6e 64 20 5f 63 6d  s.server and _cm
05f0: 64 5f 6f 70 74 69 6f 6e 73 2e 73 65 72 76 65 72  d_options.server
0600: 2e 73 74 61 72 74 73 77 69 74 68 28 27 67 65 76  .startswith('gev
0610: 65 6e 74 27 29 3a 0a 20 20 20 20 20 20 20 20 69  ent'):.        i
0620: 6d 70 6f 72 74 20 67 65 76 65 6e 74 2e 6d 6f 6e  mport gevent.mon
0630: 6b 65 79 3b 20 67 65 76 65 6e 74 2e 6d 6f 6e 6b  key; gevent.monk
0640: 65 79 2e 70 61 74 63 68 5f 61 6c 6c 28 29 0a 0a  ey.patch_all()..
0650: 69 6d 70 6f 72 74 20 62 61 73 65 36 34 2c 20 63  import base64, c
0660: 67 69 2c 20 65 6d 61 69 6c 2e 75 74 69 6c 73 2c  gi, email.utils,
0670: 20 66 75 6e 63 74 6f 6f 6c 73 2c 20 68 6d 61 63   functools, hmac
0680: 2c 20 69 6d 70 2c 20 69 74 65 72 74 6f 6f 6c 73  , imp, itertools
0690: 2c 20 6d 69 6d 65 74 79 70 65 73 2c 5c 0a 20 20  , mimetypes,\.  
06a0: 20 20 20 20 20 20 6f 73 2c 20 72 65 2c 20 73 75        os, re, su
06b0: 62 70 72 6f 63 65 73 73 2c 20 73 79 73 2c 20 74  bprocess, sys, t
06c0: 65 6d 70 66 69 6c 65 2c 20 74 68 72 65 61 64 69  empfile, threadi
06d0: 6e 67 2c 20 74 69 6d 65 2c 20 77 61 72 6e 69 6e  ng, time, warnin
06e0: 67 73 0a 0a 66 72 6f 6d 20 64 61 74 65 74 69 6d  gs..from datetim
06f0: 65 20 69 6d 70 6f 72 74 20 64 61 74 65 20 61 73  e import date as
0700: 20 64 61 74 65 64 61 74 65 2c 20 64 61 74 65 74   datedate, datet
0710: 69 6d 65 2c 20 74 69 6d 65 64 65 6c 74 61 0a 66  ime, timedelta.f
0720: 72 6f 6d 20 74 65 6d 70 66 69 6c 65 20 69 6d 70  rom tempfile imp
0730: 6f 72 74 20 54 65 6d 70 6f 72 61 72 79 46 69 6c  ort TemporaryFil
0740: 65 0a 66 72 6f 6d 20 74 72 61 63 65 62 61 63 6b  e.from traceback
0750: 20 69 6d 70 6f 72 74 20 66 6f 72 6d 61 74 5f 65   import format_e
0760: 78 63 2c 20 70 72 69 6e 74 5f 65 78 63 0a 66 72  xc, print_exc.fr
0770: 6f 6d 20 69 6e 73 70 65 63 74 20 69 6d 70 6f 72  om inspect impor
0780: 74 20 67 65 74 61 72 67 73 70 65 63 0a 66 72 6f  t getargspec.fro
0790: 6d 20 75 6e 69 63 6f 64 65 64 61 74 61 20 69 6d  m unicodedata im
07a0: 70 6f 72 74 20 6e 6f 72 6d 61 6c 69 7a 65 0a 0a  port normalize..
07b0: 0a 74 72 79 3a 20 66 72 6f 6d 20 73 69 6d 70 6c  .try: from simpl
07c0: 65 6a 73 6f 6e 20 69 6d 70 6f 72 74 20 64 75 6d  ejson import dum
07d0: 70 73 20 61 73 20 6a 73 6f 6e 5f 64 75 6d 70 73  ps as json_dumps
07e0: 2c 20 6c 6f 61 64 73 20 61 73 20 6a 73 6f 6e 5f  , loads as json_
07f0: 6c 64 73 0a 65 78 63 65 70 74 20 49 6d 70 6f 72  lds.except Impor
0800: 74 45 72 72 6f 72 3a 20 23 20 70 72 61 67 6d 61  tError: # pragma
0810: 3a 20 6e 6f 20 63 6f 76 65 72 0a 20 20 20 20 74  : no cover.    t
0820: 72 79 3a 20 66 72 6f 6d 20 6a 73 6f 6e 20 69 6d  ry: from json im
0830: 70 6f 72 74 20 64 75 6d 70 73 20 61 73 20 6a 73  port dumps as js
0840: 6f 6e 5f 64 75 6d 70 73 2c 20 6c 6f 61 64 73 20  on_dumps, loads 
0850: 61 73 20 6a 73 6f 6e 5f 6c 64 73 0a 20 20 20 20  as json_lds.    
0860: 65 78 63 65 70 74 20 49 6d 70 6f 72 74 45 72 72  except ImportErr
0870: 6f 72 3a 0a 20 20 20 20 20 20 20 20 74 72 79 3a  or:.        try:
0880: 20 66 72 6f 6d 20 64 6a 61 6e 67 6f 2e 75 74 69   from django.uti
0890: 6c 73 2e 73 69 6d 70 6c 65 6a 73 6f 6e 20 69 6d  ls.simplejson im
08a0: 70 6f 72 74 20 64 75 6d 70 73 20 61 73 20 6a 73  port dumps as js
08b0: 6f 6e 5f 64 75 6d 70 73 2c 20 6c 6f 61 64 73 20  on_dumps, loads 
08c0: 61 73 20 6a 73 6f 6e 5f 6c 64 73 0a 20 20 20 20  as json_lds.    
08d0: 20 20 20 20 65 78 63 65 70 74 20 49 6d 70 6f 72      except Impor
08e0: 74 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20  tError:.        
08f0: 20 20 20 20 64 65 66 20 6a 73 6f 6e 5f 64 75 6d      def json_dum
0900: 70 73 28 64 61 74 61 29 3a 0a 20 20 20 20 20 20  ps(data):.      
0910: 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65 20            raise 
0920: 49 6d 70 6f 72 74 45 72 72 6f 72 28 22 4a 53 4f  ImportError("JSO
0930: 4e 20 73 75 70 70 6f 72 74 20 72 65 71 75 69 72  N support requir
0940: 65 73 20 50 79 74 68 6f 6e 20 32 2e 36 20 6f 72  es Python 2.6 or
0950: 20 73 69 6d 70 6c 65 6a 73 6f 6e 2e 22 29 0a 20   simplejson."). 
0960: 20 20 20 20 20 20 20 20 20 20 20 6a 73 6f 6e 5f             json_
0970: 6c 64 73 20 3d 20 6a 73 6f 6e 5f 64 75 6d 70 73  lds = json_dumps
0980: 0a 0a 0a 0a 23 20 57 65 20 6e 6f 77 20 74 72 79  ....# We now try
0990: 20 74 6f 20 66 69 78 20 32 2e 35 2f 32 2e 36 2f   to fix 2.5/2.6/
09a0: 33 2e 31 2f 33 2e 32 20 69 6e 63 6f 6d 70 61 74  3.1/3.2 incompat
09b0: 69 62 69 6c 69 74 69 65 73 2e 0a 23 20 49 74 20  ibilities..# It 
09c0: 61 69 6e 27 74 20 70 72 65 74 74 79 20 62 75 74  ain't pretty but
09d0: 20 69 74 20 77 6f 72 6b 73 2e 2e 2e 20 53 6f 72   it works... Sor
09e0: 72 79 20 66 6f 72 20 74 68 65 20 6d 65 73 73 2e  ry for the mess.
09f0: 0a 0a 70 79 20 20 20 3d 20 73 79 73 2e 76 65 72  ..py   = sys.ver
0a00: 73 69 6f 6e 5f 69 6e 66 6f 0a 70 79 33 6b 20 3d  sion_info.py3k =
0a10: 20 70 79 20 3e 3d 20 28 33 2c 20 30 2c 20 30 29   py >= (3, 0, 0)
0a20: 0a 70 79 32 35 20 3d 20 70 79 20 3c 20 20 28 32  .py25 = py <  (2
0a30: 2c 20 36 2c 20 30 29 0a 70 79 33 31 20 3d 20 28  , 6, 0).py31 = (
0a40: 33 2c 20 31 2c 20 30 29 20 3c 3d 20 70 79 20 3c  3, 1, 0) <= py <
0a50: 20 28 33 2c 20 32 2c 20 30 29 0a 0a 23 20 57 6f   (3, 2, 0)..# Wo
0a60: 72 6b 61 72 6f 75 6e 64 20 66 6f 72 20 74 68 65  rkaround for the
0a70: 20 6d 69 73 73 69 6e 67 20 22 61 73 22 20 6b 65   missing "as" ke
0a80: 79 77 6f 72 64 20 69 6e 20 70 79 33 6b 2e 0a 64  yword in py3k..d
0a90: 65 66 20 5f 65 28 29 3a 20 72 65 74 75 72 6e 20  ef _e(): return 
0aa0: 73 79 73 2e 65 78 63 5f 69 6e 66 6f 28 29 5b 31  sys.exc_info()[1
0ab0: 5d 0a 0a 23 20 57 6f 72 6b 61 72 6f 75 6e 64 20  ]..# Workaround 
0ac0: 66 6f 72 20 74 68 65 20 22 70 72 69 6e 74 20 69  for the "print i
0ad0: 73 20 61 20 6b 65 79 77 6f 72 64 2f 66 75 6e 63  s a keyword/func
0ae0: 74 69 6f 6e 22 20 50 79 74 68 6f 6e 20 32 2f 33  tion" Python 2/3
0af0: 20 64 69 6c 65 6d 6d 61 0a 23 20 61 6e 64 20 61   dilemma.# and a
0b00: 20 66 61 6c 6c 62 61 63 6b 20 66 6f 72 20 6d 6f   fallback for mo
0b10: 64 5f 77 73 67 69 20 28 72 65 73 74 69 63 74 73  d_wsgi (resticts
0b20: 20 73 74 64 6f 75 74 2f 65 72 72 20 61 74 74 72   stdout/err attr
0b30: 69 62 75 74 65 20 61 63 63 65 73 73 29 0a 74 72  ibute access).tr
0b40: 79 3a 0a 20 20 20 20 5f 73 74 64 6f 75 74 2c 20  y:.    _stdout, 
0b50: 5f 73 74 64 65 72 72 20 3d 20 73 79 73 2e 73 74  _stderr = sys.st
0b60: 64 6f 75 74 2e 77 72 69 74 65 2c 20 73 79 73 2e  dout.write, sys.
0b70: 73 74 64 65 72 72 2e 77 72 69 74 65 0a 65 78 63  stderr.write.exc
0b80: 65 70 74 20 49 4f 45 72 72 6f 72 3a 0a 20 20 20  ept IOError:.   
0b90: 20 5f 73 74 64 6f 75 74 20 3d 20 6c 61 6d 62 64   _stdout = lambd
0ba0: 61 20 78 3a 20 73 79 73 2e 73 74 64 6f 75 74 2e  a x: sys.stdout.
0bb0: 77 72 69 74 65 28 78 29 0a 20 20 20 20 5f 73 74  write(x).    _st
0bc0: 64 65 72 72 20 3d 20 6c 61 6d 62 64 61 20 78 3a  derr = lambda x:
0bd0: 20 73 79 73 2e 73 74 64 65 72 72 2e 77 72 69 74   sys.stderr.writ
0be0: 65 28 78 29 0a 0a 23 20 4c 6f 74 73 20 6f 66 20  e(x)..# Lots of 
0bf0: 73 74 64 6c 69 62 20 61 6e 64 20 62 75 69 6c 74  stdlib and built
0c00: 69 6e 20 64 69 66 66 65 72 65 6e 63 65 73 2e 0a  in differences..
0c10: 69 66 20 70 79 33 6b 3a 0a 20 20 20 20 69 6d 70  if py3k:.    imp
0c20: 6f 72 74 20 68 74 74 70 2e 63 6c 69 65 6e 74 20  ort http.client 
0c30: 61 73 20 68 74 74 70 6c 69 62 0a 20 20 20 20 69  as httplib.    i
0c40: 6d 70 6f 72 74 20 5f 74 68 72 65 61 64 20 61 73  mport _thread as
0c50: 20 74 68 72 65 61 64 0a 20 20 20 20 66 72 6f 6d   thread.    from
0c60: 20 75 72 6c 6c 69 62 2e 70 61 72 73 65 20 69 6d   urllib.parse im
0c70: 70 6f 72 74 20 75 72 6c 6a 6f 69 6e 2c 20 53 70  port urljoin, Sp
0c80: 6c 69 74 52 65 73 75 6c 74 20 61 73 20 55 72 6c  litResult as Url
0c90: 53 70 6c 69 74 52 65 73 75 6c 74 0a 20 20 20 20  SplitResult.    
0ca0: 66 72 6f 6d 20 75 72 6c 6c 69 62 2e 70 61 72 73  from urllib.pars
0cb0: 65 20 69 6d 70 6f 72 74 20 75 72 6c 65 6e 63 6f  e import urlenco
0cc0: 64 65 2c 20 71 75 6f 74 65 20 61 73 20 75 72 6c  de, quote as url
0cd0: 71 75 6f 74 65 2c 20 75 6e 71 75 6f 74 65 20 61  quote, unquote a
0ce0: 73 20 75 72 6c 75 6e 71 75 6f 74 65 0a 20 20 20  s urlunquote.   
0cf0: 20 75 72 6c 75 6e 71 75 6f 74 65 20 3d 20 66 75   urlunquote = fu
0d00: 6e 63 74 6f 6f 6c 73 2e 70 61 72 74 69 61 6c 28  nctools.partial(
0d10: 75 72 6c 75 6e 71 75 6f 74 65 2c 20 65 6e 63 6f  urlunquote, enco
0d20: 64 69 6e 67 3d 27 6c 61 74 69 6e 31 27 29 0a 20  ding='latin1'). 
0d30: 20 20 20 66 72 6f 6d 20 68 74 74 70 2e 63 6f 6f     from http.coo
0d40: 6b 69 65 73 20 69 6d 70 6f 72 74 20 53 69 6d 70  kies import Simp
0d50: 6c 65 43 6f 6f 6b 69 65 0a 20 20 20 20 66 72 6f  leCookie.    fro
0d60: 6d 20 63 6f 6c 6c 65 63 74 69 6f 6e 73 20 69 6d  m collections im
0d70: 70 6f 72 74 20 4d 75 74 61 62 6c 65 4d 61 70 70  port MutableMapp
0d80: 69 6e 67 20 61 73 20 44 69 63 74 4d 69 78 69 6e  ing as DictMixin
0d90: 0a 20 20 20 20 69 6d 70 6f 72 74 20 70 69 63 6b  .    import pick
0da0: 6c 65 0a 20 20 20 20 66 72 6f 6d 20 69 6f 20 69  le.    from io i
0db0: 6d 70 6f 72 74 20 42 79 74 65 73 49 4f 0a 20 20  mport BytesIO.  
0dc0: 20 20 66 72 6f 6d 20 63 6f 6e 66 69 67 70 61 72    from configpar
0dd0: 73 65 72 20 69 6d 70 6f 72 74 20 43 6f 6e 66 69  ser import Confi
0de0: 67 50 61 72 73 65 72 0a 20 20 20 20 62 61 73 65  gParser.    base
0df0: 73 74 72 69 6e 67 20 3d 20 73 74 72 0a 20 20 20  string = str.   
0e00: 20 75 6e 69 63 6f 64 65 20 3d 20 73 74 72 0a 20   unicode = str. 
0e10: 20 20 20 6a 73 6f 6e 5f 6c 6f 61 64 73 20 3d 20     json_loads = 
0e20: 6c 61 6d 62 64 61 20 73 3a 20 6a 73 6f 6e 5f 6c  lambda s: json_l
0e30: 64 73 28 74 6f 75 6e 69 28 73 29 29 0a 20 20 20  ds(touni(s)).   
0e40: 20 63 61 6c 6c 61 62 6c 65 20 3d 20 6c 61 6d 62   callable = lamb
0e50: 64 61 20 78 3a 20 68 61 73 61 74 74 72 28 78 2c  da x: hasattr(x,
0e60: 20 27 5f 5f 63 61 6c 6c 5f 5f 27 29 0a 20 20 20   '__call__').   
0e70: 20 69 6d 61 70 20 3d 20 6d 61 70 0a 20 20 20 20   imap = map.    
0e80: 64 65 66 20 5f 72 61 69 73 65 28 2a 61 29 3a 20  def _raise(*a): 
0e90: 72 61 69 73 65 20 61 5b 30 5d 28 61 5b 31 5d 29  raise a[0](a[1])
0ea0: 2e 77 69 74 68 5f 74 72 61 63 65 62 61 63 6b 28  .with_traceback(
0eb0: 61 5b 32 5d 29 0a 65 6c 73 65 3a 20 23 20 32 2e  a[2]).else: # 2.
0ec0: 78 0a 20 20 20 20 69 6d 70 6f 72 74 20 68 74 74  x.    import htt
0ed0: 70 6c 69 62 0a 20 20 20 20 69 6d 70 6f 72 74 20  plib.    import 
0ee0: 74 68 72 65 61 64 0a 20 20 20 20 66 72 6f 6d 20  thread.    from 
0ef0: 75 72 6c 70 61 72 73 65 20 69 6d 70 6f 72 74 20  urlparse import 
0f00: 75 72 6c 6a 6f 69 6e 2c 20 53 70 6c 69 74 52 65  urljoin, SplitRe
0f10: 73 75 6c 74 20 61 73 20 55 72 6c 53 70 6c 69 74  sult as UrlSplit
0f20: 52 65 73 75 6c 74 0a 20 20 20 20 66 72 6f 6d 20  Result.    from 
0f30: 75 72 6c 6c 69 62 20 69 6d 70 6f 72 74 20 75 72  urllib import ur
0f40: 6c 65 6e 63 6f 64 65 2c 20 71 75 6f 74 65 20 61  lencode, quote a
0f50: 73 20 75 72 6c 71 75 6f 74 65 2c 20 75 6e 71 75  s urlquote, unqu
0f60: 6f 74 65 20 61 73 20 75 72 6c 75 6e 71 75 6f 74  ote as urlunquot
0f70: 65 0a 20 20 20 20 66 72 6f 6d 20 43 6f 6f 6b 69  e.    from Cooki
0f80: 65 20 69 6d 70 6f 72 74 20 53 69 6d 70 6c 65 43  e import SimpleC
0f90: 6f 6f 6b 69 65 0a 20 20 20 20 66 72 6f 6d 20 69  ookie.    from i
0fa0: 74 65 72 74 6f 6f 6c 73 20 69 6d 70 6f 72 74 20  tertools import 
0fb0: 69 6d 61 70 0a 20 20 20 20 69 6d 70 6f 72 74 20  imap.    import 
0fc0: 63 50 69 63 6b 6c 65 20 61 73 20 70 69 63 6b 6c  cPickle as pickl
0fd0: 65 0a 20 20 20 20 66 72 6f 6d 20 53 74 72 69 6e  e.    from Strin
0fe0: 67 49 4f 20 69 6d 70 6f 72 74 20 53 74 72 69 6e  gIO import Strin
0ff0: 67 49 4f 20 61 73 20 42 79 74 65 73 49 4f 0a 20  gIO as BytesIO. 
1000: 20 20 20 66 72 6f 6d 20 43 6f 6e 66 69 67 50 61     from ConfigPa
1010: 72 73 65 72 20 69 6d 70 6f 72 74 20 53 61 66 65  rser import Safe
1020: 43 6f 6e 66 69 67 50 61 72 73 65 72 20 61 73 20  ConfigParser as 
1030: 43 6f 6e 66 69 67 50 61 72 73 65 72 0a 20 20 20  ConfigParser.   
1040: 20 69 66 20 70 79 32 35 3a 0a 20 20 20 20 20 20   if py25:.      
1050: 20 20 6d 73 67 20 20 3d 20 22 50 79 74 68 6f 6e    msg  = "Python
1060: 20 32 2e 35 20 73 75 70 70 6f 72 74 20 6d 61 79   2.5 support may
1070: 20 62 65 20 64 72 6f 70 70 65 64 20 69 6e 20 66   be dropped in f
1080: 75 74 75 72 65 20 76 65 72 73 69 6f 6e 73 20 6f  uture versions o
1090: 66 20 42 6f 74 74 6c 65 2e 22 0a 20 20 20 20 20  f Bottle.".     
10a0: 20 20 20 77 61 72 6e 69 6e 67 73 2e 77 61 72 6e     warnings.warn
10b0: 28 6d 73 67 2c 20 44 65 70 72 65 63 61 74 69 6f  (msg, Deprecatio
10c0: 6e 57 61 72 6e 69 6e 67 29 0a 20 20 20 20 20 20  nWarning).      
10d0: 20 20 66 72 6f 6d 20 55 73 65 72 44 69 63 74 20    from UserDict 
10e0: 69 6d 70 6f 72 74 20 44 69 63 74 4d 69 78 69 6e  import DictMixin
10f0: 0a 20 20 20 20 20 20 20 20 64 65 66 20 6e 65 78  .        def nex
1100: 74 28 69 74 29 3a 20 72 65 74 75 72 6e 20 69 74  t(it): return it
1110: 2e 6e 65 78 74 28 29 0a 20 20 20 20 20 20 20 20  .next().        
1120: 62 79 74 65 73 20 3d 20 73 74 72 0a 20 20 20 20  bytes = str.    
1130: 65 6c 73 65 3a 20 23 20 32 2e 36 2c 20 32 2e 37  else: # 2.6, 2.7
1140: 0a 20 20 20 20 20 20 20 20 66 72 6f 6d 20 63 6f  .        from co
1150: 6c 6c 65 63 74 69 6f 6e 73 20 69 6d 70 6f 72 74  llections import
1160: 20 4d 75 74 61 62 6c 65 4d 61 70 70 69 6e 67 20   MutableMapping 
1170: 61 73 20 44 69 63 74 4d 69 78 69 6e 0a 20 20 20  as DictMixin.   
1180: 20 75 6e 69 63 6f 64 65 20 3d 20 75 6e 69 63 6f   unicode = unico
1190: 64 65 0a 20 20 20 20 6a 73 6f 6e 5f 6c 6f 61 64  de.    json_load
11a0: 73 20 3d 20 6a 73 6f 6e 5f 6c 64 73 0a 20 20 20  s = json_lds.   
11b0: 20 65 76 61 6c 28 63 6f 6d 70 69 6c 65 28 27 64   eval(compile('d
11c0: 65 66 20 5f 72 61 69 73 65 28 2a 61 29 3a 20 72  ef _raise(*a): r
11d0: 61 69 73 65 20 61 5b 30 5d 2c 20 61 5b 31 5d 2c  aise a[0], a[1],
11e0: 20 61 5b 32 5d 27 2c 20 27 3c 70 79 33 66 69 78   a[2]', '<py3fix
11f0: 3e 27 2c 20 27 65 78 65 63 27 29 29 0a 0a 23 20  >', 'exec'))..# 
1200: 53 6f 6d 65 20 68 65 6c 70 65 72 73 20 66 6f 72  Some helpers for
1210: 20 73 74 72 69 6e 67 2f 62 79 74 65 20 68 61 6e   string/byte han
1220: 64 6c 69 6e 67 0a 64 65 66 20 74 6f 62 28 73 2c  dling.def tob(s,
1230: 20 65 6e 63 3d 27 75 74 66 38 27 29 3a 0a 20 20   enc='utf8'):.  
1240: 20 20 72 65 74 75 72 6e 20 73 2e 65 6e 63 6f 64    return s.encod
1250: 65 28 65 6e 63 29 20 69 66 20 69 73 69 6e 73 74  e(enc) if isinst
1260: 61 6e 63 65 28 73 2c 20 75 6e 69 63 6f 64 65 29  ance(s, unicode)
1270: 20 65 6c 73 65 20 62 79 74 65 73 28 73 29 0a 64   else bytes(s).d
1280: 65 66 20 74 6f 75 6e 69 28 73 2c 20 65 6e 63 3d  ef touni(s, enc=
1290: 27 75 74 66 38 27 2c 20 65 72 72 3d 27 73 74 72  'utf8', err='str
12a0: 69 63 74 27 29 3a 0a 20 20 20 20 72 65 74 75 72  ict'):.    retur
12b0: 6e 20 73 2e 64 65 63 6f 64 65 28 65 6e 63 2c 20  n s.decode(enc, 
12c0: 65 72 72 29 20 69 66 20 69 73 69 6e 73 74 61 6e  err) if isinstan
12d0: 63 65 28 73 2c 20 62 79 74 65 73 29 20 65 6c 73  ce(s, bytes) els
12e0: 65 20 75 6e 69 63 6f 64 65 28 73 29 0a 74 6f 6e  e unicode(s).ton
12f0: 61 74 20 3d 20 74 6f 75 6e 69 20 69 66 20 70 79  at = touni if py
1300: 33 6b 20 65 6c 73 65 20 74 6f 62 0a 0a 23 20 33  3k else tob..# 3
1310: 2e 32 20 66 69 78 65 73 20 63 67 69 2e 46 69 65  .2 fixes cgi.Fie
1320: 6c 64 53 74 6f 72 61 67 65 20 74 6f 20 61 63 63  ldStorage to acc
1330: 65 70 74 20 62 79 74 65 73 20 28 77 68 69 63 68  ept bytes (which
1340: 20 6d 61 6b 65 73 20 61 20 6c 6f 74 20 6f 66 20   makes a lot of 
1350: 73 65 6e 73 65 29 2e 0a 23 20 33 2e 31 20 6e 65  sense)..# 3.1 ne
1360: 65 64 73 20 61 20 77 6f 72 6b 61 72 6f 75 6e 64  eds a workaround
1370: 2e 0a 69 66 20 70 79 33 31 3a 0a 20 20 20 20 66  ..if py31:.    f
1380: 72 6f 6d 20 69 6f 20 69 6d 70 6f 72 74 20 54 65  rom io import Te
1390: 78 74 49 4f 57 72 61 70 70 65 72 0a 20 20 20 20  xtIOWrapper.    
13a0: 63 6c 61 73 73 20 4e 43 54 65 78 74 49 4f 57 72  class NCTextIOWr
13b0: 61 70 70 65 72 28 54 65 78 74 49 4f 57 72 61 70  apper(TextIOWrap
13c0: 70 65 72 29 3a 0a 20 20 20 20 20 20 20 20 64 65  per):.        de
13d0: 66 20 63 6c 6f 73 65 28 73 65 6c 66 29 3a 20 70  f close(self): p
13e0: 61 73 73 20 23 20 4b 65 65 70 20 77 72 61 70 70  ass # Keep wrapp
13f0: 65 64 20 62 75 66 66 65 72 20 6f 70 65 6e 2e 0a  ed buffer open..
1400: 0a 0a 23 20 41 20 62 75 67 20 69 6e 20 66 75 6e  ..# A bug in fun
1410: 63 74 6f 6f 6c 73 20 63 61 75 73 65 73 20 69 74  ctools causes it
1420: 20 74 6f 20 62 72 65 61 6b 20 69 66 20 74 68 65   to break if the
1430: 20 77 72 61 70 70 65 72 20 69 73 20 61 6e 20 69   wrapper is an i
1440: 6e 73 74 61 6e 63 65 20 6d 65 74 68 6f 64 0a 64  nstance method.d
1450: 65 66 20 75 70 64 61 74 65 5f 77 72 61 70 70 65  ef update_wrappe
1460: 72 28 77 72 61 70 70 65 72 2c 20 77 72 61 70 70  r(wrapper, wrapp
1470: 65 64 2c 20 2a 61 2c 20 2a 2a 6b 61 29 3a 0a 20  ed, *a, **ka):. 
1480: 20 20 20 74 72 79 3a 20 66 75 6e 63 74 6f 6f 6c     try: functool
1490: 73 2e 75 70 64 61 74 65 5f 77 72 61 70 70 65 72  s.update_wrapper
14a0: 28 77 72 61 70 70 65 72 2c 20 77 72 61 70 70 65  (wrapper, wrappe
14b0: 64 2c 20 2a 61 2c 20 2a 2a 6b 61 29 0a 20 20 20  d, *a, **ka).   
14c0: 20 65 78 63 65 70 74 20 41 74 74 72 69 62 75 74   except Attribut
14d0: 65 45 72 72 6f 72 3a 20 70 61 73 73 0a 0a 0a 0a  eError: pass....
14e0: 23 20 54 68 65 73 65 20 68 65 6c 70 65 72 73 20  # These helpers 
14f0: 61 72 65 20 75 73 65 64 20 61 74 20 6d 6f 64 75  are used at modu
1500: 6c 65 20 6c 65 76 65 6c 20 61 6e 64 20 6e 65 65  le level and nee
1510: 64 20 74 6f 20 62 65 20 64 65 66 69 6e 65 64 20  d to be defined 
1520: 66 69 72 73 74 2e 0a 23 20 41 6e 64 20 79 65 73  first..# And yes
1530: 2c 20 49 20 6b 6e 6f 77 20 50 45 50 2d 38 2c 20  , I know PEP-8, 
1540: 62 75 74 20 73 6f 6d 65 74 69 6d 65 73 20 61 20  but sometimes a 
1550: 6c 6f 77 65 72 2d 63 61 73 65 20 63 6c 61 73 73  lower-case class
1560: 6e 61 6d 65 20 6d 61 6b 65 73 20 6d 6f 72 65 20  name makes more 
1570: 73 65 6e 73 65 2e 0a 0a 64 65 66 20 64 65 70 72  sense...def depr
1580: 28 6d 65 73 73 61 67 65 2c 20 68 61 72 64 3d 46  (message, hard=F
1590: 61 6c 73 65 29 3a 0a 20 20 20 20 77 61 72 6e 69  alse):.    warni
15a0: 6e 67 73 2e 77 61 72 6e 28 6d 65 73 73 61 67 65  ngs.warn(message
15b0: 2c 20 44 65 70 72 65 63 61 74 69 6f 6e 57 61 72  , DeprecationWar
15c0: 6e 69 6e 67 2c 20 73 74 61 63 6b 6c 65 76 65 6c  ning, stacklevel
15d0: 3d 33 29 0a 0a 64 65 66 20 6d 61 6b 65 6c 69 73  =3)..def makelis
15e0: 74 28 64 61 74 61 29 3a 20 23 20 54 68 69 73 20  t(data): # This 
15f0: 69 73 20 6a 75 73 74 20 74 6f 20 68 61 6e 64 79  is just to handy
1600: 0a 20 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e  .    if isinstan
1610: 63 65 28 64 61 74 61 2c 20 28 74 75 70 6c 65 2c  ce(data, (tuple,
1620: 20 6c 69 73 74 2c 20 73 65 74 2c 20 64 69 63 74   list, set, dict
1630: 29 29 3a 20 72 65 74 75 72 6e 20 6c 69 73 74 28  )): return list(
1640: 64 61 74 61 29 0a 20 20 20 20 65 6c 69 66 20 64  data).    elif d
1650: 61 74 61 3a 20 72 65 74 75 72 6e 20 5b 64 61 74  ata: return [dat
1660: 61 5d 0a 20 20 20 20 65 6c 73 65 3a 20 72 65 74  a].    else: ret
1670: 75 72 6e 20 5b 5d 0a 0a 0a 63 6c 61 73 73 20 44  urn []...class D
1680: 69 63 74 50 72 6f 70 65 72 74 79 28 6f 62 6a 65  ictProperty(obje
1690: 63 74 29 3a 0a 20 20 20 20 27 27 27 20 50 72 6f  ct):.    ''' Pro
16a0: 70 65 72 74 79 20 74 68 61 74 20 6d 61 70 73 20  perty that maps 
16b0: 74 6f 20 61 20 6b 65 79 20 69 6e 20 61 20 6c 6f  to a key in a lo
16c0: 63 61 6c 20 64 69 63 74 2d 6c 69 6b 65 20 61 74  cal dict-like at
16d0: 74 72 69 62 75 74 65 2e 20 27 27 27 0a 20 20 20  tribute. '''.   
16e0: 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 28 73 65   def __init__(se
16f0: 6c 66 2c 20 61 74 74 72 2c 20 6b 65 79 3d 4e 6f  lf, attr, key=No
1700: 6e 65 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d 46 61  ne, read_only=Fa
1710: 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20 73 65  lse):.        se
1720: 6c 66 2e 61 74 74 72 2c 20 73 65 6c 66 2e 6b 65  lf.attr, self.ke
1730: 79 2c 20 73 65 6c 66 2e 72 65 61 64 5f 6f 6e 6c  y, self.read_onl
1740: 79 20 3d 20 61 74 74 72 2c 20 6b 65 79 2c 20 72  y = attr, key, r
1750: 65 61 64 5f 6f 6e 6c 79 0a 0a 20 20 20 20 64 65  ead_only..    de
1760: 66 20 5f 5f 63 61 6c 6c 5f 5f 28 73 65 6c 66 2c  f __call__(self,
1770: 20 66 75 6e 63 29 3a 0a 20 20 20 20 20 20 20 20   func):.        
1780: 66 75 6e 63 74 6f 6f 6c 73 2e 75 70 64 61 74 65  functools.update
1790: 5f 77 72 61 70 70 65 72 28 73 65 6c 66 2c 20 66  _wrapper(self, f
17a0: 75 6e 63 2c 20 75 70 64 61 74 65 64 3d 5b 5d 29  unc, updated=[])
17b0: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 67 65  .        self.ge
17c0: 74 74 65 72 2c 20 73 65 6c 66 2e 6b 65 79 20 3d  tter, self.key =
17d0: 20 66 75 6e 63 2c 20 73 65 6c 66 2e 6b 65 79 20   func, self.key 
17e0: 6f 72 20 66 75 6e 63 2e 5f 5f 6e 61 6d 65 5f 5f  or func.__name__
17f0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
1800: 73 65 6c 66 0a 0a 20 20 20 20 64 65 66 20 5f 5f  self..    def __
1810: 67 65 74 5f 5f 28 73 65 6c 66 2c 20 6f 62 6a 2c  get__(self, obj,
1820: 20 63 6c 73 29 3a 0a 20 20 20 20 20 20 20 20 69   cls):.        i
1830: 66 20 6f 62 6a 20 69 73 20 4e 6f 6e 65 3a 20 72  f obj is None: r
1840: 65 74 75 72 6e 20 73 65 6c 66 0a 20 20 20 20 20  eturn self.     
1850: 20 20 20 6b 65 79 2c 20 73 74 6f 72 61 67 65 20     key, storage 
1860: 3d 20 73 65 6c 66 2e 6b 65 79 2c 20 67 65 74 61  = self.key, geta
1870: 74 74 72 28 6f 62 6a 2c 20 73 65 6c 66 2e 61 74  ttr(obj, self.at
1880: 74 72 29 0a 20 20 20 20 20 20 20 20 69 66 20 6b  tr).        if k
1890: 65 79 20 6e 6f 74 20 69 6e 20 73 74 6f 72 61 67  ey not in storag
18a0: 65 3a 20 73 74 6f 72 61 67 65 5b 6b 65 79 5d 20  e: storage[key] 
18b0: 3d 20 73 65 6c 66 2e 67 65 74 74 65 72 28 6f 62  = self.getter(ob
18c0: 6a 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  j).        retur
18d0: 6e 20 73 74 6f 72 61 67 65 5b 6b 65 79 5d 0a 0a  n storage[key]..
18e0: 20 20 20 20 64 65 66 20 5f 5f 73 65 74 5f 5f 28      def __set__(
18f0: 73 65 6c 66 2c 20 6f 62 6a 2c 20 76 61 6c 75 65  self, obj, value
1900: 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 73 65  ):.        if se
1910: 6c 66 2e 72 65 61 64 5f 6f 6e 6c 79 3a 20 72 61  lf.read_only: ra
1920: 69 73 65 20 41 74 74 72 69 62 75 74 65 45 72 72  ise AttributeErr
1930: 6f 72 28 22 52 65 61 64 2d 4f 6e 6c 79 20 70 72  or("Read-Only pr
1940: 6f 70 65 72 74 79 2e 22 29 0a 20 20 20 20 20 20  operty.").      
1950: 20 20 67 65 74 61 74 74 72 28 6f 62 6a 2c 20 73    getattr(obj, s
1960: 65 6c 66 2e 61 74 74 72 29 5b 73 65 6c 66 2e 6b  elf.attr)[self.k
1970: 65 79 5d 20 3d 20 76 61 6c 75 65 0a 0a 20 20 20  ey] = value..   
1980: 20 64 65 66 20 5f 5f 64 65 6c 65 74 65 5f 5f 28   def __delete__(
1990: 73 65 6c 66 2c 20 6f 62 6a 29 3a 0a 20 20 20 20  self, obj):.    
19a0: 20 20 20 20 69 66 20 73 65 6c 66 2e 72 65 61 64      if self.read
19b0: 5f 6f 6e 6c 79 3a 20 72 61 69 73 65 20 41 74 74  _only: raise Att
19c0: 72 69 62 75 74 65 45 72 72 6f 72 28 22 52 65 61  ributeError("Rea
19d0: 64 2d 4f 6e 6c 79 20 70 72 6f 70 65 72 74 79 2e  d-Only property.
19e0: 22 29 0a 20 20 20 20 20 20 20 20 64 65 6c 20 67  ").        del g
19f0: 65 74 61 74 74 72 28 6f 62 6a 2c 20 73 65 6c 66  etattr(obj, self
1a00: 2e 61 74 74 72 29 5b 73 65 6c 66 2e 6b 65 79 5d  .attr)[self.key]
1a10: 0a 0a 0a 63 6c 61 73 73 20 63 61 63 68 65 64 5f  ...class cached_
1a20: 70 72 6f 70 65 72 74 79 28 6f 62 6a 65 63 74 29  property(object)
1a30: 3a 0a 20 20 20 20 27 27 27 20 41 20 70 72 6f 70  :.    ''' A prop
1a40: 65 72 74 79 20 74 68 61 74 20 69 73 20 6f 6e 6c  erty that is onl
1a50: 79 20 63 6f 6d 70 75 74 65 64 20 6f 6e 63 65 20  y computed once 
1a60: 70 65 72 20 69 6e 73 74 61 6e 63 65 20 61 6e 64  per instance and
1a70: 20 74 68 65 6e 20 72 65 70 6c 61 63 65 73 0a 20   then replaces. 
1a80: 20 20 20 20 20 20 20 69 74 73 65 6c 66 20 77 69         itself wi
1a90: 74 68 20 61 6e 20 6f 72 64 69 6e 61 72 79 20 61  th an ordinary a
1aa0: 74 74 72 69 62 75 74 65 2e 20 44 65 6c 65 74 69  ttribute. Deleti
1ab0: 6e 67 20 74 68 65 20 61 74 74 72 69 62 75 74 65  ng the attribute
1ac0: 20 72 65 73 65 74 73 20 74 68 65 0a 20 20 20 20   resets the.    
1ad0: 20 20 20 20 70 72 6f 70 65 72 74 79 2e 20 27 27      property. ''
1ae0: 27 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e 69  '..    def __ini
1af0: 74 5f 5f 28 73 65 6c 66 2c 20 66 75 6e 63 29 3a  t__(self, func):
1b00: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 5f  .        self.__
1b10: 64 6f 63 5f 5f 20 3d 20 67 65 74 61 74 74 72 28  doc__ = getattr(
1b20: 66 75 6e 63 2c 20 27 5f 5f 64 6f 63 5f 5f 27 29  func, '__doc__')
1b30: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 66 75  .        self.fu
1b40: 6e 63 20 3d 20 66 75 6e 63 0a 0a 20 20 20 20 64  nc = func..    d
1b50: 65 66 20 5f 5f 67 65 74 5f 5f 28 73 65 6c 66 2c  ef __get__(self,
1b60: 20 6f 62 6a 2c 20 63 6c 73 29 3a 0a 20 20 20 20   obj, cls):.    
1b70: 20 20 20 20 69 66 20 6f 62 6a 20 69 73 20 4e 6f      if obj is No
1b80: 6e 65 3a 20 72 65 74 75 72 6e 20 73 65 6c 66 0a  ne: return self.
1b90: 20 20 20 20 20 20 20 20 76 61 6c 75 65 20 3d 20          value = 
1ba0: 6f 62 6a 2e 5f 5f 64 69 63 74 5f 5f 5b 73 65 6c  obj.__dict__[sel
1bb0: 66 2e 66 75 6e 63 2e 5f 5f 6e 61 6d 65 5f 5f 5d  f.func.__name__]
1bc0: 20 3d 20 73 65 6c 66 2e 66 75 6e 63 28 6f 62 6a   = self.func(obj
1bd0: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
1be0: 20 76 61 6c 75 65 0a 0a 0a 63 6c 61 73 73 20 6c   value...class l
1bf0: 61 7a 79 5f 61 74 74 72 69 62 75 74 65 28 6f 62  azy_attribute(ob
1c00: 6a 65 63 74 29 3a 0a 20 20 20 20 27 27 27 20 41  ject):.    ''' A
1c10: 20 70 72 6f 70 65 72 74 79 20 74 68 61 74 20 63   property that c
1c20: 61 63 68 65 73 20 69 74 73 65 6c 66 20 74 6f 20  aches itself to 
1c30: 74 68 65 20 63 6c 61 73 73 20 6f 62 6a 65 63 74  the class object
1c40: 2e 20 27 27 27 0a 20 20 20 20 64 65 66 20 5f 5f  . '''.    def __
1c50: 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 66 75 6e  init__(self, fun
1c60: 63 29 3a 0a 20 20 20 20 20 20 20 20 66 75 6e 63  c):.        func
1c70: 74 6f 6f 6c 73 2e 75 70 64 61 74 65 5f 77 72 61  tools.update_wra
1c80: 70 70 65 72 28 73 65 6c 66 2c 20 66 75 6e 63 2c  pper(self, func,
1c90: 20 75 70 64 61 74 65 64 3d 5b 5d 29 0a 20 20 20   updated=[]).   
1ca0: 20 20 20 20 20 73 65 6c 66 2e 67 65 74 74 65 72       self.getter
1cb0: 20 3d 20 66 75 6e 63 0a 0a 20 20 20 20 64 65 66   = func..    def
1cc0: 20 5f 5f 67 65 74 5f 5f 28 73 65 6c 66 2c 20 6f   __get__(self, o
1cd0: 62 6a 2c 20 63 6c 73 29 3a 0a 20 20 20 20 20 20  bj, cls):.      
1ce0: 20 20 76 61 6c 75 65 20 3d 20 73 65 6c 66 2e 67    value = self.g
1cf0: 65 74 74 65 72 28 63 6c 73 29 0a 20 20 20 20 20  etter(cls).     
1d00: 20 20 20 73 65 74 61 74 74 72 28 63 6c 73 2c 20     setattr(cls, 
1d10: 73 65 6c 66 2e 5f 5f 6e 61 6d 65 5f 5f 2c 20 76  self.__name__, v
1d20: 61 6c 75 65 29 0a 20 20 20 20 20 20 20 20 72 65  alue).        re
1d30: 74 75 72 6e 20 76 61 6c 75 65 0a 0a 0a 0a 0a 0a  turn value......
1d40: 0a 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  .###############
1d50: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d60: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d70: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d80: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d90: 0a 23 20 45 78 63 65 70 74 69 6f 6e 73 20 61 6e  .# Exceptions an
1da0: 64 20 45 76 65 6e 74 73 20 23 23 23 23 23 23 23  d Events #######
1db0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1dc0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1dd0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1de0: 23 0a 23 23 23 23 23 23 23 23 23 23 23 23 23 23  #.##############
1df0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1e00: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1e10: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1e20: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1e30: 23 0a 0a 0a 63 6c 61 73 73 20 42 6f 74 74 6c 65  #...class Bottle
1e40: 45 78 63 65 70 74 69 6f 6e 28 45 78 63 65 70 74  Exception(Except
1e50: 69 6f 6e 29 3a 0a 20 20 20 20 22 22 22 20 41 20  ion):.    """ A 
1e60: 62 61 73 65 20 63 6c 61 73 73 20 66 6f 72 20 65  base class for e
1e70: 78 63 65 70 74 69 6f 6e 73 20 75 73 65 64 20 62  xceptions used b
1e80: 79 20 62 6f 74 74 6c 65 2e 20 22 22 22 0a 20 20  y bottle. """.  
1e90: 20 20 70 61 73 73 0a 0a 0a 0a 0a 0a 0a 23 23 23    pass.......###
1ea0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1eb0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ec0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ee0: 23 23 23 23 23 23 23 23 23 23 23 23 0a 23 20 52  ############.# R
1ef0: 6f 75 74 69 6e 67 20 23 23 23 23 23 23 23 23 23  outing #########
1f00: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f10: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f20: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f30: 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 23 23  #############.##
1f40: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f50: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f60: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f70: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1f80: 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 0a 0a  #############...
1f90: 63 6c 61 73 73 20 52 6f 75 74 65 45 72 72 6f 72  class RouteError
1fa0: 28 42 6f 74 74 6c 65 45 78 63 65 70 74 69 6f 6e  (BottleException
1fb0: 29 3a 0a 20 20 20 20 22 22 22 20 54 68 69 73 20  ):.    """ This 
1fc0: 69 73 20 61 20 62 61 73 65 20 63 6c 61 73 73 20  is a base class 
1fd0: 66 6f 72 20 61 6c 6c 20 72 6f 75 74 69 6e 67 20  for all routing 
1fe0: 72 65 6c 61 74 65 64 20 65 78 63 65 70 74 69 6f  related exceptio
1ff0: 6e 73 20 22 22 22 0a 0a 0a 63 6c 61 73 73 20 52  ns """...class R
2000: 6f 75 74 65 52 65 73 65 74 28 42 6f 74 74 6c 65  outeReset(Bottle
2010: 45 78 63 65 70 74 69 6f 6e 29 3a 0a 20 20 20 20  Exception):.    
2020: 22 22 22 20 49 66 20 72 61 69 73 65 64 20 62 79  """ If raised by
2030: 20 61 20 70 6c 75 67 69 6e 20 6f 72 20 72 65 71   a plugin or req
2040: 75 65 73 74 20 68 61 6e 64 6c 65 72 2c 20 74 68  uest handler, th
2050: 65 20 72 6f 75 74 65 20 69 73 20 72 65 73 65 74  e route is reset
2060: 20 61 6e 64 20 61 6c 6c 0a 20 20 20 20 20 20 20   and all.       
2070: 20 70 6c 75 67 69 6e 73 20 61 72 65 20 72 65 2d   plugins are re-
2080: 61 70 70 6c 69 65 64 2e 20 22 22 22 0a 0a 63 6c  applied. """..cl
2090: 61 73 73 20 52 6f 75 74 65 72 55 6e 6b 6e 6f 77  ass RouterUnknow
20a0: 6e 4d 6f 64 65 45 72 72 6f 72 28 52 6f 75 74 65  nModeError(Route
20b0: 45 72 72 6f 72 29 3a 20 70 61 73 73 0a 0a 0a 63  Error): pass...c
20c0: 6c 61 73 73 20 52 6f 75 74 65 53 79 6e 74 61 78  lass RouteSyntax
20d0: 45 72 72 6f 72 28 52 6f 75 74 65 45 72 72 6f 72  Error(RouteError
20e0: 29 3a 0a 20 20 20 20 22 22 22 20 54 68 65 20 72  ):.    """ The r
20f0: 6f 75 74 65 20 70 61 72 73 65 72 20 66 6f 75 6e  oute parser foun
2100: 64 20 73 6f 6d 65 74 68 69 6e 67 20 6e 6f 74 20  d something not 
2110: 73 75 70 70 6f 72 74 65 64 20 62 79 20 74 68 69  supported by thi
2120: 73 20 72 6f 75 74 65 72 2e 20 22 22 22 0a 0a 0a  s router. """...
2130: 63 6c 61 73 73 20 52 6f 75 74 65 42 75 69 6c 64  class RouteBuild
2140: 45 72 72 6f 72 28 52 6f 75 74 65 45 72 72 6f 72  Error(RouteError
2150: 29 3a 0a 20 20 20 20 22 22 22 20 54 68 65 20 72  ):.    """ The r
2160: 6f 75 74 65 20 63 6f 75 6c 64 20 6e 6f 74 20 62  oute could not b
2170: 65 20 62 75 69 6c 74 2e 20 22 22 22 0a 0a 0a 64  e built. """...d
2180: 65 66 20 5f 72 65 5f 66 6c 61 74 74 65 6e 28 70  ef _re_flatten(p
2190: 29 3a 0a 20 20 20 20 27 27 27 20 54 75 72 6e 20  ):.    ''' Turn 
21a0: 61 6c 6c 20 63 61 70 74 75 72 69 6e 67 20 67 72  all capturing gr
21b0: 6f 75 70 73 20 69 6e 20 61 20 72 65 67 75 6c 61  oups in a regula
21c0: 72 20 65 78 70 72 65 73 73 69 6f 6e 20 70 61 74  r expression pat
21d0: 74 65 72 6e 20 69 6e 74 6f 0a 20 20 20 20 20 20  tern into.      
21e0: 20 20 6e 6f 6e 2d 63 61 70 74 75 72 69 6e 67 20    non-capturing 
21f0: 67 72 6f 75 70 73 2e 20 27 27 27 0a 20 20 20 20  groups. '''.    
2200: 69 66 20 27 28 27 20 6e 6f 74 20 69 6e 20 70 3a  if '(' not in p:
2210: 20 72 65 74 75 72 6e 20 70 0a 20 20 20 20 72 65   return p.    re
2220: 74 75 72 6e 20 72 65 2e 73 75 62 28 72 27 28 5c  turn re.sub(r'(\
2230: 5c 2a 29 28 5c 28 5c 3f 50 3c 5b 5e 3e 5d 2b 3e  \*)(\(\?P<[^>]+>
2240: 7c 5c 28 28 3f 21 5c 3f 29 29 27 2c 0a 20 20 20  |\((?!\?))',.   
2250: 20 20 20 20 20 6c 61 6d 62 64 61 20 6d 3a 20 6d       lambda m: m
2260: 2e 67 72 6f 75 70 28 30 29 20 69 66 20 6c 65 6e  .group(0) if len
2270: 28 6d 2e 67 72 6f 75 70 28 31 29 29 20 25 20 32  (m.group(1)) % 2
2280: 20 65 6c 73 65 20 6d 2e 67 72 6f 75 70 28 31 29   else m.group(1)
2290: 20 2b 20 27 28 3f 3a 27 2c 20 70 29 0a 0a 0a 63   + '(?:', p)...c
22a0: 6c 61 73 73 20 52 6f 75 74 65 72 28 6f 62 6a 65  lass Router(obje
22b0: 63 74 29 3a 0a 20 20 20 20 27 27 27 20 41 20 52  ct):.    ''' A R
22c0: 6f 75 74 65 72 20 69 73 20 61 6e 20 6f 72 64 65  outer is an orde
22d0: 72 65 64 20 63 6f 6c 6c 65 63 74 69 6f 6e 20 6f  red collection o
22e0: 66 20 72 6f 75 74 65 2d 3e 74 61 72 67 65 74 20  f route->target 
22f0: 70 61 69 72 73 2e 20 49 74 20 69 73 20 75 73 65  pairs. It is use
2300: 64 20 74 6f 0a 20 20 20 20 20 20 20 20 65 66 66  d to.        eff
2310: 69 63 69 65 6e 74 6c 79 20 6d 61 74 63 68 20 57  iciently match W
2320: 53 47 49 20 72 65 71 75 65 73 74 73 20 61 67 61  SGI requests aga
2330: 69 6e 73 74 20 61 20 6e 75 6d 62 65 72 20 6f 66  inst a number of
2340: 20 72 6f 75 74 65 73 20 61 6e 64 20 72 65 74 75   routes and retu
2350: 72 6e 0a 20 20 20 20 20 20 20 20 74 68 65 20 66  rn.        the f
2360: 69 72 73 74 20 74 61 72 67 65 74 20 74 68 61 74  irst target that
2370: 20 73 61 74 69 73 66 69 65 73 20 74 68 65 20 72   satisfies the r
2380: 65 71 75 65 73 74 2e 20 54 68 65 20 74 61 72 67  equest. The targ
2390: 65 74 20 6d 61 79 20 62 65 20 61 6e 79 74 68 69  et may be anythi
23a0: 6e 67 2c 0a 20 20 20 20 20 20 20 20 75 73 75 61  ng,.        usua
23b0: 6c 6c 79 20 61 20 73 74 72 69 6e 67 2c 20 49 44  lly a string, ID
23c0: 20 6f 72 20 63 61 6c 6c 61 62 6c 65 20 6f 62 6a   or callable obj
23d0: 65 63 74 2e 20 41 20 72 6f 75 74 65 20 63 6f 6e  ect. A route con
23e0: 73 69 73 74 73 20 6f 66 20 61 20 70 61 74 68 2d  sists of a path-
23f0: 72 75 6c 65 0a 20 20 20 20 20 20 20 20 61 6e 64  rule.        and
2400: 20 61 20 48 54 54 50 20 6d 65 74 68 6f 64 2e 0a   a HTTP method..
2410: 0a 20 20 20 20 20 20 20 20 54 68 65 20 70 61 74  .        The pat
2420: 68 2d 72 75 6c 65 20 69 73 20 65 69 74 68 65 72  h-rule is either
2430: 20 61 20 73 74 61 74 69 63 20 70 61 74 68 20 28   a static path (
2440: 65 2e 67 2e 20 60 2f 63 6f 6e 74 61 63 74 60 29  e.g. `/contact`)
2450: 20 6f 72 20 61 20 64 79 6e 61 6d 69 63 0a 20 20   or a dynamic.  
2460: 20 20 20 20 20 20 70 61 74 68 20 74 68 61 74 20        path that 
2470: 63 6f 6e 74 61 69 6e 73 20 77 69 6c 64 63 61 72  contains wildcar
2480: 64 73 20 28 65 2e 67 2e 20 60 2f 77 69 6b 69 2f  ds (e.g. `/wiki/
2490: 3c 70 61 67 65 3e 60 29 2e 20 54 68 65 20 77 69  <page>`). The wi
24a0: 6c 64 63 61 72 64 20 73 79 6e 74 61 78 0a 20 20  ldcard syntax.  
24b0: 20 20 20 20 20 20 61 6e 64 20 64 65 74 61 69 6c        and detail
24c0: 73 20 6f 6e 20 74 68 65 20 6d 61 74 63 68 69 6e  s on the matchin
24d0: 67 20 6f 72 64 65 72 20 61 72 65 20 64 65 73 63  g order are desc
24e0: 72 69 62 65 64 20 69 6e 20 64 6f 63 73 3a 60 72  ribed in docs:`r
24f0: 6f 75 74 69 6e 67 60 2e 0a 20 20 20 20 27 27 27  outing`..    '''
2500: 0a 0a 20 20 20 20 64 65 66 61 75 6c 74 5f 70 61  ..    default_pa
2510: 74 74 65 72 6e 20 3d 20 27 5b 5e 2f 5d 2b 27 0a  ttern = '[^/]+'.
2520: 20 20 20 20 64 65 66 61 75 6c 74 5f 66 69 6c 74      default_filt
2530: 65 72 20 20 3d 20 27 72 65 27 0a 0a 20 20 20 20  er  = 're'..    
2540: 23 3a 20 54 68 65 20 63 75 72 72 65 6e 74 20 43  #: The current C
2550: 50 79 74 68 6f 6e 20 72 65 67 65 78 70 20 69 6d  Python regexp im
2560: 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 20 64 6f 65  plementation doe
2570: 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 6d 6f 72 65  s not allow more
2580: 0a 20 20 20 20 23 3a 20 74 68 61 6e 20 39 39 20  .    #: than 99 
2590: 6d 61 74 63 68 69 6e 67 20 67 72 6f 75 70 73 20  matching groups 
25a0: 70 65 72 20 72 65 67 75 6c 61 72 20 65 78 70 72  per regular expr
25b0: 65 73 73 69 6f 6e 2e 0a 20 20 20 20 5f 4d 41 58  ession..    _MAX
25c0: 5f 47 52 4f 55 50 53 5f 50 45 52 5f 50 41 54 54  _GROUPS_PER_PATT
25d0: 45 52 4e 20 3d 20 39 39 0a 0a 20 20 20 20 64 65  ERN = 99..    de
25e0: 66 20 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c  f __init__(self,
25f0: 20 73 74 72 69 63 74 3d 46 61 6c 73 65 29 3a 0a   strict=False):.
2600: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 72 75 6c          self.rul
2610: 65 73 20 20 20 20 3d 20 5b 5d 20 23 20 41 6c 6c  es    = [] # All
2620: 20 72 75 6c 65 73 20 69 6e 20 6f 72 64 65 72 0a   rules in order.
2630: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 67 72          self._gr
2640: 6f 75 70 73 20 20 3d 20 7b 7d 20 23 20 69 6e 64  oups  = {} # ind
2650: 65 78 20 6f 66 20 72 65 67 65 78 65 73 20 74 6f  ex of regexes to
2660: 20 66 69 6e 64 20 74 68 65 6d 20 69 6e 20 64 79   find them in dy
2670: 6e 61 5f 72 6f 75 74 65 73 0a 20 20 20 20 20 20  na_routes.      
2680: 20 20 73 65 6c 66 2e 62 75 69 6c 64 65 72 20 20    self.builder  
2690: 3d 20 7b 7d 20 23 20 44 61 74 61 20 73 74 72 75  = {} # Data stru
26a0: 63 74 75 72 65 20 66 6f 72 20 74 68 65 20 75 72  cture for the ur
26b0: 6c 20 62 75 69 6c 64 65 72 0a 20 20 20 20 20 20  l builder.      
26c0: 20 20 73 65 6c 66 2e 73 74 61 74 69 63 20 20 20    self.static   
26d0: 3d 20 7b 7d 20 23 20 53 65 61 72 63 68 20 73 74  = {} # Search st
26e0: 72 75 63 74 75 72 65 20 66 6f 72 20 73 74 61 74  ructure for stat
26f0: 69 63 20 72 6f 75 74 65 73 0a 20 20 20 20 20 20  ic routes.      
2700: 20 20 73 65 6c 66 2e 64 79 6e 61 5f 72 6f 75 74    self.dyna_rout
2710: 65 73 20 20 20 3d 20 7b 7d 0a 20 20 20 20 20 20  es   = {}.      
2720: 20 20 73 65 6c 66 2e 64 79 6e 61 5f 72 65 67 65    self.dyna_rege
2730: 78 65 73 20 20 3d 20 7b 7d 20 23 20 53 65 61 72  xes  = {} # Sear
2740: 63 68 20 73 74 72 75 63 74 75 72 65 20 66 6f 72  ch structure for
2750: 20 64 79 6e 61 6d 69 63 20 72 6f 75 74 65 73 0a   dynamic routes.
2760: 20 20 20 20 20 20 20 20 23 3a 20 49 66 20 74 72          #: If tr
2770: 75 65 2c 20 73 74 61 74 69 63 20 72 6f 75 74 65  ue, static route
2780: 73 20 61 72 65 20 6e 6f 20 6c 6f 6e 67 65 72 20  s are no longer 
2790: 63 68 65 63 6b 65 64 20 66 69 72 73 74 2e 0a 20  checked first.. 
27a0: 20 20 20 20 20 20 20 73 65 6c 66 2e 73 74 72 69         self.stri
27b0: 63 74 5f 6f 72 64 65 72 20 3d 20 73 74 72 69 63  ct_order = stric
27c0: 74 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 66  t.        self.f
27d0: 69 6c 74 65 72 73 20 3d 20 7b 0a 20 20 20 20 20  ilters = {.     
27e0: 20 20 20 20 20 20 20 27 72 65 27 3a 20 20 20 20         're':    
27f0: 6c 61 6d 62 64 61 20 63 6f 6e 66 3a 0a 20 20 20  lambda conf:.   
2800: 20 20 20 20 20 20 20 20 20 20 20 20 20 28 5f 72               (_r
2810: 65 5f 66 6c 61 74 74 65 6e 28 63 6f 6e 66 20 6f  e_flatten(conf o
2820: 72 20 73 65 6c 66 2e 64 65 66 61 75 6c 74 5f 70  r self.default_p
2830: 61 74 74 65 72 6e 29 2c 20 4e 6f 6e 65 2c 20 4e  attern), None, N
2840: 6f 6e 65 29 2c 0a 20 20 20 20 20 20 20 20 20 20  one),.          
2850: 20 20 27 69 6e 74 27 3a 20 20 20 6c 61 6d 62 64    'int':   lambd
2860: 61 20 63 6f 6e 66 3a 20 28 72 27 2d 3f 5c 64 2b  a conf: (r'-?\d+
2870: 27 2c 20 69 6e 74 2c 20 6c 61 6d 62 64 61 20 78  ', int, lambda x
2880: 3a 20 73 74 72 28 69 6e 74 28 78 29 29 29 2c 0a  : str(int(x))),.
2890: 20 20 20 20 20 20 20 20 20 20 20 20 27 66 6c 6f              'flo
28a0: 61 74 27 3a 20 6c 61 6d 62 64 61 20 63 6f 6e 66  at': lambda conf
28b0: 3a 20 28 72 27 2d 3f 5b 5c 64 2e 5d 2b 27 2c 20  : (r'-?[\d.]+', 
28c0: 66 6c 6f 61 74 2c 20 6c 61 6d 62 64 61 20 78 3a  float, lambda x:
28d0: 20 73 74 72 28 66 6c 6f 61 74 28 78 29 29 29 2c   str(float(x))),
28e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 27 70 61  .            'pa
28f0: 74 68 27 3a 20 20 6c 61 6d 62 64 61 20 63 6f 6e  th':  lambda con
2900: 66 3a 20 28 72 27 2e 2b 3f 27 2c 20 4e 6f 6e 65  f: (r'.+?', None
2910: 2c 20 4e 6f 6e 65 29 7d 0a 0a 20 20 20 20 64 65  , None)}..    de
2920: 66 20 61 64 64 5f 66 69 6c 74 65 72 28 73 65 6c  f add_filter(sel
2930: 66 2c 20 6e 61 6d 65 2c 20 66 75 6e 63 29 3a 0a  f, name, func):.
2940: 20 20 20 20 20 20 20 20 27 27 27 20 41 64 64 20          ''' Add 
2950: 61 20 66 69 6c 74 65 72 2e 20 54 68 65 20 70 72  a filter. The pr
2960: 6f 76 69 64 65 64 20 66 75 6e 63 74 69 6f 6e 20  ovided function 
2970: 69 73 20 63 61 6c 6c 65 64 20 77 69 74 68 20 74  is called with t
2980: 68 65 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e  he configuration
2990: 0a 20 20 20 20 20 20 20 20 73 74 72 69 6e 67 20  .        string 
29a0: 61 73 20 70 61 72 61 6d 65 74 65 72 20 61 6e 64  as parameter and
29b0: 20 6d 75 73 74 20 72 65 74 75 72 6e 20 61 20 28   must return a (
29c0: 72 65 67 65 78 70 2c 20 74 6f 5f 70 79 74 68 6f  regexp, to_pytho
29d0: 6e 2c 20 74 6f 5f 75 72 6c 29 20 74 75 70 6c 65  n, to_url) tuple
29e0: 2e 0a 20 20 20 20 20 20 20 20 54 68 65 20 66 69  ..        The fi
29f0: 72 73 74 20 65 6c 65 6d 65 6e 74 20 69 73 20 61  rst element is a
2a00: 20 73 74 72 69 6e 67 2c 20 74 68 65 20 6c 61 73   string, the las
2a10: 74 20 74 77 6f 20 61 72 65 20 63 61 6c 6c 61 62  t two are callab
2a20: 6c 65 73 20 6f 72 20 4e 6f 6e 65 2e 20 27 27 27  les or None. '''
2a30: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 66 69  .        self.fi
2a40: 6c 74 65 72 73 5b 6e 61 6d 65 5d 20 3d 20 66 75  lters[name] = fu
2a50: 6e 63 0a 0a 20 20 20 20 72 75 6c 65 5f 73 79 6e  nc..    rule_syn
2a60: 74 61 78 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  tax = re.compile
2a70: 28 27 28 5c 5c 5c 5c 2a 29 27 5c 0a 20 20 20 20  ('(\\\\*)'\.    
2a80: 20 20 20 20 27 28 3f 3a 28 3f 3a 3a 28 5b 61 2d      '(?:(?::([a-
2a90: 7a 41 2d 5a 5f 5d 5b 61 2d 7a 41 2d 5a 5f 30 2d  zA-Z_][a-zA-Z_0-
2aa0: 39 5d 2a 29 3f 28 29 28 3f 3a 23 28 2e 2a 3f 29  9]*)?()(?:#(.*?)
2ab0: 23 29 3f 29 27 5c 0a 20 20 20 20 20 20 20 20 20  #)?)'\.         
2ac0: 20 27 7c 28 3f 3a 3c 28 5b 61 2d 7a 41 2d 5a 5f   '|(?:<([a-zA-Z_
2ad0: 5d 5b 61 2d 7a 41 2d 5a 5f 30 2d 39 5d 2a 29 3f  ][a-zA-Z_0-9]*)?
2ae0: 28 3f 3a 3a 28 5b 61 2d 7a 41 2d 5a 5f 5d 2a 29  (?::([a-zA-Z_]*)
2af0: 27 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 27  '\.            '
2b00: 28 3f 3a 3a 28 28 3f 3a 5c 5c 5c 5c 2e 7c 5b 5e  (?::((?:\\\\.|[^
2b10: 5c 5c 5c 5c 3e 5d 2b 29 2b 29 3f 29 3f 29 3f 3e  \\\\>]+)+)?)?)?>
2b20: 29 29 27 29 0a 0a 20 20 20 20 64 65 66 20 5f 69  ))')..    def _i
2b30: 74 65 72 74 6f 6b 65 6e 73 28 73 65 6c 66 2c 20  tertokens(self, 
2b40: 72 75 6c 65 29 3a 0a 20 20 20 20 20 20 20 20 6f  rule):.        o
2b50: 66 66 73 65 74 2c 20 70 72 65 66 69 78 20 3d 20  ffset, prefix = 
2b60: 30 2c 20 27 27 0a 20 20 20 20 20 20 20 20 66 6f  0, ''.        fo
2b70: 72 20 6d 61 74 63 68 20 69 6e 20 73 65 6c 66 2e  r match in self.
2b80: 72 75 6c 65 5f 73 79 6e 74 61 78 2e 66 69 6e 64  rule_syntax.find
2b90: 69 74 65 72 28 72 75 6c 65 29 3a 0a 20 20 20 20  iter(rule):.    
2ba0: 20 20 20 20 20 20 20 20 70 72 65 66 69 78 20 2b          prefix +
2bb0: 3d 20 72 75 6c 65 5b 6f 66 66 73 65 74 3a 6d 61  = rule[offset:ma
2bc0: 74 63 68 2e 73 74 61 72 74 28 29 5d 0a 20 20 20  tch.start()].   
2bd0: 20 20 20 20 20 20 20 20 20 67 20 3d 20 6d 61 74           g = mat
2be0: 63 68 2e 67 72 6f 75 70 73 28 29 0a 20 20 20 20  ch.groups().    
2bf0: 20 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 67          if len(g
2c00: 5b 30 5d 29 25 32 3a 20 23 20 45 73 63 61 70 65  [0])%2: # Escape
2c10: 64 20 77 69 6c 64 63 61 72 64 0a 20 20 20 20 20  d wildcard.     
2c20: 20 20 20 20 20 20 20 20 20 20 20 70 72 65 66 69             prefi
2c30: 78 20 2b 3d 20 6d 61 74 63 68 2e 67 72 6f 75 70  x += match.group
2c40: 28 30 29 5b 6c 65 6e 28 67 5b 30 5d 29 3a 5d 0a  (0)[len(g[0]):].
2c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c60: 6f 66 66 73 65 74 20 3d 20 6d 61 74 63 68 2e 65  offset = match.e
2c70: 6e 64 28 29 0a 20 20 20 20 20 20 20 20 20 20 20  nd().           
2c80: 20 20 20 20 20 63 6f 6e 74 69 6e 75 65 0a 20 20       continue.  
2c90: 20 20 20 20 20 20 20 20 20 20 69 66 20 70 72 65            if pre
2ca0: 66 69 78 3a 0a 20 20 20 20 20 20 20 20 20 20 20  fix:.           
2cb0: 20 20 20 20 20 79 69 65 6c 64 20 70 72 65 66 69       yield prefi
2cc0: 78 2c 20 4e 6f 6e 65 2c 20 4e 6f 6e 65 0a 20 20  x, None, None.  
2cd0: 20 20 20 20 20 20 20 20 20 20 6e 61 6d 65 2c 20            name, 
2ce0: 66 69 6c 74 72 2c 20 63 6f 6e 66 20 3d 20 67 5b  filtr, conf = g[
2cf0: 34 3a 37 5d 20 69 66 20 67 5b 32 5d 20 69 73 20  4:7] if g[2] is 
2d00: 4e 6f 6e 65 20 65 6c 73 65 20 67 5b 31 3a 34 5d  None else g[1:4]
2d10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65  .            yie
2d20: 6c 64 20 6e 61 6d 65 2c 20 66 69 6c 74 72 20 6f  ld name, filtr o
2d30: 72 20 27 64 65 66 61 75 6c 74 27 2c 20 63 6f 6e  r 'default', con
2d40: 66 20 6f 72 20 4e 6f 6e 65 0a 20 20 20 20 20 20  f or None.      
2d50: 20 20 20 20 20 20 6f 66 66 73 65 74 2c 20 70 72        offset, pr
2d60: 65 66 69 78 20 3d 20 6d 61 74 63 68 2e 65 6e 64  efix = match.end
2d70: 28 29 2c 20 27 27 0a 20 20 20 20 20 20 20 20 69  (), ''.        i
2d80: 66 20 6f 66 66 73 65 74 20 3c 3d 20 6c 65 6e 28  f offset <= len(
2d90: 72 75 6c 65 29 20 6f 72 20 70 72 65 66 69 78 3a  rule) or prefix:
2da0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65  .            yie
2db0: 6c 64 20 70 72 65 66 69 78 2b 72 75 6c 65 5b 6f  ld prefix+rule[o
2dc0: 66 66 73 65 74 3a 5d 2c 20 4e 6f 6e 65 2c 20 4e  ffset:], None, N
2dd0: 6f 6e 65 0a 0a 20 20 20 20 64 65 66 20 61 64 64  one..    def add
2de0: 28 73 65 6c 66 2c 20 72 75 6c 65 2c 20 6d 65 74  (self, rule, met
2df0: 68 6f 64 2c 20 74 61 72 67 65 74 2c 20 6e 61 6d  hod, target, nam
2e00: 65 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20  e=None):.       
2e10: 20 27 27 27 20 41 64 64 20 61 20 6e 65 77 20 72   ''' Add a new r
2e20: 75 6c 65 20 6f 72 20 72 65 70 6c 61 63 65 20 74  ule or replace t
2e30: 68 65 20 74 61 72 67 65 74 20 66 6f 72 20 61 6e  he target for an
2e40: 20 65 78 69 73 74 69 6e 67 20 72 75 6c 65 2e 20   existing rule. 
2e50: 27 27 27 0a 20 20 20 20 20 20 20 20 61 6e 6f 6e  '''.        anon
2e60: 73 20 20 20 20 20 3d 20 30 20 20 20 20 23 20 4e  s     = 0    # N
2e70: 75 6d 62 65 72 20 6f 66 20 61 6e 6f 6e 79 6d 6f  umber of anonymo
2e80: 75 73 20 77 69 6c 64 63 61 72 64 73 20 66 6f 75  us wildcards fou
2e90: 6e 64 0a 20 20 20 20 20 20 20 20 6b 65 79 73 20  nd.        keys 
2ea0: 20 20 20 20 20 3d 20 5b 5d 20 20 20 23 20 4e 61       = []   # Na
2eb0: 6d 65 73 20 6f 66 20 6b 65 79 73 0a 20 20 20 20  mes of keys.    
2ec0: 20 20 20 20 70 61 74 74 65 72 6e 20 20 20 3d 20      pattern   = 
2ed0: 27 27 20 20 20 23 20 52 65 67 75 6c 61 72 20 65  ''   # Regular e
2ee0: 78 70 72 65 73 73 69 6f 6e 20 70 61 74 74 65 72  xpression patter
2ef0: 6e 20 77 69 74 68 20 6e 61 6d 65 64 20 67 72 6f  n with named gro
2f00: 75 70 73 0a 20 20 20 20 20 20 20 20 66 69 6c 74  ups.        filt
2f10: 65 72 73 20 20 20 3d 20 5b 5d 20 20 20 23 20 4c  ers   = []   # L
2f20: 69 73 74 73 20 6f 66 20 77 69 6c 64 63 61 72 64  ists of wildcard
2f30: 20 69 6e 70 75 74 20 66 69 6c 74 65 72 73 0a 20   input filters. 
2f40: 20 20 20 20 20 20 20 62 75 69 6c 64 65 72 20 20         builder  
2f50: 20 3d 20 5b 5d 20 20 20 23 20 44 61 74 61 20 73   = []   # Data s
2f60: 74 72 75 63 74 75 72 65 20 66 6f 72 20 74 68 65  tructure for the
2f70: 20 55 52 4c 20 62 75 69 6c 64 65 72 0a 20 20 20   URL builder.   
2f80: 20 20 20 20 20 69 73 5f 73 74 61 74 69 63 20 3d       is_static =
2f90: 20 54 72 75 65 0a 0a 20 20 20 20 20 20 20 20 66   True..        f
2fa0: 6f 72 20 6b 65 79 2c 20 6d 6f 64 65 2c 20 63 6f  or key, mode, co
2fb0: 6e 66 20 69 6e 20 73 65 6c 66 2e 5f 69 74 65 72  nf in self._iter
2fc0: 74 6f 6b 65 6e 73 28 72 75 6c 65 29 3a 0a 20 20  tokens(rule):.  
2fd0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6d 6f 64            if mod
2fe0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
2ff0: 20 20 20 69 73 5f 73 74 61 74 69 63 20 3d 20 46     is_static = F
3000: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 20 20 20  alse.           
3010: 20 20 20 20 20 69 66 20 6d 6f 64 65 20 3d 3d 20       if mode == 
3020: 27 64 65 66 61 75 6c 74 27 3a 20 6d 6f 64 65 20  'default': mode 
3030: 3d 20 73 65 6c 66 2e 64 65 66 61 75 6c 74 5f 66  = self.default_f
3040: 69 6c 74 65 72 0a 20 20 20 20 20 20 20 20 20 20  ilter.          
3050: 20 20 20 20 20 20 6d 61 73 6b 2c 20 69 6e 5f 66        mask, in_f
3060: 69 6c 74 65 72 2c 20 6f 75 74 5f 66 69 6c 74 65  ilter, out_filte
3070: 72 20 3d 20 73 65 6c 66 2e 66 69 6c 74 65 72 73  r = self.filters
3080: 5b 6d 6f 64 65 5d 28 63 6f 6e 66 29 0a 20 20 20  [mode](conf).   
3090: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
30a0: 6e 6f 74 20 6b 65 79 3a 0a 20 20 20 20 20 20 20  not key:.       
30b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 61 74               pat
30c0: 74 65 72 6e 20 2b 3d 20 27 28 3f 3a 25 73 29 27  tern += '(?:%s)'
30d0: 20 25 20 6d 61 73 6b 0a 20 20 20 20 20 20 20 20   % mask.        
30e0: 20 20 20 20 20 20 20 20 20 20 20 20 6b 65 79 20              key 
30f0: 3d 20 27 61 6e 6f 6e 25 64 27 20 25 20 61 6e 6f  = 'anon%d' % ano
3100: 6e 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ns.             
3110: 20 20 20 20 20 20 20 61 6e 6f 6e 73 20 2b 3d 20         anons += 
3120: 31 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1.              
3130: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
3140: 20 20 20 20 20 20 20 20 20 20 20 20 70 61 74 74              patt
3150: 65 72 6e 20 2b 3d 20 27 28 3f 50 3c 25 73 3e 25  ern += '(?P<%s>%
3160: 73 29 27 20 25 20 28 6b 65 79 2c 20 6d 61 73 6b  s)' % (key, mask
3170: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
3180: 20 20 20 20 20 20 6b 65 79 73 2e 61 70 70 65 6e        keys.appen
3190: 64 28 6b 65 79 29 0a 20 20 20 20 20 20 20 20 20  d(key).         
31a0: 20 20 20 20 20 20 20 69 66 20 69 6e 5f 66 69 6c         if in_fil
31b0: 74 65 72 3a 20 66 69 6c 74 65 72 73 2e 61 70 70  ter: filters.app
31c0: 65 6e 64 28 28 6b 65 79 2c 20 69 6e 5f 66 69 6c  end((key, in_fil
31d0: 74 65 72 29 29 0a 20 20 20 20 20 20 20 20 20 20  ter)).          
31e0: 20 20 20 20 20 20 62 75 69 6c 64 65 72 2e 61 70        builder.ap
31f0: 70 65 6e 64 28 28 6b 65 79 2c 20 6f 75 74 5f 66  pend((key, out_f
3200: 69 6c 74 65 72 20 6f 72 20 73 74 72 29 29 0a 20  ilter or str)). 
3210: 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20             elif 
3220: 6b 65 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  key:.           
3230: 20 20 20 20 20 70 61 74 74 65 72 6e 20 2b 3d 20       pattern += 
3240: 72 65 2e 65 73 63 61 70 65 28 6b 65 79 29 0a 20  re.escape(key). 
3250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
3260: 75 69 6c 64 65 72 2e 61 70 70 65 6e 64 28 28 4e  uilder.append((N
3270: 6f 6e 65 2c 20 6b 65 79 29 29 0a 0a 20 20 20 20  one, key))..    
3280: 20 20 20 20 73 65 6c 66 2e 62 75 69 6c 64 65 72      self.builder
3290: 5b 72 75 6c 65 5d 20 3d 20 62 75 69 6c 64 65 72  [rule] = builder
32a0: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 61 6d 65  .        if name
32b0: 3a 20 73 65 6c 66 2e 62 75 69 6c 64 65 72 5b 6e  : self.builder[n
32c0: 61 6d 65 5d 20 3d 20 62 75 69 6c 64 65 72 0a 0a  ame] = builder..
32d0: 20 20 20 20 20 20 20 20 69 66 20 69 73 5f 73 74          if is_st
32e0: 61 74 69 63 20 61 6e 64 20 6e 6f 74 20 73 65 6c  atic and not sel
32f0: 66 2e 73 74 72 69 63 74 5f 6f 72 64 65 72 3a 0a  f.strict_order:.
3300: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
3310: 2e 73 74 61 74 69 63 2e 73 65 74 64 65 66 61 75  .static.setdefau
3320: 6c 74 28 6d 65 74 68 6f 64 2c 20 7b 7d 29 0a 20  lt(method, {}). 
3330: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
3340: 73 74 61 74 69 63 5b 6d 65 74 68 6f 64 5d 5b 73  static[method][s
3350: 65 6c 66 2e 62 75 69 6c 64 28 72 75 6c 65 29 5d  elf.build(rule)]
3360: 20 3d 20 28 74 61 72 67 65 74 2c 20 4e 6f 6e 65   = (target, None
3370: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  ).            re
3380: 74 75 72 6e 0a 0a 20 20 20 20 20 20 20 20 74 72  turn..        tr
3390: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  y:.            r
33a0: 65 5f 70 61 74 74 65 72 6e 20 3d 20 72 65 2e 63  e_pattern = re.c
33b0: 6f 6d 70 69 6c 65 28 27 5e 28 25 73 29 24 27 20  ompile('^(%s)$' 
33c0: 25 20 70 61 74 74 65 72 6e 29 0a 20 20 20 20 20  % pattern).     
33d0: 20 20 20 20 20 20 20 72 65 5f 6d 61 74 63 68 20         re_match 
33e0: 3d 20 72 65 5f 70 61 74 74 65 72 6e 2e 6d 61 74  = re_pattern.mat
33f0: 63 68 0a 20 20 20 20 20 20 20 20 65 78 63 65 70  ch.        excep
3400: 74 20 72 65 2e 65 72 72 6f 72 3a 0a 20 20 20 20  t re.error:.    
3410: 20 20 20 20 20 20 20 20 72 61 69 73 65 20 52 6f          raise Ro
3420: 75 74 65 53 79 6e 74 61 78 45 72 72 6f 72 28 22  uteSyntaxError("
3430: 43 6f 75 6c 64 20 6e 6f 74 20 61 64 64 20 52 6f  Could not add Ro
3440: 75 74 65 3a 20 25 73 20 28 25 73 29 22 20 25 20  ute: %s (%s)" % 
3450: 28 72 75 6c 65 2c 20 5f 65 28 29 29 29 0a 0a 20  (rule, _e())).. 
3460: 20 20 20 20 20 20 20 69 66 20 66 69 6c 74 65 72         if filter
3470: 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  s:.            d
3480: 65 66 20 67 65 74 61 72 67 73 28 70 61 74 68 29  ef getargs(path)
3490: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
34a0: 20 20 75 72 6c 5f 61 72 67 73 20 3d 20 72 65 5f    url_args = re_
34b0: 6d 61 74 63 68 28 70 61 74 68 29 2e 67 72 6f 75  match(path).grou
34c0: 70 64 69 63 74 28 29 0a 20 20 20 20 20 20 20 20  pdict().        
34d0: 20 20 20 20 20 20 20 20 66 6f 72 20 6e 61 6d 65          for name
34e0: 2c 20 77 69 6c 64 63 61 72 64 5f 66 69 6c 74 65  , wildcard_filte
34f0: 72 20 69 6e 20 66 69 6c 74 65 72 73 3a 0a 20 20  r in filters:.  
3500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3510: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20    try:.         
3520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 75                 u
3530: 72 6c 5f 61 72 67 73 5b 6e 61 6d 65 5d 20 3d 20  rl_args[name] = 
3540: 77 69 6c 64 63 61 72 64 5f 66 69 6c 74 65 72 28  wildcard_filter(
3550: 75 72 6c 5f 61 72 67 73 5b 6e 61 6d 65 5d 29 0a  url_args[name]).
3560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3570: 20 20 20 20 65 78 63 65 70 74 20 56 61 6c 75 65      except Value
3580: 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20  Error:.         
3590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
35a0: 61 69 73 65 20 48 54 54 50 45 72 72 6f 72 28 34  aise HTTPError(4
35b0: 30 30 2c 20 27 50 61 74 68 20 68 61 73 20 77 72  00, 'Path has wr
35c0: 6f 6e 67 20 66 6f 72 6d 61 74 2e 27 29 0a 20 20  ong format.').  
35d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
35e0: 74 75 72 6e 20 75 72 6c 5f 61 72 67 73 0a 20 20  turn url_args.  
35f0: 20 20 20 20 20 20 65 6c 69 66 20 72 65 5f 70 61        elif re_pa
3600: 74 74 65 72 6e 2e 67 72 6f 75 70 69 6e 64 65 78  ttern.groupindex
3610: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 65  :.            de
3620: 66 20 67 65 74 61 72 67 73 28 70 61 74 68 29 3a  f getargs(path):
3630: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3640: 20 72 65 74 75 72 6e 20 72 65 5f 6d 61 74 63 68   return re_match
3650: 28 70 61 74 68 29 2e 67 72 6f 75 70 64 69 63 74  (path).groupdict
3660: 28 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a  ().        else:
3670: 0a 20 20 20 20 20 20 20 20 20 20 20 20 67 65 74  .            get
3680: 61 72 67 73 20 3d 20 4e 6f 6e 65 0a 0a 20 20 20  args = None..   
3690: 20 20 20 20 20 66 6c 61 74 70 61 74 20 3d 20 5f       flatpat = _
36a0: 72 65 5f 66 6c 61 74 74 65 6e 28 70 61 74 74 65  re_flatten(patte
36b0: 72 6e 29 0a 20 20 20 20 20 20 20 20 77 68 6f 6c  rn).        whol
36c0: 65 5f 72 75 6c 65 20 3d 20 28 72 75 6c 65 2c 20  e_rule = (rule, 
36d0: 66 6c 61 74 70 61 74 2c 20 74 61 72 67 65 74 2c  flatpat, target,
36e0: 20 67 65 74 61 72 67 73 29 0a 0a 20 20 20 20 20   getargs)..     
36f0: 20 20 20 69 66 20 28 66 6c 61 74 70 61 74 2c 20     if (flatpat, 
3700: 6d 65 74 68 6f 64 29 20 69 6e 20 73 65 6c 66 2e  method) in self.
3710: 5f 67 72 6f 75 70 73 3a 0a 20 20 20 20 20 20 20  _groups:.       
3720: 20 20 20 20 20 69 66 20 44 45 42 55 47 3a 0a 20       if DEBUG:. 
3730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6d                 m
3740: 73 67 20 3d 20 27 52 6f 75 74 65 20 3c 25 73 20  sg = 'Route <%s 
3750: 25 73 3e 20 6f 76 65 72 77 72 69 74 65 73 20 61  %s> overwrites a
3760: 20 70 72 65 76 69 6f 75 73 6c 79 20 64 65 66 69   previously defi
3770: 6e 65 64 20 72 6f 75 74 65 27 0a 20 20 20 20 20  ned route'.     
3780: 20 20 20 20 20 20 20 20 20 20 20 77 61 72 6e 69             warni
3790: 6e 67 73 2e 77 61 72 6e 28 6d 73 67 20 25 20 28  ngs.warn(msg % (
37a0: 6d 65 74 68 6f 64 2c 20 72 75 6c 65 29 2c 20 52  method, rule), R
37b0: 75 6e 74 69 6d 65 57 61 72 6e 69 6e 67 29 0a 20  untimeWarning). 
37c0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
37d0: 64 79 6e 61 5f 72 6f 75 74 65 73 5b 6d 65 74 68  dyna_routes[meth
37e0: 6f 64 5d 5b 73 65 6c 66 2e 5f 67 72 6f 75 70 73  od][self._groups
37f0: 5b 66 6c 61 74 70 61 74 2c 20 6d 65 74 68 6f 64  [flatpat, method
3800: 5d 5d 20 3d 20 77 68 6f 6c 65 5f 72 75 6c 65 0a  ]] = whole_rule.
3810: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
3820: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64            self.d
3830: 79 6e 61 5f 72 6f 75 74 65 73 2e 73 65 74 64 65  yna_routes.setde
3840: 66 61 75 6c 74 28 6d 65 74 68 6f 64 2c 20 5b 5d  fault(method, []
3850: 29 2e 61 70 70 65 6e 64 28 77 68 6f 6c 65 5f 72  ).append(whole_r
3860: 75 6c 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  ule).           
3870: 20 73 65 6c 66 2e 5f 67 72 6f 75 70 73 5b 66 6c   self._groups[fl
3880: 61 74 70 61 74 2c 20 6d 65 74 68 6f 64 5d 20 3d  atpat, method] =
3890: 20 6c 65 6e 28 73 65 6c 66 2e 64 79 6e 61 5f 72   len(self.dyna_r
38a0: 6f 75 74 65 73 5b 6d 65 74 68 6f 64 5d 29 20 2d  outes[method]) -
38b0: 20 31 0a 0a 20 20 20 20 20 20 20 20 73 65 6c 66   1..        self
38c0: 2e 5f 63 6f 6d 70 69 6c 65 28 6d 65 74 68 6f 64  ._compile(method
38d0: 29 0a 0a 20 20 20 20 64 65 66 20 5f 63 6f 6d 70  )..    def _comp
38e0: 69 6c 65 28 73 65 6c 66 2c 20 6d 65 74 68 6f 64  ile(self, method
38f0: 29 3a 0a 20 20 20 20 20 20 20 20 61 6c 6c 5f 72  ):.        all_r
3900: 75 6c 65 73 20 3d 20 73 65 6c 66 2e 64 79 6e 61  ules = self.dyna
3910: 5f 72 6f 75 74 65 73 5b 6d 65 74 68 6f 64 5d 0a  _routes[method].
3920: 20 20 20 20 20 20 20 20 63 6f 6d 62 6f 72 75 6c          comborul
3930: 65 73 20 3d 20 73 65 6c 66 2e 64 79 6e 61 5f 72  es = self.dyna_r
3940: 65 67 65 78 65 73 5b 6d 65 74 68 6f 64 5d 20 3d  egexes[method] =
3950: 20 5b 5d 0a 20 20 20 20 20 20 20 20 6d 61 78 67   [].        maxg
3960: 72 6f 75 70 73 20 3d 20 73 65 6c 66 2e 5f 4d 41  roups = self._MA
3970: 58 5f 47 52 4f 55 50 53 5f 50 45 52 5f 50 41 54  X_GROUPS_PER_PAT
3980: 54 45 52 4e 0a 20 20 20 20 20 20 20 20 66 6f 72  TERN.        for
3990: 20 78 20 69 6e 20 72 61 6e 67 65 28 30 2c 20 6c   x in range(0, l
39a0: 65 6e 28 61 6c 6c 5f 72 75 6c 65 73 29 2c 20 6d  en(all_rules), m
39b0: 61 78 67 72 6f 75 70 73 29 3a 0a 20 20 20 20 20  axgroups):.     
39c0: 20 20 20 20 20 20 20 73 6f 6d 65 20 3d 20 61 6c         some = al
39d0: 6c 5f 72 75 6c 65 73 5b 78 3a 78 2b 6d 61 78 67  l_rules[x:x+maxg
39e0: 72 6f 75 70 73 5d 0a 20 20 20 20 20 20 20 20 20  roups].         
39f0: 20 20 20 63 6f 6d 62 69 6e 65 64 20 3d 20 28 66     combined = (f
3a00: 6c 61 74 70 61 74 20 66 6f 72 20 28 5f 2c 20 66  latpat for (_, f
3a10: 6c 61 74 70 61 74 2c 20 5f 2c 20 5f 29 20 69 6e  latpat, _, _) in
3a20: 20 73 6f 6d 65 29 0a 20 20 20 20 20 20 20 20 20   some).         
3a30: 20 20 20 63 6f 6d 62 69 6e 65 64 20 3d 20 27 7c     combined = '|
3a40: 27 2e 6a 6f 69 6e 28 27 28 5e 25 73 24 29 27 20  '.join('(^%s$)' 
3a50: 25 20 66 6c 61 74 70 61 74 20 66 6f 72 20 66 6c  % flatpat for fl
3a60: 61 74 70 61 74 20 69 6e 20 63 6f 6d 62 69 6e 65  atpat in combine
3a70: 64 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 63  d).            c
3a80: 6f 6d 62 69 6e 65 64 20 3d 20 72 65 2e 63 6f 6d  ombined = re.com
3a90: 70 69 6c 65 28 63 6f 6d 62 69 6e 65 64 29 2e 6d  pile(combined).m
3aa0: 61 74 63 68 0a 20 20 20 20 20 20 20 20 20 20 20  atch.           
3ab0: 20 72 75 6c 65 73 20 3d 20 5b 28 74 61 72 67 65   rules = [(targe
3ac0: 74 2c 20 67 65 74 61 72 67 73 29 20 66 6f 72 20  t, getargs) for 
3ad0: 28 5f 2c 20 5f 2c 20 74 61 72 67 65 74 2c 20 67  (_, _, target, g
3ae0: 65 74 61 72 67 73 29 20 69 6e 20 73 6f 6d 65 5d  etargs) in some]
3af0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6d  .            com
3b00: 62 6f 72 75 6c 65 73 2e 61 70 70 65 6e 64 28 28  borules.append((
3b10: 63 6f 6d 62 69 6e 65 64 2c 20 72 75 6c 65 73 29  combined, rules)
3b20: 29 0a 0a 20 20 20 20 64 65 66 20 62 75 69 6c 64  )..    def build
3b30: 28 73 65 6c 66 2c 20 5f 6e 61 6d 65 2c 20 2a 61  (self, _name, *a
3b40: 6e 6f 6e 73 2c 20 2a 2a 71 75 65 72 79 29 3a 0a  nons, **query):.
3b50: 20 20 20 20 20 20 20 20 27 27 27 20 42 75 69 6c          ''' Buil
3b60: 64 20 61 6e 20 55 52 4c 20 62 79 20 66 69 6c 6c  d an URL by fill
3b70: 69 6e 67 20 74 68 65 20 77 69 6c 64 63 61 72 64  ing the wildcard
3b80: 73 20 69 6e 20 61 20 72 75 6c 65 2e 20 27 27 27  s in a rule. '''
3b90: 0a 20 20 20 20 20 20 20 20 62 75 69 6c 64 65 72  .        builder
3ba0: 20 3d 20 73 65 6c 66 2e 62 75 69 6c 64 65 72 2e   = self.builder.
3bb0: 67 65 74 28 5f 6e 61 6d 65 29 0a 20 20 20 20 20  get(_name).     
3bc0: 20 20 20 69 66 20 6e 6f 74 20 62 75 69 6c 64 65     if not builde
3bd0: 72 3a 20 72 61 69 73 65 20 52 6f 75 74 65 42 75  r: raise RouteBu
3be0: 69 6c 64 45 72 72 6f 72 28 22 4e 6f 20 72 6f 75  ildError("No rou
3bf0: 74 65 20 77 69 74 68 20 74 68 61 74 20 6e 61 6d  te with that nam
3c00: 65 2e 22 2c 20 5f 6e 61 6d 65 29 0a 20 20 20 20  e.", _name).    
3c10: 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
3c20: 20 20 20 20 20 66 6f 72 20 69 2c 20 76 61 6c 75       for i, valu
3c30: 65 20 69 6e 20 65 6e 75 6d 65 72 61 74 65 28 61  e in enumerate(a
3c40: 6e 6f 6e 73 29 3a 20 71 75 65 72 79 5b 27 61 6e  nons): query['an
3c50: 6f 6e 25 64 27 25 69 5d 20 3d 20 76 61 6c 75 65  on%d'%i] = value
3c60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 75 72 6c  .            url
3c70: 20 3d 20 27 27 2e 6a 6f 69 6e 28 5b 66 28 71 75   = ''.join([f(qu
3c80: 65 72 79 2e 70 6f 70 28 6e 29 29 20 69 66 20 6e  ery.pop(n)) if n
3c90: 20 65 6c 73 65 20 66 20 66 6f 72 20 28 6e 2c 66   else f for (n,f
3ca0: 29 20 69 6e 20 62 75 69 6c 64 65 72 5d 29 0a 20  ) in builder]). 
3cb0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
3cc0: 6e 20 75 72 6c 20 69 66 20 6e 6f 74 20 71 75 65  n url if not que
3cd0: 72 79 20 65 6c 73 65 20 75 72 6c 2b 27 3f 27 2b  ry else url+'?'+
3ce0: 75 72 6c 65 6e 63 6f 64 65 28 71 75 65 72 79 29  urlencode(query)
3cf0: 0a 20 20 20 20 20 20 20 20 65 78 63 65 70 74 20  .        except 
3d00: 4b 65 79 45 72 72 6f 72 3a 0a 20 20 20 20 20 20  KeyError:.      
3d10: 20 20 20 20 20 20 72 61 69 73 65 20 52 6f 75 74        raise Rout
3d20: 65 42 75 69 6c 64 45 72 72 6f 72 28 27 4d 69 73  eBuildError('Mis
3d30: 73 69 6e 67 20 55 52 4c 20 61 72 67 75 6d 65 6e  sing URL argumen
3d40: 74 3a 20 25 72 27 20 25 20 5f 65 28 29 2e 61 72  t: %r' % _e().ar
3d50: 67 73 5b 30 5d 29 0a 0a 20 20 20 20 64 65 66 20  gs[0])..    def 
3d60: 6d 61 74 63 68 28 73 65 6c 66 2c 20 65 6e 76 69  match(self, envi
3d70: 72 6f 6e 29 3a 0a 20 20 20 20 20 20 20 20 27 27  ron):.        ''
3d80: 27 20 52 65 74 75 72 6e 20 61 20 28 74 61 72 67  ' Return a (targ
3d90: 65 74 2c 20 75 72 6c 5f 61 67 72 73 29 20 74 75  et, url_agrs) tu
3da0: 70 6c 65 20 6f 72 20 72 61 69 73 65 20 48 54 54  ple or raise HTT
3db0: 50 45 72 72 6f 72 28 34 30 30 2f 34 30 34 2f 34  PError(400/404/4
3dc0: 30 35 29 2e 20 27 27 27 0a 20 20 20 20 20 20 20  05). '''.       
3dd0: 20 76 65 72 62 20 3d 20 65 6e 76 69 72 6f 6e 5b   verb = environ[
3de0: 27 52 45 51 55 45 53 54 5f 4d 45 54 48 4f 44 27  'REQUEST_METHOD'
3df0: 5d 2e 75 70 70 65 72 28 29 0a 20 20 20 20 20 20  ].upper().      
3e00: 20 20 70 61 74 68 20 3d 20 65 6e 76 69 72 6f 6e    path = environ
3e10: 5b 27 50 41 54 48 5f 49 4e 46 4f 27 5d 20 6f 72  ['PATH_INFO'] or
3e20: 20 27 2f 27 0a 20 20 20 20 20 20 20 20 74 61 72   '/'.        tar
3e30: 67 65 74 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20  get = None.     
3e40: 20 20 20 69 66 20 76 65 72 62 20 3d 3d 20 27 48     if verb == 'H
3e50: 45 41 44 27 3a 0a 20 20 20 20 20 20 20 20 20 20  EAD':.          
3e60: 20 20 6d 65 74 68 6f 64 73 20 3d 20 5b 27 50 52    methods = ['PR
3e70: 4f 58 59 27 2c 20 76 65 72 62 2c 20 27 47 45 54  OXY', verb, 'GET
3e80: 27 2c 20 27 41 4e 59 27 5d 0a 20 20 20 20 20 20  ', 'ANY'].      
3e90: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
3ea0: 20 20 20 20 6d 65 74 68 6f 64 73 20 3d 20 5b 27      methods = ['
3eb0: 50 52 4f 58 59 27 2c 20 76 65 72 62 2c 20 27 41  PROXY', verb, 'A
3ec0: 4e 59 27 5d 0a 0a 20 20 20 20 20 20 20 20 66 6f  NY']..        fo
3ed0: 72 20 6d 65 74 68 6f 64 20 69 6e 20 6d 65 74 68  r method in meth
3ee0: 6f 64 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ods:.           
3ef0: 20 69 66 20 6d 65 74 68 6f 64 20 69 6e 20 73 65   if method in se
3f00: 6c 66 2e 73 74 61 74 69 63 20 61 6e 64 20 70 61  lf.static and pa
3f10: 74 68 20 69 6e 20 73 65 6c 66 2e 73 74 61 74 69  th in self.stati
3f20: 63 5b 6d 65 74 68 6f 64 5d 3a 0a 20 20 20 20 20  c[method]:.     
3f30: 20 20 20 20 20 20 20 20 20 20 20 74 61 72 67 65             targe
3f40: 74 2c 20 67 65 74 61 72 67 73 20 3d 20 73 65 6c  t, getargs = sel
3f50: 66 2e 73 74 61 74 69 63 5b 6d 65 74 68 6f 64 5d  f.static[method]
3f60: 5b 70 61 74 68 5d 0a 20 20 20 20 20 20 20 20 20  [path].         
3f70: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 74 61         return ta
3f80: 72 67 65 74 2c 20 67 65 74 61 72 67 73 28 70 61  rget, getargs(pa
3f90: 74 68 29 20 69 66 20 67 65 74 61 72 67 73 20 65  th) if getargs e
3fa0: 6c 73 65 20 7b 7d 0a 20 20 20 20 20 20 20 20 20  lse {}.         
3fb0: 20 20 20 65 6c 69 66 20 6d 65 74 68 6f 64 20 69     elif method i
3fc0: 6e 20 73 65 6c 66 2e 64 79 6e 61 5f 72 65 67 65  n self.dyna_rege
3fd0: 78 65 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20  xes:.           
3fe0: 20 20 20 20 20 66 6f 72 20 63 6f 6d 62 69 6e 65       for combine
3ff0: 64 2c 20 72 75 6c 65 73 20 69 6e 20 73 65 6c 66  d, rules in self
4000: 2e 64 79 6e 61 5f 72 65 67 65 78 65 73 5b 6d 65  .dyna_regexes[me
4010: 74 68 6f 64 5d 3a 0a 20 20 20 20 20 20 20 20 20  thod]:.         
4020: 20 20 20 20 20 20 20 20 20 20 20 6d 61 74 63 68             match
4030: 20 3d 20 63 6f 6d 62 69 6e 65 64 28 70 61 74 68   = combined(path
4040: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
4050: 20 20 20 20 20 20 69 66 20 6d 61 74 63 68 3a 0a        if match:.
4060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4070: 20 20 20 20 20 20 20 20 74 61 72 67 65 74 2c 20          target, 
4080: 67 65 74 61 72 67 73 20 3d 20 72 75 6c 65 73 5b  getargs = rules[
4090: 6d 61 74 63 68 2e 6c 61 73 74 69 6e 64 65 78 20  match.lastindex 
40a0: 2d 20 31 5d 0a 20 20 20 20 20 20 20 20 20 20 20  - 1].           
40b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
40c0: 75 72 6e 20 74 61 72 67 65 74 2c 20 67 65 74 61  urn target, geta
40d0: 72 67 73 28 70 61 74 68 29 20 69 66 20 67 65 74  rgs(path) if get
40e0: 61 72 67 73 20 65 6c 73 65 20 7b 7d 0a 0a 20 20  args else {}..  
40f0: 20 20 20 20 20 20 23 20 4e 6f 20 6d 61 74 63 68        # No match
4100: 69 6e 67 20 72 6f 75 74 65 20 66 6f 75 6e 64 2e  ing route found.
4110: 20 43 6f 6c 6c 65 63 74 20 61 6c 74 65 72 6e 61   Collect alterna
4120: 74 69 76 65 20 6d 65 74 68 6f 64 73 20 66 6f 72  tive methods for
4130: 20 34 30 35 20 72 65 73 70 6f 6e 73 65 0a 20 20   405 response.  
4140: 20 20 20 20 20 20 61 6c 6c 6f 77 65 64 20 3d 20        allowed = 
4150: 73 65 74 28 5b 5d 29 0a 20 20 20 20 20 20 20 20  set([]).        
4160: 6e 6f 63 68 65 63 6b 20 3d 20 73 65 74 28 6d 65  nocheck = set(me
4170: 74 68 6f 64 73 29 0a 20 20 20 20 20 20 20 20 66  thods).        f
4180: 6f 72 20 6d 65 74 68 6f 64 20 69 6e 20 73 65 74  or method in set
4190: 28 73 65 6c 66 2e 73 74 61 74 69 63 29 20 2d 20  (self.static) - 
41a0: 6e 6f 63 68 65 63 6b 3a 0a 20 20 20 20 20 20 20  nocheck:.       
41b0: 20 20 20 20 20 69 66 20 70 61 74 68 20 69 6e 20       if path in 
41c0: 73 65 6c 66 2e 73 74 61 74 69 63 5b 6d 65 74 68  self.static[meth
41d0: 6f 64 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20  od]:.           
41e0: 20 20 20 20 20 61 6c 6c 6f 77 65 64 2e 61 64 64       allowed.add
41f0: 28 76 65 72 62 29 0a 20 20 20 20 20 20 20 20 66  (verb).        f
4200: 6f 72 20 6d 65 74 68 6f 64 20 69 6e 20 73 65 74  or method in set
4210: 28 73 65 6c 66 2e 64 79 6e 61 5f 72 65 67 65 78  (self.dyna_regex
4220: 65 73 29 20 2d 20 61 6c 6c 6f 77 65 64 20 2d 20  es) - allowed - 
4230: 6e 6f 63 68 65 63 6b 3a 0a 20 20 20 20 20 20 20  nocheck:.       
4240: 20 20 20 20 20 66 6f 72 20 63 6f 6d 62 69 6e 65       for combine
4250: 64 2c 20 72 75 6c 65 73 20 69 6e 20 73 65 6c 66  d, rules in self
4260: 2e 64 79 6e 61 5f 72 65 67 65 78 65 73 5b 6d 65  .dyna_regexes[me
4270: 74 68 6f 64 5d 3a 0a 20 20 20 20 20 20 20 20 20  thod]:.         
4280: 20 20 20 20 20 20 20 6d 61 74 63 68 20 3d 20 63         match = c
4290: 6f 6d 62 69 6e 65 64 28 70 61 74 68 29 0a 20 20  ombined(path).  
42a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
42b0: 20 6d 61 74 63 68 3a 0a 20 20 20 20 20 20 20 20   match:.        
42c0: 20 20 20 20 20 20 20 20 20 20 20 20 61 6c 6c 6f              allo
42d0: 77 65 64 2e 61 64 64 28 6d 65 74 68 6f 64 29 0a  wed.add(method).
42e0: 20 20 20 20 20 20 20 20 69 66 20 61 6c 6c 6f 77          if allow
42f0: 65 64 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ed:.            
4300: 61 6c 6c 6f 77 5f 68 65 61 64 65 72 20 3d 20 22  allow_header = "
4310: 2c 22 2e 6a 6f 69 6e 28 73 6f 72 74 65 64 28 61  ,".join(sorted(a
4320: 6c 6c 6f 77 65 64 29 29 0a 20 20 20 20 20 20 20  llowed)).       
4330: 20 20 20 20 20 72 61 69 73 65 20 48 54 54 50 45       raise HTTPE
4340: 72 72 6f 72 28 34 30 35 2c 20 22 4d 65 74 68 6f  rror(405, "Metho
4350: 64 20 6e 6f 74 20 61 6c 6c 6f 77 65 64 2e 22 2c  d not allowed.",
4360: 20 41 6c 6c 6f 77 3d 61 6c 6c 6f 77 5f 68 65 61   Allow=allow_hea
4370: 64 65 72 29 0a 0a 20 20 20 20 20 20 20 20 23 20  der)..        # 
4380: 4e 6f 20 6d 61 74 63 68 69 6e 67 20 72 6f 75 74  No matching rout
4390: 65 20 61 6e 64 20 6e 6f 20 61 6c 74 65 72 6e 61  e and no alterna
43a0: 74 69 76 65 20 6d 65 74 68 6f 64 20 66 6f 75 6e  tive method foun
43b0: 64 2e 20 57 65 20 67 69 76 65 20 75 70 0a 20 20  d. We give up.  
43c0: 20 20 20 20 20 20 72 61 69 73 65 20 48 54 54 50        raise HTTP
43d0: 45 72 72 6f 72 28 34 30 34 2c 20 22 4e 6f 74 20  Error(404, "Not 
43e0: 66 6f 75 6e 64 3a 20 22 20 2b 20 72 65 70 72 28  found: " + repr(
43f0: 70 61 74 68 29 29 0a 0a 0a 0a 0a 0a 0a 63 6c 61  path)).......cla
4400: 73 73 20 52 6f 75 74 65 28 6f 62 6a 65 63 74 29  ss Route(object)
4410: 3a 0a 20 20 20 20 27 27 27 20 54 68 69 73 20 63  :.    ''' This c
4420: 6c 61 73 73 20 77 72 61 70 73 20 61 20 72 6f 75  lass wraps a rou
4430: 74 65 20 63 61 6c 6c 62 61 63 6b 20 61 6c 6f 6e  te callback alon
4440: 67 20 77 69 74 68 20 72 6f 75 74 65 20 73 70 65  g with route spe
4450: 63 69 66 69 63 20 6d 65 74 61 64 61 74 61 20 61  cific metadata a
4460: 6e 64 0a 20 20 20 20 20 20 20 20 63 6f 6e 66 69  nd.        confi
4470: 67 75 72 61 74 69 6f 6e 20 61 6e 64 20 61 70 70  guration and app
4480: 6c 69 65 73 20 50 6c 75 67 69 6e 73 20 6f 6e 20  lies Plugins on 
4490: 64 65 6d 61 6e 64 2e 20 49 74 20 69 73 20 61 6c  demand. It is al
44a0: 73 6f 20 72 65 73 70 6f 6e 73 69 62 6c 65 20 66  so responsible f
44b0: 6f 72 0a 20 20 20 20 20 20 20 20 74 75 72 69 6e  or.        turin
44c0: 67 20 61 6e 20 55 52 4c 20 70 61 74 68 20 72 75  g an URL path ru
44d0: 6c 65 20 69 6e 74 6f 20 61 20 72 65 67 75 6c 61  le into a regula
44e0: 72 20 65 78 70 72 65 73 73 69 6f 6e 20 75 73 61  r expression usa
44f0: 62 6c 65 20 62 79 20 74 68 65 20 52 6f 75 74 65  ble by the Route
4500: 72 2e 0a 20 20 20 20 27 27 27 0a 0a 20 20 20 20  r..    '''..    
4510: 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c  def __init__(sel
4520: 66 2c 20 61 70 70 2c 20 72 75 6c 65 2c 20 6d 65  f, app, rule, me
4530: 74 68 6f 64 2c 20 63 61 6c 6c 62 61 63 6b 2c 20  thod, callback, 
4540: 6e 61 6d 65 3d 4e 6f 6e 65 2c 0a 20 20 20 20 20  name=None,.     
4550: 20 20 20 20 20 20 20 20 20 20 20 20 70 6c 75 67              plug
4560: 69 6e 73 3d 4e 6f 6e 65 2c 20 73 6b 69 70 6c 69  ins=None, skipli
4570: 73 74 3d 4e 6f 6e 65 2c 20 2a 2a 63 6f 6e 66 69  st=None, **confi
4580: 67 29 3a 0a 20 20 20 20 20 20 20 20 23 3a 20 54  g):.        #: T
4590: 68 65 20 61 70 70 6c 69 63 61 74 69 6f 6e 20 74  he application t
45a0: 68 69 73 20 72 6f 75 74 65 20 69 73 20 69 6e 73  his route is ins
45b0: 74 61 6c 6c 65 64 20 74 6f 2e 0a 20 20 20 20 20  talled to..     
45c0: 20 20 20 73 65 6c 66 2e 61 70 70 20 3d 20 61 70     self.app = ap
45d0: 70 0a 20 20 20 20 20 20 20 20 23 3a 20 54 68 65  p.        #: The
45e0: 20 70 61 74 68 2d 72 75 6c 65 20 73 74 72 69 6e   path-rule strin
45f0: 67 20 28 65 2e 67 2e 20 60 60 2f 77 69 6b 69 2f  g (e.g. ``/wiki/
4600: 3a 70 61 67 65 60 60 29 2e 0a 20 20 20 20 20 20  :page``)..      
4610: 20 20 73 65 6c 66 2e 72 75 6c 65 20 3d 20 72 75    self.rule = ru
4620: 6c 65 0a 20 20 20 20 20 20 20 20 23 3a 20 54 68  le.        #: Th
4630: 65 20 48 54 54 50 20 6d 65 74 68 6f 64 20 61 73  e HTTP method as
4640: 20 61 20 73 74 72 69 6e 67 20 28 65 2e 67 2e 20   a string (e.g. 
4650: 60 60 47 45 54 60 60 29 2e 0a 20 20 20 20 20 20  ``GET``)..      
4660: 20 20 73 65 6c 66 2e 6d 65 74 68 6f 64 20 3d 20    self.method = 
4670: 6d 65 74 68 6f 64 0a 20 20 20 20 20 20 20 20 23  method.        #
4680: 3a 20 54 68 65 20 6f 72 69 67 69 6e 61 6c 20 63  : The original c
4690: 61 6c 6c 62 61 63 6b 20 77 69 74 68 20 6e 6f 20  allback with no 
46a0: 70 6c 75 67 69 6e 73 20 61 70 70 6c 69 65 64 2e  plugins applied.
46b0: 20 55 73 65 66 75 6c 20 66 6f 72 20 69 6e 74 72   Useful for intr
46c0: 6f 73 70 65 63 74 69 6f 6e 2e 0a 20 20 20 20 20  ospection..     
46d0: 20 20 20 73 65 6c 66 2e 63 61 6c 6c 62 61 63 6b     self.callback
46e0: 20 3d 20 63 61 6c 6c 62 61 63 6b 0a 20 20 20 20   = callback.    
46f0: 20 20 20 20 23 3a 20 54 68 65 20 6e 61 6d 65 20      #: The name 
4700: 6f 66 20 74 68 65 20 72 6f 75 74 65 20 28 69 66  of the route (if
4710: 20 73 70 65 63 69 66 69 65 64 29 20 6f 72 20 60   specified) or `
4720: 60 4e 6f 6e 65 60 60 2e 0a 20 20 20 20 20 20 20  `None``..       
4730: 20 73 65 6c 66 2e 6e 61 6d 65 20 3d 20 6e 61 6d   self.name = nam
4740: 65 20 6f 72 20 4e 6f 6e 65 0a 20 20 20 20 20 20  e or None.      
4750: 20 20 23 3a 20 41 20 6c 69 73 74 20 6f 66 20 72    #: A list of r
4760: 6f 75 74 65 2d 73 70 65 63 69 66 69 63 20 70 6c  oute-specific pl
4770: 75 67 69 6e 73 20 28 73 65 65 20 3a 6d 65 74 68  ugins (see :meth
4780: 3a 60 42 6f 74 74 6c 65 2e 72 6f 75 74 65 60 29  :`Bottle.route`)
4790: 2e 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 70  ..        self.p
47a0: 6c 75 67 69 6e 73 20 3d 20 70 6c 75 67 69 6e 73  lugins = plugins
47b0: 20 6f 72 20 5b 5d 0a 20 20 20 20 20 20 20 20 23   or [].        #
47c0: 3a 20 41 20 6c 69 73 74 20 6f 66 20 70 6c 75 67  : A list of plug
47d0: 69 6e 73 20 74 6f 20 6e 6f 74 20 61 70 70 6c 79  ins to not apply
47e0: 20 74 6f 20 74 68 69 73 20 72 6f 75 74 65 20 28   to this route (
47f0: 73 65 65 20 3a 6d 65 74 68 3a 60 42 6f 74 74 6c  see :meth:`Bottl
4800: 65 2e 72 6f 75 74 65 60 29 2e 0a 20 20 20 20 20  e.route`)..     
4810: 20 20 20 73 65 6c 66 2e 73 6b 69 70 6c 69 73 74     self.skiplist
4820: 20 3d 20 73 6b 69 70 6c 69 73 74 20 6f 72 20 5b   = skiplist or [
4830: 5d 0a 20 20 20 20 20 20 20 20 23 3a 20 41 64 64  ].        #: Add
4840: 69 74 69 6f 6e 61 6c 20 6b 65 79 77 6f 72 64 20  itional keyword 
4850: 61 72 67 75 6d 65 6e 74 73 20 70 61 73 73 65 64  arguments passed
4860: 20 74 6f 20 74 68 65 20 3a 6d 65 74 68 3a 60 42   to the :meth:`B
4870: 6f 74 74 6c 65 2e 72 6f 75 74 65 60 0a 20 20 20  ottle.route`.   
4880: 20 20 20 20 20 23 3a 20 64 65 63 6f 72 61 74 6f       #: decorato
4890: 72 20 61 72 65 20 73 74 6f 72 65 64 20 69 6e 20  r are stored in 
48a0: 74 68 69 73 20 64 69 63 74 69 6f 6e 61 72 79 2e  this dictionary.
48b0: 20 55 73 65 64 20 66 6f 72 20 72 6f 75 74 65 2d   Used for route-
48c0: 73 70 65 63 69 66 69 63 0a 20 20 20 20 20 20 20  specific.       
48d0: 20 23 3a 20 70 6c 75 67 69 6e 20 63 6f 6e 66 69   #: plugin confi
48e0: 67 75 72 61 74 69 6f 6e 20 61 6e 64 20 6d 65 74  guration and met
48f0: 61 2d 64 61 74 61 2e 0a 20 20 20 20 20 20 20 20  a-data..        
4900: 73 65 6c 66 2e 63 6f 6e 66 69 67 20 3d 20 43 6f  self.config = Co
4910: 6e 66 69 67 44 69 63 74 28 29 2e 6c 6f 61 64 5f  nfigDict().load_
4920: 64 69 63 74 28 63 6f 6e 66 69 67 2c 20 6d 61 6b  dict(config, mak
4930: 65 5f 6e 61 6d 65 73 70 61 63 65 73 3d 54 72 75  e_namespaces=Tru
4940: 65 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 63 61  e)..    def __ca
4950: 6c 6c 5f 5f 28 73 65 6c 66 2c 20 2a 61 2c 20 2a  ll__(self, *a, *
4960: 2a 6b 61 29 3a 0a 20 20 20 20 20 20 20 20 64 65  *ka):.        de
4970: 70 72 28 22 53 6f 6d 65 20 41 50 49 73 20 63 68  pr("Some APIs ch
4980: 61 6e 67 65 64 20 74 6f 20 72 65 74 75 72 6e 20  anged to return 
4990: 52 6f 75 74 65 28 29 20 69 6e 73 74 61 6e 63 65  Route() instance
49a0: 73 20 69 6e 73 74 65 61 64 20 6f 66 22 5c 0a 20  s instead of"\. 
49b0: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 63 61              " ca
49c0: 6c 6c 61 62 6c 65 73 2e 20 4d 61 6b 65 20 73 75  llables. Make su
49d0: 72 65 20 74 6f 20 75 73 65 20 74 68 65 20 52 6f  re to use the Ro
49e0: 75 74 65 2e 63 61 6c 6c 20 6d 65 74 68 6f 64 20  ute.call method 
49f0: 61 6e 64 20 6e 6f 74 20 74 6f 22 5c 0a 20 20 20  and not to"\.   
4a00: 20 20 20 20 20 20 20 20 20 20 22 20 63 61 6c 6c            " call
4a10: 20 52 6f 75 74 65 20 69 6e 73 74 61 6e 63 65 73   Route instances
4a20: 20 64 69 72 65 63 74 6c 79 2e 22 29 20 23 30 2e   directly.") #0.
4a30: 31 32 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  12.        retur
4a40: 6e 20 73 65 6c 66 2e 63 61 6c 6c 28 2a 61 2c 20  n self.call(*a, 
4a50: 2a 2a 6b 61 29 0a 0a 20 20 20 20 40 63 61 63 68  **ka)..    @cach
4a60: 65 64 5f 70 72 6f 70 65 72 74 79 0a 20 20 20 20  ed_property.    
4a70: 64 65 66 20 63 61 6c 6c 28 73 65 6c 66 29 3a 0a  def call(self):.
4a80: 20 20 20 20 20 20 20 20 27 27 27 20 54 68 65 20          ''' The 
4a90: 72 6f 75 74 65 20 63 61 6c 6c 62 61 63 6b 20 77  route callback w
4aa0: 69 74 68 20 61 6c 6c 20 70 6c 75 67 69 6e 73 20  ith all plugins 
4ab0: 61 70 70 6c 69 65 64 2e 20 54 68 69 73 20 70 72  applied. This pr
4ac0: 6f 70 65 72 74 79 20 69 73 0a 20 20 20 20 20 20  operty is.      
4ad0: 20 20 20 20 20 20 63 72 65 61 74 65 64 20 6f 6e        created on
4ae0: 20 64 65 6d 61 6e 64 20 61 6e 64 20 74 68 65 6e   demand and then
4af0: 20 63 61 63 68 65 64 20 74 6f 20 73 70 65 65 64   cached to speed
4b00: 20 75 70 20 73 75 62 73 65 71 75 65 6e 74 20 72   up subsequent r
4b10: 65 71 75 65 73 74 73 2e 27 27 27 0a 20 20 20 20  equests.'''.    
4b20: 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e      return self.
4b30: 5f 6d 61 6b 65 5f 63 61 6c 6c 62 61 63 6b 28 29  _make_callback()
4b40: 0a 0a 20 20 20 20 64 65 66 20 72 65 73 65 74 28  ..    def reset(
4b50: 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 27  self):.        '
4b60: 27 27 20 46 6f 72 67 65 74 20 61 6e 79 20 63 61  '' Forget any ca
4b70: 63 68 65 64 20 76 61 6c 75 65 73 2e 20 54 68 65  ched values. The
4b80: 20 6e 65 78 74 20 74 69 6d 65 20 3a 61 74 74 72   next time :attr
4b90: 3a 60 63 61 6c 6c 60 20 69 73 20 61 63 63 65 73  :`call` is acces
4ba0: 73 65 64 2c 0a 20 20 20 20 20 20 20 20 20 20 20  sed,.           
4bb0: 20 61 6c 6c 20 70 6c 75 67 69 6e 73 20 61 72 65   all plugins are
4bc0: 20 72 65 2d 61 70 70 6c 69 65 64 2e 20 27 27 27   re-applied. '''
4bd0: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 5f  .        self.__
4be0: 64 69 63 74 5f 5f 2e 70 6f 70 28 27 63 61 6c 6c  dict__.pop('call
4bf0: 27 2c 20 4e 6f 6e 65 29 0a 0a 20 20 20 20 64 65  ', None)..    de
4c00: 66 20 70 72 65 70 61 72 65 28 73 65 6c 66 29 3a  f prepare(self):
4c10: 0a 20 20 20 20 20 20 20 20 27 27 27 20 44 6f 20  .        ''' Do 
4c20: 61 6c 6c 20 6f 6e 2d 64 65 6d 61 6e 64 20 77 6f  all on-demand wo
4c30: 72 6b 20 69 6d 6d 65 64 69 61 74 65 6c 79 20 28  rk immediately (
4c40: 75 73 65 66 75 6c 20 66 6f 72 20 64 65 62 75 67  useful for debug
4c50: 67 69 6e 67 29 2e 27 27 27 0a 20 20 20 20 20 20  ging).'''.      
4c60: 20 20 73 65 6c 66 2e 63 61 6c 6c 0a 0a 20 20 20    self.call..   
4c70: 20 40 70 72 6f 70 65 72 74 79 0a 20 20 20 20 64   @property.    d
4c80: 65 66 20 5f 63 6f 6e 74 65 78 74 28 73 65 6c 66  ef _context(self
4c90: 29 3a 0a 20 20 20 20 20 20 20 20 64 65 70 72 28  ):.        depr(
4ca0: 27 53 77 69 74 63 68 20 74 6f 20 50 6c 75 67 69  'Switch to Plugi
4cb0: 6e 20 41 50 49 20 76 32 20 61 6e 64 20 61 63 63  n API v2 and acc
4cc0: 65 73 73 20 74 68 65 20 52 6f 75 74 65 20 6f 62  ess the Route ob
4cd0: 6a 65 63 74 20 64 69 72 65 63 74 6c 79 2e 27 29  ject directly.')
4ce0: 20 20 23 30 2e 31 32 0a 20 20 20 20 20 20 20 20    #0.12.        
4cf0: 72 65 74 75 72 6e 20 64 69 63 74 28 72 75 6c 65  return dict(rule
4d00: 3d 73 65 6c 66 2e 72 75 6c 65 2c 20 6d 65 74 68  =self.rule, meth
4d10: 6f 64 3d 73 65 6c 66 2e 6d 65 74 68 6f 64 2c 20  od=self.method, 
4d20: 63 61 6c 6c 62 61 63 6b 3d 73 65 6c 66 2e 63 61  callback=self.ca
4d30: 6c 6c 62 61 63 6b 2c 0a 20 20 20 20 20 20 20 20  llback,.        
4d40: 20 20 20 20 20 20 20 20 20 20 20 20 6e 61 6d 65              name
4d50: 3d 73 65 6c 66 2e 6e 61 6d 65 2c 20 61 70 70 3d  =self.name, app=
4d60: 73 65 6c 66 2e 61 70 70 2c 20 63 6f 6e 66 69 67  self.app, config
4d70: 3d 73 65 6c 66 2e 63 6f 6e 66 69 67 2c 0a 20 20  =self.config,.  
4d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4d90: 20 20 61 70 70 6c 79 3d 73 65 6c 66 2e 70 6c 75    apply=self.plu
4da0: 67 69 6e 73 2c 20 73 6b 69 70 3d 73 65 6c 66 2e  gins, skip=self.
4db0: 73 6b 69 70 6c 69 73 74 29 0a 0a 20 20 20 20 64  skiplist)..    d
4dc0: 65 66 20 61 6c 6c 5f 70 6c 75 67 69 6e 73 28 73  ef all_plugins(s
4dd0: 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 27 27  elf):.        ''
4de0: 27 20 59 69 65 6c 64 20 61 6c 6c 20 50 6c 75 67  ' Yield all Plug
4df0: 69 6e 73 20 61 66 66 65 63 74 69 6e 67 20 74 68  ins affecting th
4e00: 69 73 20 72 6f 75 74 65 2e 20 27 27 27 0a 20 20  is route. '''.  
4e10: 20 20 20 20 20 20 75 6e 69 71 75 65 20 3d 20 73        unique = s
4e20: 65 74 28 29 0a 20 20 20 20 20 20 20 20 66 6f 72  et().        for
4e30: 20 70 20 69 6e 20 72 65 76 65 72 73 65 64 28 73   p in reversed(s
4e40: 65 6c 66 2e 61 70 70 2e 70 6c 75 67 69 6e 73 20  elf.app.plugins 
4e50: 2b 20 73 65 6c 66 2e 70 6c 75 67 69 6e 73 29 3a  + self.plugins):
4e60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
4e70: 54 72 75 65 20 69 6e 20 73 65 6c 66 2e 73 6b 69  True in self.ski
4e80: 70 6c 69 73 74 3a 20 62 72 65 61 6b 0a 20 20 20  plist: break.   
4e90: 20 20 20 20 20 20 20 20 20 6e 61 6d 65 20 3d 20           name = 
4ea0: 67 65 74 61 74 74 72 28 70 2c 20 27 6e 61 6d 65  getattr(p, 'name
4eb0: 27 2c 20 46 61 6c 73 65 29 0a 20 20 20 20 20 20  ', False).      
4ec0: 20 20 20 20 20 20 69 66 20 6e 61 6d 65 20 61 6e        if name an
4ed0: 64 20 28 6e 61 6d 65 20 69 6e 20 73 65 6c 66 2e  d (name in self.
4ee0: 73 6b 69 70 6c 69 73 74 20 6f 72 20 6e 61 6d 65  skiplist or name
4ef0: 20 69 6e 20 75 6e 69 71 75 65 29 3a 20 63 6f 6e   in unique): con
4f00: 74 69 6e 75 65 0a 20 20 20 20 20 20 20 20 20 20  tinue.          
4f10: 20 20 69 66 20 70 20 69 6e 20 73 65 6c 66 2e 73    if p in self.s
4f20: 6b 69 70 6c 69 73 74 20 6f 72 20 74 79 70 65 28  kiplist or type(
4f30: 70 29 20 69 6e 20 73 65 6c 66 2e 73 6b 69 70 6c  p) in self.skipl
4f40: 69 73 74 3a 20 63 6f 6e 74 69 6e 75 65 0a 20 20  ist: continue.  
4f50: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 61 6d            if nam
4f60: 65 3a 20 75 6e 69 71 75 65 2e 61 64 64 28 6e 61  e: unique.add(na
4f70: 6d 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  me).            
4f80: 79 69 65 6c 64 20 70 0a 0a 20 20 20 20 64 65 66  yield p..    def
4f90: 20 5f 6d 61 6b 65 5f 63 61 6c 6c 62 61 63 6b 28   _make_callback(
4fa0: 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 63  self):.        c
4fb0: 61 6c 6c 62 61 63 6b 20 3d 20 73 65 6c 66 2e 63  allback = self.c
4fc0: 61 6c 6c 62 61 63 6b 0a 20 20 20 20 20 20 20 20  allback.        
4fd0: 66 6f 72 20 70 6c 75 67 69 6e 20 69 6e 20 73 65  for plugin in se
4fe0: 6c 66 2e 61 6c 6c 5f 70 6c 75 67 69 6e 73 28 29  lf.all_plugins()
4ff0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 74 72  :.            tr
5000: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y:.             
5010: 20 20 20 69 66 20 68 61 73 61 74 74 72 28 70 6c     if hasattr(pl
5020: 75 67 69 6e 2c 20 27 61 70 70 6c 79 27 29 3a 0a  ugin, 'apply'):.
5030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5040: 20 20 20 20 61 70 69 20 3d 20 67 65 74 61 74 74      api = getatt
5050: 72 28 70 6c 75 67 69 6e 2c 20 27 61 70 69 27 2c  r(plugin, 'api',
5060: 20 31 29 0a 20 20 20 20 20 20 20 20 20 20 20 20   1).            
5070: 20 20 20 20 20 20 20 20 63 6f 6e 74 65 78 74 20          context 
5080: 3d 20 73 65 6c 66 20 69 66 20 61 70 69 20 3e 20  = self if api > 
5090: 31 20 65 6c 73 65 20 73 65 6c 66 2e 5f 63 6f 6e  1 else self._con
50a0: 74 65 78 74 0a 20 20 20 20 20 20 20 20 20 20 20  text.           
50b0: 20 20 20 20 20 20 20 20 20 63 61 6c 6c 62 61 63           callbac
50c0: 6b 20 3d 20 70 6c 75 67 69 6e 2e 61 70 70 6c 79  k = plugin.apply
50d0: 28 63 61 6c 6c 62 61 63 6b 2c 20 63 6f 6e 74 65  (callback, conte
50e0: 78 74 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt).            
50f0: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
5100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 63 61                ca
5110: 6c 6c 62 61 63 6b 20 3d 20 70 6c 75 67 69 6e 28  llback = plugin(
5120: 63 61 6c 6c 62 61 63 6b 29 0a 20 20 20 20 20 20  callback).      
5130: 20 20 20 20 20 20 65 78 63 65 70 74 20 52 6f 75        except Rou
5140: 74 65 52 65 73 65 74 3a 20 23 20 54 72 79 20 61  teReset: # Try a
5150: 67 61 69 6e 20 77 69 74 68 20 63 68 61 6e 67 65  gain with change
5160: 64 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e 2e  d configuration.
5170: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5180: 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f 6d 61   return self._ma
5190: 6b 65 5f 63 61 6c 6c 62 61 63 6b 28 29 0a 20 20  ke_callback().  
51a0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
51b0: 20 63 61 6c 6c 62 61 63 6b 20 69 73 20 73 65 6c   callback is sel
51c0: 66 2e 63 61 6c 6c 62 61 63 6b 3a 0a 20 20 20 20  f.callback:.    
51d0: 20 20 20 20 20 20 20 20 20 20 20 20 75 70 64 61              upda
51e0: 74 65 5f 77 72 61 70 70 65 72 28 63 61 6c 6c 62  te_wrapper(callb
51f0: 61 63 6b 2c 20 73 65 6c 66 2e 63 61 6c 6c 62 61  ack, self.callba
5200: 63 6b 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  ck).        retu
5210: 72 6e 20 63 61 6c 6c 62 61 63 6b 0a 0a 20 20 20  rn callback..   
5220: 20 64 65 66 20 67 65 74 5f 75 6e 64 65 63 6f 72   def get_undecor
5230: 61 74 65 64 5f 63 61 6c 6c 62 61 63 6b 28 73 65  ated_callback(se
5240: 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27  lf):.        '''
5250: 20 52 65 74 75 72 6e 20 74 68 65 20 63 61 6c 6c   Return the call
5260: 62 61 63 6b 2e 20 49 66 20 74 68 65 20 63 61 6c  back. If the cal
5270: 6c 62 61 63 6b 20 69 73 20 61 20 64 65 63 6f 72  lback is a decor
5280: 61 74 65 64 20 66 75 6e 63 74 69 6f 6e 2c 20 74  ated function, t
5290: 72 79 20 74 6f 0a 20 20 20 20 20 20 20 20 20 20  ry to.          
52a0: 20 20 72 65 63 6f 76 65 72 20 74 68 65 20 6f 72    recover the or
52b0: 69 67 69 6e 61 6c 20 66 75 6e 63 74 69 6f 6e 2e  iginal function.
52c0: 20 27 27 27 0a 20 20 20 20 20 20 20 20 66 75 6e   '''.        fun
52d0: 63 20 3d 20 73 65 6c 66 2e 63 61 6c 6c 62 61 63  c = self.callbac
52e0: 6b 0a 20 20 20 20 20 20 20 20 66 75 6e 63 20 3d  k.        func =
52f0: 20 67 65 74 61 74 74 72 28 66 75 6e 63 2c 20 27   getattr(func, '
5300: 5f 5f 66 75 6e 63 5f 5f 27 20 69 66 20 70 79 33  __func__' if py3
5310: 6b 20 65 6c 73 65 20 27 69 6d 5f 66 75 6e 63 27  k else 'im_func'
5320: 2c 20 66 75 6e 63 29 0a 20 20 20 20 20 20 20 20  , func).        
5330: 63 6c 6f 73 75 72 65 5f 61 74 74 72 20 3d 20 27  closure_attr = '
5340: 5f 5f 63 6c 6f 73 75 72 65 5f 5f 27 20 69 66 20  __closure__' if 
5350: 70 79 33 6b 20 65 6c 73 65 20 27 66 75 6e 63 5f  py3k else 'func_
5360: 63 6c 6f 73 75 72 65 27 0a 20 20 20 20 20 20 20  closure'.       
5370: 20 77 68 69 6c 65 20 68 61 73 61 74 74 72 28 66   while hasattr(f
5380: 75 6e 63 2c 20 63 6c 6f 73 75 72 65 5f 61 74 74  unc, closure_att
5390: 72 29 20 61 6e 64 20 67 65 74 61 74 74 72 28 66  r) and getattr(f
53a0: 75 6e 63 2c 20 63 6c 6f 73 75 72 65 5f 61 74 74  unc, closure_att
53b0: 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  r):.            
53c0: 66 75 6e 63 20 3d 20 67 65 74 61 74 74 72 28 66  func = getattr(f
53d0: 75 6e 63 2c 20 63 6c 6f 73 75 72 65 5f 61 74 74  unc, closure_att
53e0: 72 29 5b 30 5d 2e 63 65 6c 6c 5f 63 6f 6e 74 65  r)[0].cell_conte
53f0: 6e 74 73 0a 20 20 20 20 20 20 20 20 72 65 74 75  nts.        retu
5400: 72 6e 20 66 75 6e 63 0a 0a 20 20 20 20 64 65 66  rn func..    def
5410: 20 67 65 74 5f 63 61 6c 6c 62 61 63 6b 5f 61 72   get_callback_ar
5420: 67 73 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20  gs(self):.      
5430: 20 20 27 27 27 20 52 65 74 75 72 6e 20 61 20 6c    ''' Return a l
5440: 69 73 74 20 6f 66 20 61 72 67 75 6d 65 6e 74 20  ist of argument 
5450: 6e 61 6d 65 73 20 74 68 65 20 63 61 6c 6c 62 61  names the callba
5460: 63 6b 20 28 6d 6f 73 74 20 6c 69 6b 65 6c 79 29  ck (most likely)
5470: 20 61 63 63 65 70 74 73 0a 20 20 20 20 20 20 20   accepts.       
5480: 20 20 20 20 20 61 73 20 6b 65 79 77 6f 72 64 20       as keyword 
5490: 61 72 67 75 6d 65 6e 74 73 2e 20 49 66 20 74 68  arguments. If th
54a0: 65 20 63 61 6c 6c 62 61 63 6b 20 69 73 20 61 20  e callback is a 
54b0: 64 65 63 6f 72 61 74 65 64 20 66 75 6e 63 74 69  decorated functi
54c0: 6f 6e 2c 20 74 72 79 0a 20 20 20 20 20 20 20 20  on, try.        
54d0: 20 20 20 20 74 6f 20 72 65 63 6f 76 65 72 20 74      to recover t
54e0: 68 65 20 6f 72 69 67 69 6e 61 6c 20 66 75 6e 63  he original func
54f0: 74 69 6f 6e 20 62 65 66 6f 72 65 20 69 6e 73 70  tion before insp
5500: 65 63 74 69 6f 6e 2e 20 27 27 27 0a 20 20 20 20  ection. '''.    
5510: 20 20 20 20 72 65 74 75 72 6e 20 67 65 74 61 72      return getar
5520: 67 73 70 65 63 28 73 65 6c 66 2e 67 65 74 5f 75  gspec(self.get_u
5530: 6e 64 65 63 6f 72 61 74 65 64 5f 63 61 6c 6c 62  ndecorated_callb
5540: 61 63 6b 28 29 29 5b 30 5d 0a 0a 20 20 20 20 64  ack())[0]..    d
5550: 65 66 20 67 65 74 5f 63 6f 6e 66 69 67 28 73 65  ef get_config(se
5560: 6c 66 2c 20 6b 65 79 2c 20 64 65 66 61 75 6c 74  lf, key, default
5570: 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20 20  =None):.        
5580: 27 27 27 20 4c 6f 6f 6b 75 70 20 61 20 63 6f 6e  ''' Lookup a con
5590: 66 69 67 20 66 69 65 6c 64 20 61 6e 64 20 72 65  fig field and re
55a0: 74 75 72 6e 20 69 74 73 20 76 61 6c 75 65 2c 20  turn its value, 
55b0: 66 69 72 73 74 20 63 68 65 63 6b 69 6e 67 20 74  first checking t
55c0: 68 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  he.            r
55d0: 6f 75 74 65 2e 63 6f 6e 66 69 67 2c 20 74 68 65  oute.config, the
55e0: 6e 20 72 6f 75 74 65 2e 61 70 70 2e 63 6f 6e 66  n route.app.conf
55f0: 69 67 2e 27 27 27 0a 20 20 20 20 20 20 20 20 66  ig.'''.        f
5600: 6f 72 20 63 6f 6e 66 20 69 6e 20 28 73 65 6c 66  or conf in (self
5610: 2e 63 6f 6e 66 69 67 2c 20 73 65 6c 66 2e 61 70  .config, self.ap
5620: 70 2e 63 6f 6e 69 66 67 29 3a 0a 20 20 20 20 20  p.conifg):.     
5630: 20 20 20 20 20 20 20 69 66 20 6b 65 79 20 69 6e         if key in
5640: 20 63 6f 6e 66 3a 20 72 65 74 75 72 6e 20 63 6f   conf: return co
5650: 6e 66 5b 6b 65 79 5d 0a 20 20 20 20 20 20 20 20  nf[key].        
5660: 72 65 74 75 72 6e 20 64 65 66 61 75 6c 74 0a 0a  return default..
5670: 20 20 20 20 64 65 66 20 5f 5f 72 65 70 72 5f 5f      def __repr__
5680: 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20  (self):.        
5690: 63 62 20 3d 20 73 65 6c 66 2e 67 65 74 5f 75 6e  cb = self.get_un
56a0: 64 65 63 6f 72 61 74 65 64 5f 63 61 6c 6c 62 61  decorated_callba
56b0: 63 6b 28 29 0a 20 20 20 20 20 20 20 20 72 65 74  ck().        ret
56c0: 75 72 6e 20 27 3c 25 73 20 25 72 20 25 72 3e 27  urn '<%s %r %r>'
56d0: 20 25 20 28 73 65 6c 66 2e 6d 65 74 68 6f 64 2c   % (self.method,
56e0: 20 73 65 6c 66 2e 72 75 6c 65 2c 20 63 62 29 0a   self.rule, cb).
56f0: 0a 0a 0a 0a 0a 0a 23 23 23 23 23 23 23 23 23 23  ......##########
5700: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5710: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5720: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5730: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5740: 23 23 23 23 23 0a 23 20 41 70 70 6c 69 63 61 74  #####.# Applicat
5750: 69 6f 6e 20 4f 62 6a 65 63 74 20 23 23 23 23 23  ion Object #####
5760: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5770: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5780: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
5790: 23 23 23 23 23 23 0a 23 23 23 23 23 23 23 23 23  ######.#########
57a0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
57b0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
57c0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
57d0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
57e0: 23 23 23 23 23 23 0a 0a 0a 63 6c 61 73 73 20 42  ######...class B
57f0: 6f 74 74 6c 65 28 6f 62 6a 65 63 74 29 3a 0a 20  ottle(object):. 
5800: 20 20 20 22 22 22 20 45 61 63 68 20 42 6f 74 74     """ Each Bott
5810: 6c 65 20 6f 62 6a 65 63 74 20 72 65 70 72 65 73  le object repres
5820: 65 6e 74 73 20 61 20 73 69 6e 67 6c 65 2c 20 64  ents a single, d
5830: 69 73 74 69 6e 63 74 20 77 65 62 20 61 70 70 6c  istinct web appl
5840: 69 63 61 74 69 6f 6e 20 61 6e 64 0a 20 20 20 20  ication and.    
5850: 20 20 20 20 63 6f 6e 73 69 73 74 73 20 6f 66 20      consists of 
5860: 72 6f 75 74 65 73 2c 20 63 61 6c 6c 62 61 63 6b  routes, callback
5870: 73 2c 20 70 6c 75 67 69 6e 73 2c 20 72 65 73 6f  s, plugins, reso
5880: 75 72 63 65 73 20 61 6e 64 20 63 6f 6e 66 69 67  urces and config
5890: 75 72 61 74 69 6f 6e 2e 0a 20 20 20 20 20 20 20  uration..       
58a0: 20 49 6e 73 74 61 6e 63 65 73 20 61 72 65 20 63   Instances are c
58b0: 61 6c 6c 61 62 6c 65 20 57 53 47 49 20 61 70 70  allable WSGI app
58c0: 6c 69 63 61 74 69 6f 6e 73 2e 0a 0a 20 20 20 20  lications...    
58d0: 20 20 20 20 3a 70 61 72 61 6d 20 63 61 74 63 68      :param catch
58e0: 61 6c 6c 3a 20 49 66 20 74 72 75 65 20 28 64 65  all: If true (de
58f0: 66 61 75 6c 74 29 2c 20 68 61 6e 64 6c 65 20 61  fault), handle a
5900: 6c 6c 20 65 78 63 65 70 74 69 6f 6e 73 2e 20 54  ll exceptions. T
5910: 75 72 6e 20 6f 66 66 20 74 6f 0a 20 20 20 20 20  urn off to.     
5920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5930: 20 20 20 20 6c 65 74 20 64 65 62 75 67 67 69 6e      let debuggin
5940: 67 20 6d 69 64 64 6c 65 77 61 72 65 20 68 61 6e  g middleware han
5950: 64 6c 65 20 65 78 63 65 70 74 69 6f 6e 73 2e 0a  dle exceptions..
5960: 20 20 20 20 22 22 22 0a 0a 20 20 20 20 64 65 66      """..    def
5970: 20 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20   __init__(self, 
5980: 63 61 74 63 68 61 6c 6c 3d 54 72 75 65 2c 20 61  catchall=True, a
5990: 75 74 6f 6a 73 6f 6e 3d 54 72 75 65 29 3a 0a 0a  utojson=True):..
59a0: 20 20 20 20 20 20 20 20 23 3a 20 41 20 3a 63 6c          #: A :cl
59b0: 61 73 73 3a 60 43 6f 6e 66 69 67 44 69 63 74 60  ass:`ConfigDict`
59c0: 20 66 6f 72 20 61 70 70 20 73 70 65 63 69 66 69   for app specifi
59d0: 63 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e 2e  c configuration.
59e0: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 63 6f  .        self.co
59f0: 6e 66 69 67 20 3d 20 43 6f 6e 66 69 67 44 69 63  nfig = ConfigDic
5a00: 74 28 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  t().        self
5a10: 2e 63 6f 6e 66 69 67 2e 5f 6f 6e 5f 63 68 61 6e  .config._on_chan
5a20: 67 65 20 3d 20 66 75 6e 63 74 6f 6f 6c 73 2e 70  ge = functools.p
5a30: 61 72 74 69 61 6c 28 73 65 6c 66 2e 74 72 69 67  artial(self.trig
5a40: 67 65 72 5f 68 6f 6f 6b 2c 20 27 63 6f 6e 66 69  ger_hook, 'confi
5a50: 67 27 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  g').        self
5a60: 2e 63 6f 6e 66 69 67 2e 6d 65 74 61 5f 73 65 74  .config.meta_set
5a70: 28 27 61 75 74 6f 6a 73 6f 6e 27 2c 20 27 76 61  ('autojson', 'va
5a80: 6c 69 64 61 74 65 27 2c 20 62 6f 6f 6c 29 0a 20  lidate', bool). 
5a90: 20 20 20 20 20 20 20 73 65 6c 66 2e 63 6f 6e 66         self.conf
5aa0: 69 67 2e 6d 65 74 61 5f 73 65 74 28 27 63 61 74  ig.meta_set('cat
5ab0: 63 68 61 6c 6c 27 2c 20 27 76 61 6c 69 64 61 74  chall', 'validat
5ac0: 65 27 2c 20 62 6f 6f 6c 29 0a 20 20 20 20 20 20  e', bool).      
5ad0: 20 20 73 65 6c 66 2e 63 6f 6e 66 69 67 5b 27 63    self.config['c
5ae0: 61 74 63 68 61 6c 6c 27 5d 20 3d 20 63 61 74 63  atchall'] = catc
5af0: 68 61 6c 6c 0a 20 20 20 20 20 20 20 20 73 65 6c  hall.        sel
5b00: 66 2e 63 6f 6e 66 69 67 5b 27 61 75 74 6f 6a 73  f.config['autojs
5b10: 6f 6e 27 5d 20 3d 20 61 75 74 6f 6a 73 6f 6e 0a  on'] = autojson.
5b20: 0a 20 20 20 20 20 20 20 20 23 3a 20 41 20 3a 63  .        #: A :c
5b30: 6c 61 73 73 3a 60 52 65 73 6f 75 72 63 65 4d 61  lass:`ResourceMa
5b40: 6e 61 67 65 72 60 20 66 6f 72 20 61 70 70 6c 69  nager` for appli
5b50: 63 61 74 69 6f 6e 20 66 69 6c 65 73 0a 20 20 20  cation files.   
5b60: 20 20 20 20 20 73 65 6c 66 2e 72 65 73 6f 75 72       self.resour
5b70: 63 65 73 20 3d 20 52 65 73 6f 75 72 63 65 4d 61  ces = ResourceMa
5b80: 6e 61 67 65 72 28 29 0a 0a 20 20 20 20 20 20 20  nager()..       
5b90: 20 73 65 6c 66 2e 72 6f 75 74 65 73 20 3d 20 5b   self.routes = [
5ba0: 5d 20 23 20 4c 69 73 74 20 6f 66 20 69 6e 73 74  ] # List of inst
5bb0: 61 6c 6c 65 64 20 3a 63 6c 61 73 73 3a 60 52 6f  alled :class:`Ro
5bc0: 75 74 65 60 20 69 6e 73 74 61 6e 63 65 73 2e 0a  ute` instances..
5bd0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 72 6f 75          self.rou
5be0: 74 65 72 20 3d 20 52 6f 75 74 65 72 28 29 20 23  ter = Router() #
5bf0: 20 4d 61 70 73 20 72 65 71 75 65 73 74 73 20 74   Maps requests t
5c00: 6f 20 3a 63 6c 61 73 73 3a 60 52 6f 75 74 65 60  o :class:`Route`
5c10: 20 69 6e 73 74 61 6e 63 65 73 2e 0a 20 20 20 20   instances..    
5c20: 20 20 20 20 73 65 6c 66 2e 65 72 72 6f 72 5f 68      self.error_h
5c30: 61 6e 64 6c 65 72 20 3d 20 7b 7d 0a 0a 20 20 20  andler = {}..   
5c40: 20 20 20 20 20 23 20 43 6f 72 65 20 70 6c 75 67       # Core plug
5c50: 69 6e 73 0a 20 20 20 20 20 20 20 20 73 65 6c 66  ins.        self
5c60: 2e 70 6c 75 67 69 6e 73 20 3d 20 5b 5d 20 23 20  .plugins = [] # 
5c70: 4c 69 73 74 20 6f 66 20 69 6e 73 74 61 6c 6c 65  List of installe
5c80: 64 20 70 6c 75 67 69 6e 73 2e 0a 20 20 20 20 20  d plugins..     
5c90: 20 20 20 69 66 20 73 65 6c 66 2e 63 6f 6e 66 69     if self.confi
5ca0: 67 5b 27 61 75 74 6f 6a 73 6f 6e 27 5d 3a 0a 20  g['autojson']:. 
5cb0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
5cc0: 69 6e 73 74 61 6c 6c 28 4a 53 4f 4e 50 6c 75 67  install(JSONPlug
5cd0: 69 6e 28 29 29 0a 20 20 20 20 20 20 20 20 73 65  in()).        se
5ce0: 6c 66 2e 69 6e 73 74 61 6c 6c 28 54 65 6d 70 6c  lf.install(Templ
5cf0: 61 74 65 50 6c 75 67 69 6e 28 29 29 0a 0a 20 20  atePlugin())..  
5d00: 20 20 23 3a 20 49 66 20 74 72 75 65 2c 20 6d 6f    #: If true, mo
5d10: 73 74 20 65 78 63 65 70 74 69 6f 6e 73 20 61 72  st exceptions ar
5d20: 65 20 63 61 75 67 68 74 20 61 6e 64 20 72 65 74  e caught and ret
5d30: 75 72 6e 65 64 20 61 73 20 3a 65 78 63 3a 60 48  urned as :exc:`H
5d40: 54 54 50 45 72 72 6f 72 60 0a 20 20 20 20 63 61  TTPError`.    ca
5d50: 74 63 68 61 6c 6c 20 3d 20 44 69 63 74 50 72 6f  tchall = DictPro
5d60: 70 65 72 74 79 28 27 63 6f 6e 66 69 67 27 2c 20  perty('config', 
5d70: 27 63 61 74 63 68 61 6c 6c 27 29 0a 0a 20 20 20  'catchall')..   
5d80: 20 5f 5f 68 6f 6f 6b 5f 6e 61 6d 65 73 20 3d 20   __hook_names = 
5d90: 27 62 65 66 6f 72 65 5f 72 65 71 75 65 73 74 27  'before_request'
5da0: 2c 20 27 61 66 74 65 72 5f 72 65 71 75 65 73 74  , 'after_request
5db0: 27 2c 20 27 61 70 70 5f 72 65 73 65 74 27 2c 20  ', 'app_reset', 
5dc0: 27 63 6f 6e 66 69 67 27 0a 20 20 20 20 5f 5f 68  'config'.    __h
5dd0: 6f 6f 6b 5f 72 65 76 65 72 73 65 64 20 3d 20 27  ook_reversed = '
5de0: 61 66 74 65 72 5f 72 65 71 75 65 73 74 27 0a 0a  after_request'..
5df0: 20 20 20 20 40 63 61 63 68 65 64 5f 70 72 6f 70      @cached_prop
5e00: 65 72 74 79 0a 20 20 20 20 64 65 66 20 5f 68 6f  erty.    def _ho
5e10: 6f 6b 73 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  oks(self):.     
5e20: 20 20 20 72 65 74 75 72 6e 20 64 69 63 74 28 28     return dict((
5e30: 6e 61 6d 65 2c 20 5b 5d 29 20 66 6f 72 20 6e 61  name, []) for na
5e40: 6d 65 20 69 6e 20 73 65 6c 66 2e 5f 5f 68 6f 6f  me in self.__hoo
5e50: 6b 5f 6e 61 6d 65 73 29 0a 0a 20 20 20 20 64 65  k_names)..    de
5e60: 66 20 61 64 64 5f 68 6f 6f 6b 28 73 65 6c 66 2c  f add_hook(self,
5e70: 20 6e 61 6d 65 2c 20 66 75 6e 63 29 3a 0a 20 20   name, func):.  
5e80: 20 20 20 20 20 20 27 27 27 20 41 74 74 61 63 68        ''' Attach
5e90: 20 61 20 63 61 6c 6c 62 61 63 6b 20 74 6f 20 61   a callback to a
5ea0: 20 68 6f 6f 6b 2e 20 54 68 72 65 65 20 68 6f 6f   hook. Three hoo
5eb0: 6b 73 20 61 72 65 20 63 75 72 72 65 6e 74 6c 79  ks are currently
5ec0: 20 69 6d 70 6c 65 6d 65 6e 74 65 64 3a 0a 0a 20   implemented:.. 
5ed0: 20 20 20 20 20 20 20 20 20 20 20 62 65 66 6f 72             befor
5ee0: 65 5f 72 65 71 75 65 73 74 0a 20 20 20 20 20 20  e_request.      
5ef0: 20 20 20 20 20 20 20 20 20 20 45 78 65 63 75 74            Execut
5f00: 65 64 20 6f 6e 63 65 20 62 65 66 6f 72 65 20 65  ed once before e
5f10: 61 63 68 20 72 65 71 75 65 73 74 2e 20 54 68 65  ach request. The
5f20: 20 72 65 71 75 65 73 74 20 63 6f 6e 74 65 78 74   request context
5f30: 20 69 73 0a 20 20 20 20 20 20 20 20 20 20 20 20   is.            
5f40: 20 20 20 20 61 76 61 69 6c 61 62 6c 65 2c 20 62      available, b
5f50: 75 74 20 6e 6f 20 72 6f 75 74 69 6e 67 20 68 61  ut no routing ha
5f60: 73 20 68 61 70 70 65 6e 65 64 20 79 65 74 2e 0a  s happened yet..
5f70: 20 20 20 20 20 20 20 20 20 20 20 20 61 66 74 65              afte
5f80: 72 5f 72 65 71 75 65 73 74 0a 20 20 20 20 20 20  r_request.      
5f90: 20 20 20 20 20 20 20 20 20 20 45 78 65 63 75 74            Execut
5fa0: 65 64 20 6f 6e 63 65 20 61 66 74 65 72 20 65 61  ed once after ea
5fb0: 63 68 20 72 65 71 75 65 73 74 20 72 65 67 61 72  ch request regar
5fc0: 64 6c 65 73 73 20 6f 66 20 69 74 73 20 6f 75 74  dless of its out
5fd0: 63 6f 6d 65 2e 0a 20 20 20 20 20 20 20 20 20 20  come..          
5fe0: 20 20 61 70 70 5f 72 65 73 65 74 0a 20 20 20 20    app_reset.    
5ff0: 20 20 20 20 20 20 20 20 20 20 20 20 43 61 6c 6c              Call
6000: 65 64 20 77 68 65 6e 65 76 65 72 20 3a 6d 65 74  ed whenever :met
6010: 68 3a 60 42 6f 74 74 6c 65 2e 72 65 73 65 74 60  h:`Bottle.reset`
6020: 20 69 73 20 63 61 6c 6c 65 64 2e 0a 20 20 20 20   is called..    
6030: 20 20 20 20 27 27 27 0a 20 20 20 20 20 20 20 20      '''.        
6040: 69 66 20 6e 61 6d 65 20 69 6e 20 73 65 6c 66 2e  if name in self.
6050: 5f 5f 68 6f 6f 6b 5f 72 65 76 65 72 73 65 64 3a  __hook_reversed:
6060: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
6070: 66 2e 5f 68 6f 6f 6b 73 5b 6e 61 6d 65 5d 2e 69  f._hooks[name].i
6080: 6e 73 65 72 74 28 30 2c 20 66 75 6e 63 29 0a 20  nsert(0, func). 
6090: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
60a0: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 68           self._h
60b0: 6f 6f 6b 73 5b 6e 61 6d 65 5d 2e 61 70 70 65 6e  ooks[name].appen
60c0: 64 28 66 75 6e 63 29 0a 0a 20 20 20 20 64 65 66  d(func)..    def
60d0: 20 72 65 6d 6f 76 65 5f 68 6f 6f 6b 28 73 65 6c   remove_hook(sel
60e0: 66 2c 20 6e 61 6d 65 2c 20 66 75 6e 63 29 3a 0a  f, name, func):.
60f0: 20 20 20 20 20 20 20 20 27 27 27 20 52 65 6d 6f          ''' Remo
6100: 76 65 20 61 20 63 61 6c 6c 62 61 63 6b 20 66 72  ve a callback fr
6110: 6f 6d 20 61 20 68 6f 6f 6b 2e 20 27 27 27 0a 20  om a hook. '''. 
6120: 20 20 20 20 20 20 20 69 66 20 6e 61 6d 65 20 69         if name i
6130: 6e 20 73 65 6c 66 2e 5f 68 6f 6f 6b 73 20 61 6e  n self._hooks an
6140: 64 20 66 75 6e 63 20 69 6e 20 73 65 6c 66 2e 5f  d func in self._
6150: 68 6f 6f 6b 73 5b 6e 61 6d 65 5d 3a 0a 20 20 20  hooks[name]:.   
6160: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 68           self._h
6170: 6f 6f 6b 73 5b 6e 61 6d 65 5d 2e 72 65 6d 6f 76  ooks[name].remov
6180: 65 28 66 75 6e 63 29 0a 20 20 20 20 20 20 20 20  e(func).        
6190: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
61a0: 0a 20 20 20 20 64 65 66 20 74 72 69 67 67 65 72  .    def trigger
61b0: 5f 68 6f 6f 6b 28 73 65 6c 66 2c 20 5f 5f 6e 61  _hook(self, __na
61c0: 6d 65 2c 20 2a 61 72 67 73 2c 20 2a 2a 6b 77 61  me, *args, **kwa
61d0: 72 67 73 29 3a 0a 20 20 20 20 20 20 20 20 27 27  rgs):.        ''
61e0: 27 20 54 72 69 67 67 65 72 20 61 20 68 6f 6f 6b  ' Trigger a hook
61f0: 20 61 6e 64 20 72 65 74 75 72 6e 20 61 20 6c 69   and return a li
6200: 73 74 20 6f 66 20 72 65 73 75 6c 74 73 2e 20 27  st of results. '
6210: 27 27 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ''.        retur
6220: 6e 20 5b 68 6f 6f 6b 28 2a 61 72 67 73 2c 20 2a  n [hook(*args, *
6230: 2a 6b 77 61 72 67 73 29 20 66 6f 72 20 68 6f 6f  *kwargs) for hoo
6240: 6b 20 69 6e 20 73 65 6c 66 2e 5f 68 6f 6f 6b 73  k in self._hooks
6250: 5b 5f 5f 6e 61 6d 65 5d 5b 3a 5d 5d 0a 0a 20 20  [__name][:]]..  
6260: 20 20 64 65 66 20 68 6f 6f 6b 28 73 65 6c 66 2c    def hook(self,
6270: 20 6e 61 6d 65 29 3a 0a 20 20 20 20 20 20 20 20   name):.        
6280: 22 22 22 20 52 65 74 75 72 6e 20 61 20 64 65 63  """ Return a dec
6290: 6f 72 61 74 6f 72 20 74 68 61 74 20 61 74 74 61  orator that atta
62a0: 63 68 65 73 20 61 20 63 61 6c 6c 62 61 63 6b 20  ches a callback 
62b0: 74 6f 20 61 20 68 6f 6f 6b 2e 20 53 65 65 0a 20  to a hook. See. 
62c0: 20 20 20 20 20 20 20 20 20 20 20 3a 6d 65 74 68             :meth
62d0: 3a 60 61 64 64 5f 68 6f 6f 6b 60 20 66 6f 72 20  :`add_hook` for 
62e0: 64 65 74 61 69 6c 73 2e 22 22 22 0a 20 20 20 20  details.""".    
62f0: 20 20 20 20 64 65 66 20 64 65 63 6f 72 61 74 6f      def decorato
6300: 72 28 66 75 6e 63 29 3a 0a 20 20 20 20 20 20 20  r(func):.       
6310: 20 20 20 20 20 73 65 6c 66 2e 61 64 64 5f 68 6f       self.add_ho
6320: 6f 6b 28 6e 61 6d 65 2c 20 66 75 6e 63 29 0a 20  ok(name, func). 
6330: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
6340: 6e 20 66 75 6e 63 0a 20 20 20 20 20 20 20 20 72  n func.        r
6350: 65 74 75 72 6e 20 64 65 63 6f 72 61 74 6f 72 0a  eturn decorator.
6360: 0a 20 20 20 20 64 65 66 20 6d 6f 75 6e 74 28 73  .    def mount(s
6370: 65 6c 66 2c 20 70 72 65 66 69 78 2c 20 61 70 70  elf, prefix, app
6380: 2c 20 2a 2a 6f 70 74 69 6f 6e 73 29 3a 0a 20 20  , **options):.  
6390: 20 20 20 20 20 20 27 27 27 20 4d 6f 75 6e 74 20        ''' Mount 
63a0: 61 6e 20 61 70 70 6c 69 63 61 74 69 6f 6e 20 28  an application (
63b0: 3a 63 6c 61 73 73 3a 60 42 6f 74 74 6c 65 60 20  :class:`Bottle` 
63c0: 6f 72 20 70 6c 61 69 6e 20 57 53 47 49 29 20 74  or plain WSGI) t
63d0: 6f 20 61 20 73 70 65 63 69 66 69 63 0a 20 20 20  o a specific.   
63e0: 20 20 20 20 20 20 20 20 20 55 52 4c 20 70 72 65           URL pre
63f0: 66 69 78 2e 20 45 78 61 6d 70 6c 65 3a 3a 0a 0a  fix. Example::..
6400: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6410: 72 6f 6f 74 5f 61 70 70 2e 6d 6f 75 6e 74 28 27  root_app.mount('
6420: 2f 61 64 6d 69 6e 2f 27 2c 20 61 64 6d 69 6e 5f  /admin/', admin_
6430: 61 70 70 29 0a 0a 20 20 20 20 20 20 20 20 20 20  app)..          
6440: 20 20 3a 70 61 72 61 6d 20 70 72 65 66 69 78 3a    :param prefix:
6450: 20 70 61 74 68 20 70 72 65 66 69 78 20 6f 72 20   path prefix or 
6460: 60 6d 6f 75 6e 74 2d 70 6f 69 6e 74 60 2e 20 49  `mount-point`. I
6470: 66 20 69 74 20 65 6e 64 73 20 69 6e 20 61 20 73  f it ends in a s
6480: 6c 61 73 68 2c 0a 20 20 20 20 20 20 20 20 20 20  lash,.          
6490: 20 20 20 20 20 20 74 68 61 74 20 73 6c 61 73 68        that slash
64a0: 20 69 73 20 6d 61 6e 64 61 74 6f 72 79 2e 0a 20   is mandatory.. 
64b0: 20 20 20 20 20 20 20 20 20 20 20 3a 70 61 72 61             :para
64c0: 6d 20 61 70 70 3a 20 61 6e 20 69 6e 73 74 61 6e  m app: an instan
64d0: 63 65 20 6f 66 20 3a 63 6c 61 73 73 3a 60 42 6f  ce of :class:`Bo
64e0: 74 74 6c 65 60 20 6f 72 20 61 20 57 53 47 49 20  ttle` or a WSGI 
64f0: 61 70 70 6c 69 63 61 74 69 6f 6e 2e 0a 0a 20 20  application...  
6500: 20 20 20 20 20 20 20 20 20 20 41 6c 6c 20 6f 74            All ot
6510: 68 65 72 20 70 61 72 61 6d 65 74 65 72 73 20 61  her parameters a
6520: 72 65 20 70 61 73 73 65 64 20 74 6f 20 74 68 65  re passed to the
6530: 20 75 6e 64 65 72 6c 79 69 6e 67 20 3a 6d 65 74   underlying :met
6540: 68 3a 60 72 6f 75 74 65 60 20 63 61 6c 6c 2e 0a  h:`route` call..
6550: 20 20 20 20 20 20 20 20 27 27 27 0a 20 20 20 20          '''.    
6560: 20 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63      if isinstanc
6570: 65 28 61 70 70 2c 20 62 61 73 65 73 74 72 69 6e  e(app, basestrin
6580: 67 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  g):.            
6590: 64 65 70 72 28 27 50 61 72 61 6d 65 74 65 72 20  depr('Parameter 
65a0: 6f 72 64 65 72 20 6f 66 20 42 6f 74 74 6c 65 2e  order of Bottle.
65b0: 6d 6f 75 6e 74 28 29 20 63 68 61 6e 67 65 64 2e  mount() changed.
65c0: 27 2c 20 54 72 75 65 29 20 23 20 30 2e 31 30 0a  ', True) # 0.10.
65d0: 0a 20 20 20 20 20 20 20 20 73 65 67 6d 65 6e 74  .        segment
65e0: 73 20 3d 20 5b 70 20 66 6f 72 20 70 20 69 6e 20  s = [p for p in 
65f0: 70 72 65 66 69 78 2e 73 70 6c 69 74 28 27 2f 27  prefix.split('/'
6600: 29 20 69 66 20 70 5d 0a 20 20 20 20 20 20 20 20  ) if p].        
6610: 69 66 20 6e 6f 74 20 73 65 67 6d 65 6e 74 73 3a  if not segments:
6620: 20 72 61 69 73 65 20 56 61 6c 75 65 45 72 72 6f   raise ValueErro
6630: 72 28 27 45 6d 70 74 79 20 70 61 74 68 20 70 72  r('Empty path pr
6640: 65 66 69 78 2e 27 29 0a 20 20 20 20 20 20 20 20  efix.').        
6650: 70 61 74 68 5f 64 65 70 74 68 20 3d 20 6c 65 6e  path_depth = len
6660: 28 73 65 67 6d 65 6e 74 73 29 0a 0a 20 20 20 20  (segments)..    
6670: 20 20 20 20 64 65 66 20 6d 6f 75 6e 74 70 6f 69      def mountpoi
6680: 6e 74 5f 77 72 61 70 70 65 72 28 29 3a 0a 20 20  nt_wrapper():.  
6690: 20 20 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20            try:. 
66a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
66b0: 65 71 75 65 73 74 2e 70 61 74 68 5f 73 68 69 66  equest.path_shif
66c0: 74 28 70 61 74 68 5f 64 65 70 74 68 29 0a 20 20  t(path_depth).  
66d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 73                rs
66e0: 20 3d 20 48 54 54 50 52 65 73 70 6f 6e 73 65 28   = HTTPResponse(
66f0: 5b 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  []).            
6700: 20 20 20 20 64 65 66 20 73 74 61 72 74 5f 72 65      def start_re
6710: 73 70 6f 6e 73 65 28 73 74 61 74 75 73 2c 20 68  sponse(status, h
6720: 65 61 64 65 72 6c 69 73 74 2c 20 65 78 63 5f 69  eaderlist, exc_i
6730: 6e 66 6f 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20  nfo=None):.     
6740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
6750: 66 20 65 78 63 5f 69 6e 66 6f 3a 0a 20 20 20 20  f exc_info:.    
6760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6770: 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
6780: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6790: 20 20 20 20 20 5f 72 61 69 73 65 28 2a 65 78 63       _raise(*exc
67a0: 5f 69 6e 66 6f 29 0a 20 20 20 20 20 20 20 20 20  _info).         
67b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
67c0: 69 6e 61 6c 6c 79 3a 0a 20 20 20 20 20 20 20 20  inally:.        
67d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
67e0: 20 20 20 20 65 78 63 5f 69 6e 66 6f 20 3d 20 4e      exc_info = N
67f0: 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  one.            
6800: 20 20 20 20 20 20 20 20 72 73 2e 73 74 61 74 75          rs.statu
6810: 73 20 3d 20 73 74 61 74 75 73 0a 20 20 20 20 20  s = status.     
6820: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
6830: 6f 72 20 6e 61 6d 65 2c 20 76 61 6c 75 65 20 69  or name, value i
6840: 6e 20 68 65 61 64 65 72 6c 69 73 74 3a 20 72 73  n headerlist: rs
6850: 2e 61 64 64 5f 68 65 61 64 65 72 28 6e 61 6d 65  .add_header(name
6860: 2c 20 76 61 6c 75 65 29 0a 20 20 20 20 20 20 20  , value).       
6870: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
6880: 75 72 6e 20 72 73 2e 62 6f 64 79 2e 61 70 70 65  urn rs.body.appe
6890: 6e 64 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  nd.             
68a0: 20 20 20 62 6f 64 79 20 3d 20 61 70 70 28 72 65     body = app(re
68b0: 71 75 65 73 74 2e 65 6e 76 69 72 6f 6e 2c 20 73  quest.environ, s
68c0: 74 61 72 74 5f 72 65 73 70 6f 6e 73 65 29 0a 20  tart_response). 
68d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
68e0: 66 20 62 6f 64 79 20 61 6e 64 20 72 73 2e 62 6f  f body and rs.bo
68f0: 64 79 3a 20 62 6f 64 79 20 3d 20 69 74 65 72 74  dy: body = itert
6900: 6f 6f 6c 73 2e 63 68 61 69 6e 28 72 73 2e 62 6f  ools.chain(rs.bo
6910: 64 79 2c 20 62 6f 64 79 29 0a 20 20 20 20 20 20  dy, body).      
6920: 20 20 20 20 20 20 20 20 20 20 72 73 2e 62 6f 64            rs.bod
6930: 79 20 3d 20 62 6f 64 79 20 6f 72 20 72 73 2e 62  y = body or rs.b
6940: 6f 64 79 0a 20 20 20 20 20 20 20 20 20 20 20 20  ody.            
6950: 20 20 20 20 72 65 74 75 72 6e 20 72 73 0a 20 20      return rs.  
6960: 20 20 20 20 20 20 20 20 20 20 66 69 6e 61 6c 6c            finall
6970: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y:.             
6980: 20 20 20 72 65 71 75 65 73 74 2e 70 61 74 68 5f     request.path_
6990: 73 68 69 66 74 28 2d 70 61 74 68 5f 64 65 70 74  shift(-path_dept
69a0: 68 29 0a 0a 20 20 20 20 20 20 20 20 6f 70 74 69  h)..        opti
69b0: 6f 6e 73 2e 73 65 74 64 65 66 61 75 6c 74 28 27  ons.setdefault('
69c0: 73 6b 69 70 27 2c 20 54 72 75 65 29 0a 20 20 20  skip', True).   
69d0: 20 20 20 20 20 6f 70 74 69 6f 6e 73 2e 73 65 74       options.set
69e0: 64 65 66 61 75 6c 74 28 27 6d 65 74 68 6f 64 27  default('method'
69f0: 2c 20 27 50 52 4f 58 59 27 29 0a 20 20 20 20 20  , 'PROXY').     
6a00: 20 20 20 6f 70 74 69 6f 6e 73 2e 73 65 74 64 65     options.setde
6a10: 66 61 75 6c 74 28 27 6d 6f 75 6e 74 70 6f 69 6e  fault('mountpoin
6a20: 74 27 2c 20 7b 27 70 72 65 66 69 78 27 3a 20 70  t', {'prefix': p
6a30: 72 65 66 69 78 2c 20 27 74 61 72 67 65 74 27 3a  refix, 'target':
6a40: 20 61 70 70 7d 29 0a 20 20 20 20 20 20 20 20 6f   app}).        o
6a50: 70 74 69 6f 6e 73 5b 27 63 61 6c 6c 62 61 63 6b  ptions['callback
6a60: 27 5d 20 3d 20 6d 6f 75 6e 74 70 6f 69 6e 74 5f  '] = mountpoint_
6a70: 77 72 61 70 70 65 72 0a 0a 20 20 20 20 20 20 20  wrapper..       
6a80: 20 73 65 6c 66 2e 72 6f 75 74 65 28 27 2f 25 73   self.route('/%s
6a90: 2f 3c 3a 72 65 3a 2e 2a 3e 27 20 25 20 27 2f 27  /<:re:.*>' % '/'
6aa0: 2e 6a 6f 69 6e 28 73 65 67 6d 65 6e 74 73 29 2c  .join(segments),
6ab0: 20 2a 2a 6f 70 74 69 6f 6e 73 29 0a 20 20 20 20   **options).    
6ac0: 20 20 20 20 69 66 20 6e 6f 74 20 70 72 65 66 69      if not prefi
6ad0: 78 2e 65 6e 64 73 77 69 74 68 28 27 2f 27 29 3a  x.endswith('/'):
6ae0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
6af0: 66 2e 72 6f 75 74 65 28 27 2f 27 20 2b 20 27 2f  f.route('/' + '/
6b00: 27 2e 6a 6f 69 6e 28 73 65 67 6d 65 6e 74 73 29  '.join(segments)
6b10: 2c 20 2a 2a 6f 70 74 69 6f 6e 73 29 0a 0a 20 20  , **options)..  
6b20: 20 20 64 65 66 20 6d 65 72 67 65 28 73 65 6c 66    def merge(self
6b30: 2c 20 72 6f 75 74 65 73 29 3a 0a 20 20 20 20 20  , routes):.     
6b40: 20 20 20 27 27 27 20 4d 65 72 67 65 20 74 68 65     ''' Merge the
6b50: 20 72 6f 75 74 65 73 20 6f 66 20 61 6e 6f 74 68   routes of anoth
6b60: 65 72 20 3a 63 6c 61 73 73 3a 60 42 6f 74 74 6c  er :class:`Bottl
6b70: 65 60 20 61 70 70 6c 69 63 61 74 69 6f 6e 20 6f  e` application o
6b80: 72 20 61 20 6c 69 73 74 20 6f 66 0a 20 20 20 20  r a list of.    
6b90: 20 20 20 20 20 20 20 20 3a 63 6c 61 73 73 3a 60          :class:`
6ba0: 52 6f 75 74 65 60 20 6f 62 6a 65 63 74 73 20 69  Route` objects i
6bb0: 6e 74 6f 20 74 68 69 73 20 61 70 70 6c 69 63 61  nto this applica
6bc0: 74 69 6f 6e 2e 20 54 68 65 20 72 6f 75 74 65 73  tion. The routes
6bd0: 20 6b 65 65 70 20 74 68 65 69 72 0a 20 20 20 20   keep their.    
6be0: 20 20 20 20 20 20 20 20 27 6f 77 6e 65 72 27 2c          'owner',
6bf0: 20 6d 65 61 6e 69 6e 67 20 74 68 61 74 20 74 68   meaning that th
6c00: 65 20 3a 64 61 74 61 3a 60 52 6f 75 74 65 2e 61  e :data:`Route.a
6c10: 70 70 60 20 61 74 74 72 69 62 75 74 65 20 69 73  pp` attribute is
6c20: 20 6e 6f 74 0a 20 20 20 20 20 20 20 20 20 20 20   not.           
6c30: 20 63 68 61 6e 67 65 64 2e 20 27 27 27 0a 20 20   changed. '''.  
6c40: 20 20 20 20 20 20 69 66 20 69 73 69 6e 73 74 61        if isinsta
6c50: 6e 63 65 28 72 6f 75 74 65 73 2c 20 42 6f 74 74  nce(routes, Bott
6c60: 6c 65 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  le):.           
6c70: 20 72 6f 75 74 65 73 20 3d 20 72 6f 75 74 65 73   routes = routes
6c80: 2e 72 6f 75 74 65 73 0a 20 20 20 20 20 20 20 20  .routes.        
6c90: 66 6f 72 20 72 6f 75 74 65 20 69 6e 20 72 6f 75  for route in rou
6ca0: 74 65 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20  tes:.           
6cb0: 20 73 65 6c 66 2e 61 64 64 5f 72 6f 75 74 65 28   self.add_route(
6cc0: 72 6f 75 74 65 29 0a 0a 20 20 20 20 64 65 66 20  route)..    def 
6cd0: 69 6e 73 74 61 6c 6c 28 73 65 6c 66 2c 20 70 6c  install(self, pl
6ce0: 75 67 69 6e 29 3a 0a 20 20 20 20 20 20 20 20 27  ugin):.        '
6cf0: 27 27 20 41 64 64 20 61 20 70 6c 75 67 69 6e 20  '' Add a plugin 
6d00: 74 6f 20 74 68 65 20 6c 69 73 74 20 6f 66 20 70  to the list of p
6d10: 6c 75 67 69 6e 73 20 61 6e 64 20 70 72 65 70 61  lugins and prepa
6d20: 72 65 20 69 74 20 66 6f 72 20 62 65 69 6e 67 0a  re it for being.
6d30: 20 20 20 20 20 20 20 20 20 20 20 20 61 70 70 6c              appl
6d40: 69 65 64 20 74 6f 20 61 6c 6c 20 72 6f 75 74 65  ied to all route
6d50: 73 20 6f 66 20 74 68 69 73 20 61 70 70 6c 69 63  s of this applic
6d60: 61 74 69 6f 6e 2e 20 41 20 70 6c 75 67 69 6e 20  ation. A plugin 
6d70: 6d 61 79 20 62 65 20 61 20 73 69 6d 70 6c 65 0a  may be a simple.
6d80: 20 20 20 20 20 20 20 20 20 20 20 20 64 65 63 6f              deco
6d90: 72 61 74 6f 72 20 6f 72 20 61 6e 20 6f 62 6a 65  rator or an obje
6da0: 63 74 20 74 68 61 74 20 69 6d 70 6c 65 6d 65 6e  ct that implemen
6db0: 74 73 20 74 68 65 20 3a 63 6c 61 73 73 3a 60 50  ts the :class:`P
6dc0: 6c 75 67 69 6e 60 20 41 50 49 2e 0a 20 20 20 20  lugin` API..    
6dd0: 20 20 20 20 27 27 27 0a 20 20 20 20 20 20 20 20      '''.        
6de0: 69 66 20 68 61 73 61 74 74 72 28 70 6c 75 67 69  if hasattr(plugi
6df0: 6e 2c 20 27 73 65 74 75 70 27 29 3a 20 70 6c 75  n, 'setup'): plu
6e00: 67 69 6e 2e 73 65 74 75 70 28 73 65 6c 66 29 0a  gin.setup(self).
6e10: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 63          if not c
6e20: 61 6c 6c 61 62 6c 65 28 70 6c 75 67 69 6e 29 20  allable(plugin) 
6e30: 61 6e 64 20 6e 6f 74 20 68 61 73 61 74 74 72 28  and not hasattr(
6e40: 70 6c 75 67 69 6e 2c 20 27 61 70 70 6c 79 27 29  plugin, 'apply')
6e50: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 61  :.            ra
6e60: 69 73 65 20 54 79 70 65 45 72 72 6f 72 28 22 50  ise TypeError("P
6e70: 6c 75 67 69 6e 73 20 6d 75 73 74 20 62 65 20 63  lugins must be c
6e80: 61 6c 6c 61 62 6c 65 20 6f 72 20 69 6d 70 6c 65  allable or imple
6e90: 6d 65 6e 74 20 2e 61 70 70 6c 79 28 29 22 29 0a  ment .apply()").
6ea0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 70 6c 75          self.plu
6eb0: 67 69 6e 73 2e 61 70 70 65 6e 64 28 70 6c 75 67  gins.append(plug
6ec0: 69 6e 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  in).        self
6ed0: 2e 72 65 73 65 74 28 29 0a 20 20 20 20 20 20 20  .reset().       
6ee0: 20 72 65 74 75 72 6e 20 70 6c 75 67 69 6e 0a 0a   return plugin..
6ef0: 20 20 20 20 64 65 66 20 75 6e 69 6e 73 74 61 6c      def uninstal
6f00: 6c 28 73 65 6c 66 2c 20 70 6c 75 67 69 6e 29 3a  l(self, plugin):
6f10: 0a 20 20 20 20 20 20 20 20 27 27 27 20 55 6e 69  .        ''' Uni
6f20: 6e 73 74 61 6c 6c 20 70 6c 75 67 69 6e 73 2e 20  nstall plugins. 
6f30: 50 61 73 73 20 61 6e 20 69 6e 73 74 61 6e 63 65  Pass an instance
6f40: 20 74 6f 20 72 65 6d 6f 76 65 20 61 20 73 70 65   to remove a spe
6f50: 63 69 66 69 63 20 70 6c 75 67 69 6e 2c 20 61 20  cific plugin, a 
6f60: 74 79 70 65 0a 20 20 20 20 20 20 20 20 20 20 20  type.           
6f70: 20 6f 62 6a 65 63 74 20 74 6f 20 72 65 6d 6f 76   object to remov
6f80: 65 20 61 6c 6c 20 70 6c 75 67 69 6e 73 20 74 68  e all plugins th
6f90: 61 74 20 6d 61 74 63 68 20 74 68 61 74 20 74 79  at match that ty
6fa0: 70 65 2c 20 61 20 73 74 72 69 6e 67 20 74 6f 20  pe, a string to 
6fb0: 72 65 6d 6f 76 65 0a 20 20 20 20 20 20 20 20 20  remove.         
6fc0: 20 20 20 61 6c 6c 20 70 6c 75 67 69 6e 73 20 77     all plugins w
6fd0: 69 74 68 20 61 20 6d 61 74 63 68 69 6e 67 20 60  ith a matching `
6fe0: 60 6e 61 6d 65 60 60 20 61 74 74 72 69 62 75 74  `name`` attribut
6ff0: 65 20 6f 72 20 60 60 54 72 75 65 60 60 20 74 6f  e or ``True`` to
7000: 20 72 65 6d 6f 76 65 20 61 6c 6c 0a 20 20 20 20   remove all.    
7010: 20 20 20 20 20 20 20 20 70 6c 75 67 69 6e 73 2e          plugins.
7020: 20 52 65 74 75 72 6e 20 74 68 65 20 6c 69 73 74   Return the list
7030: 20 6f 66 20 72 65 6d 6f 76 65 64 20 70 6c 75 67   of removed plug
7040: 69 6e 73 2e 20 27 27 27 0a 20 20 20 20 20 20 20  ins. '''.       
7050: 20 72 65 6d 6f 76 65 64 2c 20 72 65 6d 6f 76 65   removed, remove
7060: 20 3d 20 5b 5d 2c 20 70 6c 75 67 69 6e 0a 20 20   = [], plugin.  
7070: 20 20 20 20 20 20 66 6f 72 20 69 2c 20 70 6c 75        for i, plu
7080: 67 69 6e 20 69 6e 20 6c 69 73 74 28 65 6e 75 6d  gin in list(enum
7090: 65 72 61 74 65 28 73 65 6c 66 2e 70 6c 75 67 69  erate(self.plugi
70a0: 6e 73 29 29 5b 3a 3a 2d 31 5d 3a 0a 20 20 20 20  ns))[::-1]:.    
70b0: 20 20 20 20 20 20 20 20 69 66 20 72 65 6d 6f 76          if remov
70c0: 65 20 69 73 20 54 72 75 65 20 6f 72 20 72 65 6d  e is True or rem
70d0: 6f 76 65 20 69 73 20 70 6c 75 67 69 6e 20 6f 72  ove is plugin or
70e0: 20 72 65 6d 6f 76 65 20 69 73 20 74 79 70 65 28   remove is type(
70f0: 70 6c 75 67 69 6e 29 20 5c 0a 20 20 20 20 20 20  plugin) \.      
7100: 20 20 20 20 20 20 6f 72 20 67 65 74 61 74 74 72        or getattr
7110: 28 70 6c 75 67 69 6e 2c 20 27 6e 61 6d 65 27 2c  (plugin, 'name',
7120: 20 54 72 75 65 29 20 3d 3d 20 72 65 6d 6f 76 65   True) == remove
7130: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
7140: 20 20 72 65 6d 6f 76 65 64 2e 61 70 70 65 6e 64    removed.append
7150: 28 70 6c 75 67 69 6e 29 0a 20 20 20 20 20 20 20  (plugin).       
7160: 20 20 20 20 20 20 20 20 20 64 65 6c 20 73 65 6c           del sel
7170: 66 2e 70 6c 75 67 69 6e 73 5b 69 5d 0a 20 20 20  f.plugins[i].   
7180: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
7190: 68 61 73 61 74 74 72 28 70 6c 75 67 69 6e 2c 20  hasattr(plugin, 
71a0: 27 63 6c 6f 73 65 27 29 3a 20 70 6c 75 67 69 6e  'close'): plugin
71b0: 2e 63 6c 6f 73 65 28 29 0a 20 20 20 20 20 20 20  .close().       
71c0: 20 69 66 20 72 65 6d 6f 76 65 64 3a 20 73 65 6c   if removed: sel
71d0: 66 2e 72 65 73 65 74 28 29 0a 20 20 20 20 20 20  f.reset().      
71e0: 20 20 72 65 74 75 72 6e 20 72 65 6d 6f 76 65 64    return removed
71f0: 0a 0a 20 20 20 20 64 65 66 20 72 65 73 65 74 28  ..    def reset(
7200: 73 65 6c 66 2c 20 72 6f 75 74 65 3d 4e 6f 6e 65  self, route=None
7210: 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 52  ):.        ''' R
7220: 65 73 65 74 20 61 6c 6c 20 72 6f 75 74 65 73 20  eset all routes 
7230: 28 66 6f 72 63 65 20 70 6c 75 67 69 6e 73 20 74  (force plugins t
7240: 6f 20 62 65 20 72 65 2d 61 70 70 6c 69 65 64 29  o be re-applied)
7250: 20 61 6e 64 20 63 6c 65 61 72 20 61 6c 6c 0a 20   and clear all. 
7260: 20 20 20 20 20 20 20 20 20 20 20 63 61 63 68 65             cache
7270: 73 2e 20 49 66 20 61 6e 20 49 44 20 6f 72 20 72  s. If an ID or r
7280: 6f 75 74 65 20 6f 62 6a 65 63 74 20 69 73 20 67  oute object is g
7290: 69 76 65 6e 2c 20 6f 6e 6c 79 20 74 68 61 74 20  iven, only that 
72a0: 73 70 65 63 69 66 69 63 20 72 6f 75 74 65 0a 20  specific route. 
72b0: 20 20 20 20 20 20 20 20 20 20 20 69 73 20 61 66             is af
72c0: 66 65 63 74 65 64 2e 20 27 27 27 0a 20 20 20 20  fected. '''.    
72d0: 20 20 20 20 69 66 20 72 6f 75 74 65 20 69 73 20      if route is 
72e0: 4e 6f 6e 65 3a 20 72 6f 75 74 65 73 20 3d 20 73  None: routes = s
72f0: 65 6c 66 2e 72 6f 75 74 65 73 0a 20 20 20 20 20  elf.routes.     
7300: 20 20 20 65 6c 69 66 20 69 73 69 6e 73 74 61 6e     elif isinstan
7310: 63 65 28 72 6f 75 74 65 2c 20 52 6f 75 74 65 29  ce(route, Route)
7320: 3a 20 72 6f 75 74 65 73 20 3d 20 5b 72 6f 75 74  : routes = [rout
7330: 65 5d 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a  e].        else:
7340: 20 72 6f 75 74 65 73 20 3d 20 5b 73 65 6c 66 2e   routes = [self.
7350: 72 6f 75 74 65 73 5b 72 6f 75 74 65 5d 5d 0a 20  routes[route]]. 
7360: 20 20 20 20 20 20 20 66 6f 72 20 72 6f 75 74 65         for route
7370: 20 69 6e 20 72 6f 75 74 65 73 3a 20 72 6f 75 74   in routes: rout
7380: 65 2e 72 65 73 65 74 28 29 0a 20 20 20 20 20 20  e.reset().      
7390: 20 20 69 66 20 44 45 42 55 47 3a 0a 20 20 20 20    if DEBUG:.    
73a0: 20 20 20 20 20 20 20 20 66 6f 72 20 72 6f 75 74          for rout
73b0: 65 20 69 6e 20 72 6f 75 74 65 73 3a 20 72 6f 75  e in routes: rou
73c0: 74 65 2e 70 72 65 70 61 72 65 28 29 0a 20 20 20  te.prepare().   
73d0: 20 20 20 20 20 73 65 6c 66 2e 74 72 69 67 67 65       self.trigge
73e0: 72 5f 68 6f 6f 6b 28 27 61 70 70 5f 72 65 73 65  r_hook('app_rese
73f0: 74 27 29 0a 0a 20 20 20 20 64 65 66 20 63 6c 6f  t')..    def clo
7400: 73 65 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20  se(self):.      
7410: 20 20 27 27 27 20 43 6c 6f 73 65 20 74 68 65 20    ''' Close the 
7420: 61 70 70 6c 69 63 61 74 69 6f 6e 20 61 6e 64 20  application and 
7430: 61 6c 6c 20 69 6e 73 74 61 6c 6c 65 64 20 70 6c  all installed pl
7440: 75 67 69 6e 73 2e 20 27 27 27 0a 20 20 20 20 20  ugins. '''.     
7450: 20 20 20 66 6f 72 20 70 6c 75 67 69 6e 20 69 6e     for plugin in
7460: 20 73 65 6c 66 2e 70 6c 75 67 69 6e 73 3a 0a 20   self.plugins:. 
7470: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 68 61             if ha
7480: 73 61 74 74 72 28 70 6c 75 67 69 6e 2c 20 27 63  sattr(plugin, 'c
7490: 6c 6f 73 65 27 29 3a 20 70 6c 75 67 69 6e 2e 63  lose'): plugin.c
74a0: 6c 6f 73 65 28 29 0a 20 20 20 20 20 20 20 20 73  lose().        s
74b0: 65 6c 66 2e 73 74 6f 70 70 65 64 20 3d 20 54 72  elf.stopped = Tr
74c0: 75 65 0a 0a 20 20 20 20 64 65 66 20 72 75 6e 28  ue..    def run(
74d0: 73 65 6c 66 2c 20 2a 2a 6b 77 61 72 67 73 29 3a  self, **kwargs):
74e0: 0a 20 20 20 20 20 20 20 20 27 27 27 20 43 61 6c  .        ''' Cal
74f0: 6c 73 20 3a 66 75 6e 63 3a 60 72 75 6e 60 20 77  ls :func:`run` w
7500: 69 74 68 20 74 68 65 20 73 61 6d 65 20 70 61 72  ith the same par
7510: 61 6d 65 74 65 72 73 2e 20 27 27 27 0a 20 20 20  ameters. '''.   
7520: 20 20 20 20 20 72 75 6e 28 73 65 6c 66 2c 20 2a       run(self, *
7530: 2a 6b 77 61 72 67 73 29 0a 0a 20 20 20 20 64 65  *kwargs)..    de
7540: 66 20 6d 61 74 63 68 28 73 65 6c 66 2c 20 65 6e  f match(self, en
7550: 76 69 72 6f 6e 29 3a 0a 20 20 20 20 20 20 20 20  viron):.        
7560: 22 22 22 20 53 65 61 72 63 68 20 66 6f 72 20 61  """ Search for a
7570: 20 6d 61 74 63 68 69 6e 67 20 72 6f 75 74 65 20   matching route 
7580: 61 6e 64 20 72 65 74 75 72 6e 20 61 20 28 3a 63  and return a (:c
7590: 6c 61 73 73 3a 60 52 6f 75 74 65 60 20 2c 20 75  lass:`Route` , u
75a0: 72 6c 61 72 67 73 29 0a 20 20 20 20 20 20 20 20  rlargs).        
75b0: 20 20 20 20 74 75 70 6c 65 2e 20 54 68 65 20 73      tuple. The s
75c0: 65 63 6f 6e 64 20 76 61 6c 75 65 20 69 73 20 61  econd value is a
75d0: 20 64 69 63 74 69 6f 6e 61 72 79 20 77 69 74 68   dictionary with
75e0: 20 70 61 72 61 6d 65 74 65 72 73 20 65 78 74 72   parameters extr
75f0: 61 63 74 65 64 0a 20 20 20 20 20 20 20 20 20 20  acted.          
7600: 20 20 66 72 6f 6d 20 74 68 65 20 55 52 4c 2e 20    from the URL. 
7610: 52 61 69 73 65 20 3a 65 78 63 3a 60 48 54 54 50  Raise :exc:`HTTP
7620: 45 72 72 6f 72 60 20 28 34 30 34 2f 34 30 35 29  Error` (404/405)
7630: 20 6f 6e 20 61 20 6e 6f 6e 2d 6d 61 74 63 68 2e   on a non-match.
7640: 22 22 22 0a 20 20 20 20 20 20 20 20 72 65 74 75  """.        retu
7650: 72 6e 20 73 65 6c 66 2e 72 6f 75 74 65 72 2e 6d  rn self.router.m
7660: 61 74 63 68 28 65 6e 76 69 72 6f 6e 29 0a 0a 20  atch(environ).. 
7670: 20 20 20 64 65 66 20 67 65 74 5f 75 72 6c 28 73     def get_url(s
7680: 65 6c 66 2c 20 72 6f 75 74 65 6e 61 6d 65 2c 20  elf, routename, 
7690: 2a 2a 6b 61 72 67 73 29 3a 0a 20 20 20 20 20 20  **kargs):.      
76a0: 20 20 22 22 22 20 52 65 74 75 72 6e 20 61 20 73    """ Return a s
76b0: 74 72 69 6e 67 20 74 68 61 74 20 6d 61 74 63 68  tring that match
76c0: 65 73 20 61 20 6e 61 6d 65 64 20 72 6f 75 74 65  es a named route
76d0: 20 22 22 22 0a 20 20 20 20 20 20 20 20 73 63 72   """.        scr
76e0: 69 70 74 6e 61 6d 65 20 3d 20 72 65 71 75 65 73  iptname = reques
76f0: 74 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27 53  t.environ.get('S
7700: 43 52 49 50 54 5f 4e 41 4d 45 27 2c 20 27 27 29  CRIPT_NAME', '')
7710: 2e 73 74 72 69 70 28 27 2f 27 29 20 2b 20 27 2f  .strip('/') + '/
7720: 27 0a 20 20 20 20 20 20 20 20 6c 6f 63 61 74 69  '.        locati
7730: 6f 6e 20 3d 20 73 65 6c 66 2e 72 6f 75 74 65 72  on = self.router
7740: 2e 62 75 69 6c 64 28 72 6f 75 74 65 6e 61 6d 65  .build(routename
7750: 2c 20 2a 2a 6b 61 72 67 73 29 2e 6c 73 74 72 69  , **kargs).lstri
7760: 70 28 27 2f 27 29 0a 20 20 20 20 20 20 20 20 72  p('/').        r
7770: 65 74 75 72 6e 20 75 72 6c 6a 6f 69 6e 28 75 72  eturn urljoin(ur
7780: 6c 6a 6f 69 6e 28 27 2f 27 2c 20 73 63 72 69 70  ljoin('/', scrip
7790: 74 6e 61 6d 65 29 2c 20 6c 6f 63 61 74 69 6f 6e  tname), location
77a0: 29 0a 0a 20 20 20 20 64 65 66 20 61 64 64 5f 72  )..    def add_r
77b0: 6f 75 74 65 28 73 65 6c 66 2c 20 72 6f 75 74 65  oute(self, route
77c0: 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 41  ):.        ''' A
77d0: 64 64 20 61 20 72 6f 75 74 65 20 6f 62 6a 65 63  dd a route objec
77e0: 74 2c 20 62 75 74 20 64 6f 20 6e 6f 74 20 63 68  t, but do not ch
77f0: 61 6e 67 65 20 74 68 65 20 3a 64 61 74 61 3a 60  ange the :data:`
7800: 52 6f 75 74 65 2e 61 70 70 60 0a 20 20 20 20 20  Route.app`.     
7810: 20 20 20 20 20 20 20 61 74 74 72 69 62 75 74 65         attribute
7820: 2e 27 27 27 0a 20 20 20 20 20 20 20 20 73 65 6c  .'''.        sel
7830: 66 2e 72 6f 75 74 65 73 2e 61 70 70 65 6e 64 28  f.routes.append(
7840: 72 6f 75 74 65 29 0a 20 20 20 20 20 20 20 20 73  route).        s
7850: 65 6c 66 2e 72 6f 75 74 65 72 2e 61 64 64 28 72  elf.router.add(r
7860: 6f 75 74 65 2e 72 75 6c 65 2c 20 72 6f 75 74 65  oute.rule, route
7870: 2e 6d 65 74 68 6f 64 2c 20 72 6f 75 74 65 2c 20  .method, route, 
7880: 6e 61 6d 65 3d 72 6f 75 74 65 2e 6e 61 6d 65 29  name=route.name)
7890: 0a 20 20 20 20 20 20 20 20 69 66 20 44 45 42 55  .        if DEBU
78a0: 47 3a 20 72 6f 75 74 65 2e 70 72 65 70 61 72 65  G: route.prepare
78b0: 28 29 0a 0a 20 20 20 20 64 65 66 20 72 6f 75 74  ()..    def rout
78c0: 65 28 73 65 6c 66 2c 20 70 61 74 68 3d 4e 6f 6e  e(self, path=Non
78d0: 65 2c 20 6d 65 74 68 6f 64 3d 27 47 45 54 27 2c  e, method='GET',
78e0: 20 63 61 6c 6c 62 61 63 6b 3d 4e 6f 6e 65 2c 20   callback=None, 
78f0: 6e 61 6d 65 3d 4e 6f 6e 65 2c 0a 20 20 20 20 20  name=None,.     
7900: 20 20 20 20 20 20 20 20 20 61 70 70 6c 79 3d 4e           apply=N
7910: 6f 6e 65 2c 20 73 6b 69 70 3d 4e 6f 6e 65 2c 20  one, skip=None, 
7920: 2a 2a 63 6f 6e 66 69 67 29 3a 0a 20 20 20 20 20  **config):.     
7930: 20 20 20 22 22 22 20 41 20 64 65 63 6f 72 61 74     """ A decorat
7940: 6f 72 20 74 6f 20 62 69 6e 64 20 61 20 66 75 6e  or to bind a fun
7950: 63 74 69 6f 6e 20 74 6f 20 61 20 72 65 71 75 65  ction to a reque
7960: 73 74 20 55 52 4c 2e 20 45 78 61 6d 70 6c 65 3a  st URL. Example:
7970: 3a 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  :..             
7980: 20 20 20 40 61 70 70 2e 72 6f 75 74 65 28 27 2f     @app.route('/
7990: 68 65 6c 6c 6f 2f 3a 6e 61 6d 65 27 29 0a 20 20  hello/:name').  
79a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 65                de
79b0: 66 20 68 65 6c 6c 6f 28 6e 61 6d 65 29 3a 0a 20  f hello(name):. 
79c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
79d0: 20 20 20 72 65 74 75 72 6e 20 27 48 65 6c 6c 6f     return 'Hello
79e0: 20 25 73 27 20 25 20 6e 61 6d 65 0a 0a 20 20 20   %s' % name..   
79f0: 20 20 20 20 20 20 20 20 20 54 68 65 20 60 60 3a           The ``:
7a00: 6e 61 6d 65 60 60 20 70 61 72 74 20 69 73 20 61  name`` part is a
7a10: 20 77 69 6c 64 63 61 72 64 2e 20 53 65 65 20 3a   wildcard. See :
7a20: 63 6c 61 73 73 3a 60 52 6f 75 74 65 72 60 20 66  class:`Router` f
7a30: 6f 72 20 73 79 6e 74 61 78 0a 20 20 20 20 20 20  or syntax.      
7a40: 20 20 20 20 20 20 64 65 74 61 69 6c 73 2e 0a 0a        details...
7a50: 20 20 20 20 20 20 20 20 20 20 20 20 3a 70 61 72              :par
7a60: 61 6d 20 70 61 74 68 3a 20 52 65 71 75 65 73 74  am path: Request
7a70: 20 70 61 74 68 20 6f 72 20 61 20 6c 69 73 74 20   path or a list 
7a80: 6f 66 20 70 61 74 68 73 20 74 6f 20 6c 69 73 74  of paths to list
7a90: 65 6e 20 74 6f 2e 20 49 66 20 6e 6f 0a 20 20 20  en to. If no.   
7aa0: 20 20 20 20 20 20 20 20 20 20 20 70 61 74 68 20             path 
7ab0: 69 73 20 73 70 65 63 69 66 69 65 64 2c 20 69 74  is specified, it
7ac0: 20 69 73 20 61 75 74 6f 6d 61 74 69 63 61 6c 6c   is automaticall
7ad0: 79 20 67 65 6e 65 72 61 74 65 64 20 66 72 6f 6d  y generated from
7ae0: 20 74 68 65 0a 20 20 20 20 20 20 20 20 20 20 20   the.           
7af0: 20 20 20 73 69 67 6e 61 74 75 72 65 20 6f 66 20     signature of 
7b00: 74 68 65 20 66 75 6e 63 74 69 6f 6e 2e 0a 20 20  the function..  
7b10: 20 20 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d            :param
7b20: 20 6d 65 74 68 6f 64 3a 20 48 54 54 50 20 6d 65   method: HTTP me
7b30: 74 68 6f 64 20 28 60 47 45 54 60 2c 20 60 50 4f  thod (`GET`, `PO
7b40: 53 54 60 2c 20 60 50 55 54 60 2c 20 2e 2e 2e 29  ST`, `PUT`, ...)
7b50: 20 6f 72 20 61 20 6c 69 73 74 20 6f 66 0a 20 20   or a list of.  
7b60: 20 20 20 20 20 20 20 20 20 20 20 20 6d 65 74 68              meth
7b70: 6f 64 73 20 74 6f 20 6c 69 73 74 65 6e 20 74 6f  ods to listen to
7b80: 2e 20 28 64 65 66 61 75 6c 74 3a 20 60 47 45 54  . (default: `GET
7b90: 60 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a  `).            :
7ba0: 70 61 72 61 6d 20 63 61 6c 6c 62 61 63 6b 3a 20  param callback: 
7bb0: 41 6e 20 6f 70 74 69 6f 6e 61 6c 20 73 68 6f 72  An optional shor
7bc0: 74 63 75 74 20 74 6f 20 61 76 6f 69 64 20 74 68  tcut to avoid th
7bd0: 65 20 64 65 63 6f 72 61 74 6f 72 0a 20 20 20 20  e decorator.    
7be0: 20 20 20 20 20 20 20 20 20 20 73 79 6e 74 61 78            syntax
7bf0: 2e 20 60 60 72 6f 75 74 65 28 2e 2e 2e 2c 20 63  . ``route(..., c
7c00: 61 6c 6c 62 61 63 6b 3d 66 75 6e 63 29 60 60 20  allback=func)`` 
7c10: 65 71 75 61 6c 73 20 60 60 72 6f 75 74 65 28 2e  equals ``route(.
7c20: 2e 2e 29 28 66 75 6e 63 29 60 60 0a 20 20 20 20  ..)(func)``.    
7c30: 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 6e          :param n
7c40: 61 6d 65 3a 20 54 68 65 20 6e 61 6d 65 20 66 6f  ame: The name fo
7c50: 72 20 74 68 69 73 20 72 6f 75 74 65 2e 20 28 64  r this route. (d
7c60: 65 66 61 75 6c 74 3a 20 4e 6f 6e 65 29 0a 20 20  efault: None).  
7c70: 20 20 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d            :param
7c80: 20 61 70 70 6c 79 3a 20 41 20 64 65 63 6f 72 61   apply: A decora
7c90: 74 6f 72 20 6f 72 20 70 6c 75 67 69 6e 20 6f 72  tor or plugin or
7ca0: 20 61 20 6c 69 73 74 20 6f 66 20 70 6c 75 67 69   a list of plugi
7cb0: 6e 73 2e 20 54 68 65 73 65 20 61 72 65 0a 20 20  ns. These are.  
7cc0: 20 20 20 20 20 20 20 20 20 20 20 20 61 70 70 6c              appl
7cd0: 69 65 64 20 74 6f 20 74 68 65 20 72 6f 75 74 65  ied to the route
7ce0: 20 63 61 6c 6c 62 61 63 6b 20 69 6e 20 61 64 64   callback in add
7cf0: 69 74 69 6f 6e 20 74 6f 20 69 6e 73 74 61 6c 6c  ition to install
7d00: 65 64 20 70 6c 75 67 69 6e 73 2e 0a 20 20 20 20  ed plugins..    
7d10: 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 73          :param s
7d20: 6b 69 70 3a 20 41 20 6c 69 73 74 20 6f 66 20 70  kip: A list of p
7d30: 6c 75 67 69 6e 73 2c 20 70 6c 75 67 69 6e 20 63  lugins, plugin c
7d40: 6c 61 73 73 65 73 20 6f 72 20 6e 61 6d 65 73 2e  lasses or names.
7d50: 20 4d 61 74 63 68 69 6e 67 0a 20 20 20 20 20 20   Matching.      
7d60: 20 20 20 20 20 20 20 20 70 6c 75 67 69 6e 73 20          plugins 
7d70: 61 72 65 20 6e 6f 74 20 69 6e 73 74 61 6c 6c 65  are not installe
7d80: 64 20 74 6f 20 74 68 69 73 20 72 6f 75 74 65 2e  d to this route.
7d90: 20 60 60 54 72 75 65 60 60 20 73 6b 69 70 73 20   ``True`` skips 
7da0: 61 6c 6c 2e 0a 0a 20 20 20 20 20 20 20 20 20 20  all...          
7db0: 20 20 41 6e 79 20 61 64 64 69 74 69 6f 6e 61 6c    Any additional
7dc0: 20 6b 65 79 77 6f 72 64 20 61 72 67 75 6d 65 6e   keyword argumen
7dd0: 74 73 20 61 72 65 20 73 74 6f 72 65 64 20 61 73  ts are stored as
7de0: 20 72 6f 75 74 65 2d 73 70 65 63 69 66 69 63 0a   route-specific.
7df0: 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 66              conf
7e00: 69 67 75 72 61 74 69 6f 6e 20 61 6e 64 20 70 61  iguration and pa
7e10: 73 73 65 64 20 74 6f 20 70 6c 75 67 69 6e 73 20  ssed to plugins 
7e20: 28 73 65 65 20 3a 6d 65 74 68 3a 60 50 6c 75 67  (see :meth:`Plug
7e30: 69 6e 2e 61 70 70 6c 79 60 29 2e 0a 20 20 20 20  in.apply`)..    
7e40: 20 20 20 20 22 22 22 0a 20 20 20 20 20 20 20 20      """.        
7e50: 69 66 20 63 61 6c 6c 61 62 6c 65 28 70 61 74 68  if callable(path
7e60: 29 3a 20 70 61 74 68 2c 20 63 61 6c 6c 62 61 63  ): path, callbac
7e70: 6b 20 3d 20 4e 6f 6e 65 2c 20 70 61 74 68 0a 20  k = None, path. 
7e80: 20 20 20 20 20 20 20 70 6c 75 67 69 6e 73 20 3d         plugins =
7e90: 20 6d 61 6b 65 6c 69 73 74 28 61 70 70 6c 79 29   makelist(apply)
7ea0: 0a 20 20 20 20 20 20 20 20 73 6b 69 70 6c 69 73  .        skiplis
7eb0: 74 20 3d 20 6d 61 6b 65 6c 69 73 74 28 73 6b 69  t = makelist(ski
7ec0: 70 29 0a 20 20 20 20 20 20 20 20 64 65 66 20 64  p).        def d
7ed0: 65 63 6f 72 61 74 6f 72 28 63 61 6c 6c 62 61 63  ecorator(callbac
7ee0: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
7ef0: 23 20 54 4f 44 4f 3a 20 44 6f 63 75 6d 65 6e 74  # TODO: Document
7f00: 61 74 69 6f 6e 20 61 6e 64 20 74 65 73 74 73 0a  ation and tests.
7f10: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 69              if i
7f20: 73 69 6e 73 74 61 6e 63 65 28 63 61 6c 6c 62 61  sinstance(callba
7f30: 63 6b 2c 20 62 61 73 65 73 74 72 69 6e 67 29 3a  ck, basestring):
7f40: 20 63 61 6c 6c 62 61 63 6b 20 3d 20 6c 6f 61 64   callback = load
7f50: 28 63 61 6c 6c 62 61 63 6b 29 0a 20 20 20 20 20  (callback).     
7f60: 20 20 20 20 20 20 20 66 6f 72 20 72 75 6c 65 20         for rule 
7f70: 69 6e 20 6d 61 6b 65 6c 69 73 74 28 70 61 74 68  in makelist(path
7f80: 29 20 6f 72 20 79 69 65 6c 64 72 6f 75 74 65 73  ) or yieldroutes
7f90: 28 63 61 6c 6c 62 61 63 6b 29 3a 0a 20 20 20 20  (callback):.    
7fa0: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
7fb0: 76 65 72 62 20 69 6e 20 6d 61 6b 65 6c 69 73 74  verb in makelist
7fc0: 28 6d 65 74 68 6f 64 29 3a 0a 20 20 20 20 20 20  (method):.      
7fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 76 65                ve
7fe0: 72 62 20 3d 20 76 65 72 62 2e 75 70 70 65 72 28  rb = verb.upper(
7ff0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
8000: 20 20 20 20 20 20 72 6f 75 74 65 20 3d 20 52 6f        route = Ro
8010: 75 74 65 28 73 65 6c 66 2c 20 72 75 6c 65 2c 20  ute(self, rule, 
8020: 76 65 72 62 2c 20 63 61 6c 6c 62 61 63 6b 2c 20  verb, callback, 
8030: 6e 61 6d 65 3d 6e 61 6d 65 2c 0a 20 20 20 20 20  name=name,.     
8040: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8050: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 6c 75               plu
8060: 67 69 6e 73 3d 70 6c 75 67 69 6e 73 2c 20 73 6b  gins=plugins, sk
8070: 69 70 6c 69 73 74 3d 73 6b 69 70 6c 69 73 74 2c  iplist=skiplist,
8080: 20 2a 2a 63 6f 6e 66 69 67 29 0a 20 20 20 20 20   **config).     
8090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
80a0: 65 6c 66 2e 61 64 64 5f 72 6f 75 74 65 28 72 6f  elf.add_route(ro
80b0: 75 74 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  ute).           
80c0: 20 72 65 74 75 72 6e 20 63 61 6c 6c 62 61 63 6b   return callback
80d0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
80e0: 64 65 63 6f 72 61 74 6f 72 28 63 61 6c 6c 62 61  decorator(callba
80f0: 63 6b 29 20 69 66 20 63 61 6c 6c 62 61 63 6b 20  ck) if callback 
8100: 65 6c 73 65 20 64 65 63 6f 72 61 74 6f 72 0a 0a  else decorator..
8110: 20 20 20 20 64 65 66 20 67 65 74 28 73 65 6c 66      def get(self
8120: 2c 20 70 61 74 68 3d 4e 6f 6e 65 2c 20 6d 65 74  , path=None, met
8130: 68 6f 64 3d 27 47 45 54 27 2c 20 2a 2a 6f 70 74  hod='GET', **opt
8140: 69 6f 6e 73 29 3a 0a 20 20 20 20 20 20 20 20 22  ions):.        "
8150: 22 22 20 45 71 75 61 6c 73 20 3a 6d 65 74 68 3a  "" Equals :meth:
8160: 60 72 6f 75 74 65 60 2e 20 22 22 22 0a 20 20 20  `route`. """.   
8170: 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66       return self
8180: 2e 72 6f 75 74 65 28 70 61 74 68 2c 20 6d 65 74  .route(path, met
8190: 68 6f 64 2c 20 2a 2a 6f 70 74 69 6f 6e 73 29 0a  hod, **options).
81a0: 0a 20 20 20 20 64 65 66 20 70 6f 73 74 28 73 65  .    def post(se
81b0: 6c 66 2c 20 70 61 74 68 3d 4e 6f 6e 65 2c 20 6d  lf, path=None, m
81c0: 65 74 68 6f 64 3d 27 50 4f 53 54 27 2c 20 2a 2a  ethod='POST', **
81d0: 6f 70 74 69 6f 6e 73 29 3a 0a 20 20 20 20 20 20  options):.      
81e0: 20 20 22 22 22 20 45 71 75 61 6c 73 20 3a 6d 65    """ Equals :me
81f0: 74 68 3a 60 72 6f 75 74 65 60 20 77 69 74 68 20  th:`route` with 
8200: 61 20 60 60 50 4f 53 54 60 60 20 6d 65 74 68 6f  a ``POST`` metho
8210: 64 20 70 61 72 61 6d 65 74 65 72 2e 20 22 22 22  d parameter. """
8220: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
8230: 73 65 6c 66 2e 72 6f 75 74 65 28 70 61 74 68 2c  self.route(path,
8240: 20 6d 65 74 68 6f 64 2c 20 2a 2a 6f 70 74 69 6f   method, **optio
8250: 6e 73 29 0a 0a 20 20 20 20 64 65 66 20 70 75 74  ns)..    def put
8260: 28 73 65 6c 66 2c 20 70 61 74 68 3d 4e 6f 6e 65  (self, path=None
8270: 2c 20 6d 65 74 68 6f 64 3d 27 50 55 54 27 2c 20  , method='PUT', 
8280: 2a 2a 6f 70 74 69 6f 6e 73 29 3a 0a 20 20 20 20  **options):.    
8290: 20 20 20 20 22 22 22 20 45 71 75 61 6c 73 20 3a      """ Equals :
82a0: 6d 65 74 68 3a 60 72 6f 75 74 65 60 20 77 69 74  meth:`route` wit
82b0: 68 20 61 20 60 60 50 55 54 60 60 20 6d 65 74 68  h a ``PUT`` meth
82c0: 6f 64 20 70 61 72 61 6d 65 74 65 72 2e 20 22 22  od parameter. ""
82d0: 22 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ".        return
82e0: 20 73 65 6c 66 2e 72 6f 75 74 65 28 70 61 74 68   self.route(path
82f0: 2c 20 6d 65 74 68 6f 64 2c 20 2a 2a 6f 70 74 69  , method, **opti
8300: 6f 6e 73 29 0a 0a 20 20 20 20 64 65 66 20 64 65  ons)..    def de
8310: 6c 65 74 65 28 73 65 6c 66 2c 20 70 61 74 68 3d  lete(self, path=
8320: 4e 6f 6e 65 2c 20 6d 65 74 68 6f 64 3d 27 44 45  None, method='DE
8330: 4c 45 54 45 27 2c 20 2a 2a 6f 70 74 69 6f 6e 73  LETE', **options
8340: 29 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20 45  ):.        """ E
8350: 71 75 61 6c 73 20 3a 6d 65 74 68 3a 60 72 6f 75  quals :meth:`rou
8360: 74 65 60 20 77 69 74 68 20 61 20 60 60 44 45 4c  te` with a ``DEL
8370: 45 54 45 60 60 20 6d 65 74 68 6f 64 20 70 61 72  ETE`` method par
8380: 61 6d 65 74 65 72 2e 20 22 22 22 0a 20 20 20 20  ameter. """.    
8390: 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e      return self.
83a0: 72 6f 75 74 65 28 70 61 74 68 2c 20 6d 65 74 68  route(path, meth
83b0: 6f 64 2c 20 2a 2a 6f 70 74 69 6f 6e 73 29 0a 0a  od, **options)..
83c0: 20 20 20 20 64 65 66 20 65 72 72 6f 72 28 73 65      def error(se
83d0: 6c 66 2c 20 63 6f 64 65 3d 35 30 30 29 3a 0a 20  lf, code=500):. 
83e0: 20 20 20 20 20 20 20 22 22 22 20 44 65 63 6f 72         """ Decor
83f0: 61 74 6f 72 3a 20 52 65 67 69 73 74 65 72 20 61  ator: Register a
8400: 6e 20 6f 75 74 70 75 74 20 68 61 6e 64 6c 65 72  n output handler
8410: 20 66 6f 72 20 61 20 48 54 54 50 20 65 72 72 6f   for a HTTP erro
8420: 72 20 63 6f 64 65 22 22 22 0a 20 20 20 20 20 20  r code""".      
8430: 20 20 64 65 66 20 77 72 61 70 70 65 72 28 68 61    def wrapper(ha
8440: 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20 20 20 20  ndler):.        
8450: 20 20 20 20 73 65 6c 66 2e 65 72 72 6f 72 5f 68      self.error_h
8460: 61 6e 64 6c 65 72 5b 69 6e 74 28 63 6f 64 65 29  andler[int(code)
8470: 5d 20 3d 20 68 61 6e 64 6c 65 72 0a 20 20 20 20  ] = handler.    
8480: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 68          return h
8490: 61 6e 64 6c 65 72 0a 20 20 20 20 20 20 20 20 72  andler.        r
84a0: 65 74 75 72 6e 20 77 72 61 70 70 65 72 0a 0a 20  eturn wrapper.. 
84b0: 20 20 20 64 65 66 20 64 65 66 61 75 6c 74 5f 65     def default_e
84c0: 72 72 6f 72 5f 68 61 6e 64 6c 65 72 28 73 65 6c  rror_handler(sel
84d0: 66 2c 20 72 65 73 29 3a 0a 20 20 20 20 20 20 20  f, res):.       
84e0: 20 72 65 74 75 72 6e 20 74 6f 62 28 74 65 6d 70   return tob(temp
84f0: 6c 61 74 65 28 45 52 52 4f 52 5f 50 41 47 45 5f  late(ERROR_PAGE_
8500: 54 45 4d 50 4c 41 54 45 2c 20 65 3d 72 65 73 29  TEMPLATE, e=res)
8510: 29 0a 0a 20 20 20 20 64 65 66 20 5f 68 61 6e 64  )..    def _hand
8520: 6c 65 28 73 65 6c 66 2c 20 65 6e 76 69 72 6f 6e  le(self, environ
8530: 29 3a 0a 20 20 20 20 20 20 20 20 70 61 74 68 20  ):.        path 
8540: 3d 20 65 6e 76 69 72 6f 6e 5b 27 62 6f 74 74 6c  = environ['bottl
8550: 65 2e 72 61 77 5f 70 61 74 68 27 5d 20 3d 20 65  e.raw_path'] = e
8560: 6e 76 69 72 6f 6e 5b 27 50 41 54 48 5f 49 4e 46  nviron['PATH_INF
8570: 4f 27 5d 0a 20 20 20 20 20 20 20 20 69 66 20 70  O'].        if p
8580: 79 33 6b 3a 0a 20 20 20 20 20 20 20 20 20 20 20  y3k:.           
8590: 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20   try:.          
85a0: 20 20 20 20 20 20 65 6e 76 69 72 6f 6e 5b 27 50        environ['P
85b0: 41 54 48 5f 49 4e 46 4f 27 5d 20 3d 20 70 61 74  ATH_INFO'] = pat
85c0: 68 2e 65 6e 63 6f 64 65 28 27 6c 61 74 69 6e 31  h.encode('latin1
85d0: 27 29 2e 64 65 63 6f 64 65 28 27 75 74 66 38 27  ').decode('utf8'
85e0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 78  ).            ex
85f0: 63 65 70 74 20 55 6e 69 63 6f 64 65 45 72 72 6f  cept UnicodeErro
8600: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
8610: 20 20 20 72 65 74 75 72 6e 20 48 54 54 50 45 72     return HTTPEr
8620: 72 6f 72 28 34 30 30 2c 20 27 49 6e 76 61 6c 69  ror(400, 'Invali
8630: 64 20 70 61 74 68 20 73 74 72 69 6e 67 2e 20 45  d path string. E
8640: 78 70 65 63 74 65 64 20 55 54 46 2d 38 27 29 0a  xpected UTF-8').
8650: 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20  .        try:.  
8660: 20 20 20 20 20 20 20 20 20 20 65 6e 76 69 72 6f            enviro
8670: 6e 5b 27 62 6f 74 74 6c 65 2e 61 70 70 27 5d 20  n['bottle.app'] 
8680: 3d 20 73 65 6c 66 0a 20 20 20 20 20 20 20 20 20  = self.         
8690: 20 20 20 72 65 71 75 65 73 74 2e 62 69 6e 64 28     request.bind(
86a0: 65 6e 76 69 72 6f 6e 29 0a 20 20 20 20 20 20 20  environ).       
86b0: 20 20 20 20 20 72 65 73 70 6f 6e 73 65 2e 62 69       response.bi
86c0: 6e 64 28 29 0a 20 20 20 20 20 20 20 20 20 20 20  nd().           
86d0: 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20   try:.          
86e0: 20 20 20 20 20 20 73 65 6c 66 2e 74 72 69 67 67        self.trigg
86f0: 65 72 5f 68 6f 6f 6b 28 27 62 65 66 6f 72 65 5f  er_hook('before_
8700: 72 65 71 75 65 73 74 27 29 0a 20 20 20 20 20 20  request').      
8710: 20 20 20 20 20 20 20 20 20 20 72 6f 75 74 65 2c            route,
8720: 20 61 72 67 73 20 3d 20 73 65 6c 66 2e 72 6f 75   args = self.rou
8730: 74 65 72 2e 6d 61 74 63 68 28 65 6e 76 69 72 6f  ter.match(enviro
8740: 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  n).             
8750: 20 20 20 65 6e 76 69 72 6f 6e 5b 27 72 6f 75 74     environ['rout
8760: 65 2e 68 61 6e 64 6c 65 27 5d 20 3d 20 72 6f 75  e.handle'] = rou
8770: 74 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  te.             
8780: 20 20 20 65 6e 76 69 72 6f 6e 5b 27 62 6f 74 74     environ['bott
8790: 6c 65 2e 72 6f 75 74 65 27 5d 20 3d 20 72 6f 75  le.route'] = rou
87a0: 74 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  te.             
87b0: 20 20 20 65 6e 76 69 72 6f 6e 5b 27 72 6f 75 74     environ['rout
87c0: 65 2e 75 72 6c 5f 61 72 67 73 27 5d 20 3d 20 61  e.url_args'] = a
87d0: 72 67 73 0a 20 20 20 20 20 20 20 20 20 20 20 20  rgs.            
87e0: 20 20 20 20 72 65 74 75 72 6e 20 72 6f 75 74 65      return route
87f0: 2e 63 61 6c 6c 28 2a 2a 61 72 67 73 29 0a 20 20  .call(**args).  
8800: 20 20 20 20 20 20 20 20 20 20 66 69 6e 61 6c 6c            finall
8810: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y:.             
8820: 20 20 20 73 65 6c 66 2e 74 72 69 67 67 65 72 5f     self.trigger_
8830: 68 6f 6f 6b 28 27 61 66 74 65 72 5f 72 65 71 75  hook('after_requ
8840: 65 73 74 27 29 0a 0a 20 20 20 20 20 20 20 20 65  est')..        e
8850: 78 63 65 70 74 20 48 54 54 50 52 65 73 70 6f 6e  xcept HTTPRespon
8860: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
8870: 72 65 74 75 72 6e 20 5f 65 28 29 0a 20 20 20 20  return _e().    
8880: 20 20 20 20 65 78 63 65 70 74 20 52 6f 75 74 65      except Route
8890: 52 65 73 65 74 3a 0a 20 20 20 20 20 20 20 20 20  Reset:.         
88a0: 20 20 20 72 6f 75 74 65 2e 72 65 73 65 74 28 29     route.reset()
88b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
88c0: 75 72 6e 20 73 65 6c 66 2e 5f 68 61 6e 64 6c 65  urn self._handle
88d0: 28 65 6e 76 69 72 6f 6e 29 0a 20 20 20 20 20 20  (environ).      
88e0: 20 20 65 78 63 65 70 74 20 28 4b 65 79 62 6f 61    except (Keyboa
88f0: 72 64 49 6e 74 65 72 72 75 70 74 2c 20 53 79 73  rdInterrupt, Sys
8900: 74 65 6d 45 78 69 74 2c 20 4d 65 6d 6f 72 79 45  temExit, MemoryE
8910: 72 72 6f 72 29 3a 0a 20 20 20 20 20 20 20 20 20  rror):.         
8920: 20 20 20 72 61 69 73 65 0a 20 20 20 20 20 20 20     raise.       
8930: 20 65 78 63 65 70 74 20 45 78 63 65 70 74 69 6f   except Exceptio
8940: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  n:.            i
8950: 66 20 6e 6f 74 20 73 65 6c 66 2e 63 61 74 63 68  f not self.catch
8960: 61 6c 6c 3a 20 72 61 69 73 65 0a 20 20 20 20 20  all: raise.     
8970: 20 20 20 20 20 20 20 73 74 61 63 6b 74 72 61 63         stacktrac
8980: 65 20 3d 20 66 6f 72 6d 61 74 5f 65 78 63 28 29  e = format_exc()
8990: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6e 76  .            env
89a0: 69 72 6f 6e 5b 27 77 73 67 69 2e 65 72 72 6f 72  iron['wsgi.error
89b0: 73 27 5d 2e 77 72 69 74 65 28 73 74 61 63 6b 74  s'].write(stackt
89c0: 72 61 63 65 29 0a 20 20 20 20 20 20 20 20 20 20  race).          
89d0: 20 20 72 65 74 75 72 6e 20 48 54 54 50 45 72 72    return HTTPErr
89e0: 6f 72 28 35 30 30 2c 20 22 49 6e 74 65 72 6e 61  or(500, "Interna
89f0: 6c 20 53 65 72 76 65 72 20 45 72 72 6f 72 22 2c  l Server Error",
8a00: 20 5f 65 28 29 2c 20 73 74 61 63 6b 74 72 61 63   _e(), stacktrac
8a10: 65 29 0a 0a 20 20 20 20 64 65 66 20 5f 63 61 73  e)..    def _cas
8a20: 74 28 73 65 6c 66 2c 20 6f 75 74 2c 20 70 65 65  t(self, out, pee
8a30: 6b 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20  k=None):.       
8a40: 20 22 22 22 20 54 72 79 20 74 6f 20 63 6f 6e 76   """ Try to conv
8a50: 65 72 74 20 74 68 65 20 70 61 72 61 6d 65 74 65  ert the paramete
8a60: 72 20 69 6e 74 6f 20 73 6f 6d 65 74 68 69 6e 67  r into something
8a70: 20 57 53 47 49 20 63 6f 6d 70 61 74 69 62 6c 65   WSGI compatible
8a80: 20 61 6e 64 20 73 65 74 0a 20 20 20 20 20 20 20   and set.       
8a90: 20 63 6f 72 72 65 63 74 20 48 54 54 50 20 68 65   correct HTTP he
8aa0: 61 64 65 72 73 20 77 68 65 6e 20 70 6f 73 73 69  aders when possi
8ab0: 62 6c 65 2e 0a 20 20 20 20 20 20 20 20 53 75 70  ble..        Sup
8ac0: 70 6f 72 74 3a 20 46 61 6c 73 65 2c 20 73 74 72  port: False, str
8ad0: 2c 20 75 6e 69 63 6f 64 65 2c 20 64 69 63 74 2c  , unicode, dict,
8ae0: 20 48 54 54 50 52 65 73 70 6f 6e 73 65 2c 20 48   HTTPResponse, H
8af0: 54 54 50 45 72 72 6f 72 2c 20 66 69 6c 65 2d 6c  TTPError, file-l
8b00: 69 6b 65 2c 0a 20 20 20 20 20 20 20 20 69 74 65  ike,.        ite
8b10: 72 61 62 6c 65 20 6f 66 20 73 74 72 69 6e 67 73  rable of strings
8b20: 20 61 6e 64 20 69 74 65 72 61 62 6c 65 20 6f 66   and iterable of
8b30: 20 75 6e 69 63 6f 64 65 73 0a 20 20 20 20 20 20   unicodes.      
8b40: 20 20 22 22 22 0a 0a 20 20 20 20 20 20 20 20 23    """..        #
8b50: 20 45 6d 70 74 79 20 6f 75 74 70 75 74 20 69 73   Empty output is
8b60: 20 64 6f 6e 65 20 68 65 72 65 0a 20 20 20 20 20   done here.     
8b70: 20 20 20 69 66 20 6e 6f 74 20 6f 75 74 3a 0a 20     if not out:. 
8b80: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 27 43             if 'C
8b90: 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 27 20 6e  ontent-Length' n
8ba0: 6f 74 20 69 6e 20 72 65 73 70 6f 6e 73 65 3a 0a  ot in response:.
8bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8bc0: 72 65 73 70 6f 6e 73 65 5b 27 43 6f 6e 74 65 6e  response['Conten
8bd0: 74 2d 4c 65 6e 67 74 68 27 5d 20 3d 20 30 0a 20  t-Length'] = 0. 
8be0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
8bf0: 6e 20 5b 5d 0a 20 20 20 20 20 20 20 20 23 20 4a  n [].        # J
8c00: 6f 69 6e 20 6c 69 73 74 73 20 6f 66 20 62 79 74  oin lists of byt
8c10: 65 20 6f 72 20 75 6e 69 63 6f 64 65 20 73 74 72  e or unicode str
8c20: 69 6e 67 73 2e 20 4d 69 78 65 64 20 6c 69 73 74  ings. Mixed list
8c30: 73 20 61 72 65 20 4e 4f 54 20 73 75 70 70 6f 72  s are NOT suppor
8c40: 74 65 64 0a 20 20 20 20 20 20 20 20 69 66 20 69  ted.        if i
8c50: 73 69 6e 73 74 61 6e 63 65 28 6f 75 74 2c 20 28  sinstance(out, (
8c60: 74 75 70 6c 65 2c 20 6c 69 73 74 29 29 5c 0a 20  tuple, list))\. 
8c70: 20 20 20 20 20 20 20 61 6e 64 20 69 73 69 6e 73         and isins
8c80: 74 61 6e 63 65 28 6f 75 74 5b 30 5d 2c 20 28 62  tance(out[0], (b
8c90: 79 74 65 73 2c 20 75 6e 69 63 6f 64 65 29 29 3a  ytes, unicode)):
8ca0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6f 75 74  .            out
8cb0: 20 3d 20 6f 75 74 5b 30 5d 5b 30 3a 30 5d 2e 6a   = out[0][0:0].j
8cc0: 6f 69 6e 28 6f 75 74 29 20 23 20 62 27 61 62 63  oin(out) # b'abc
8cd0: 27 5b 30 3a 30 5d 20 2d 3e 20 62 27 27 0a 20 20  '[0:0] -> b''.  
8ce0: 20 20 20 20 20 20 23 20 45 6e 63 6f 64 65 20 75        # Encode u
8cf0: 6e 69 63 6f 64 65 20 73 74 72 69 6e 67 73 0a 20  nicode strings. 
8d00: 20 20 20 20 20 20 20 69 66 20 69 73 69 6e 73 74         if isinst
8d10: 61 6e 63 65 28 6f 75 74 2c 20 75 6e 69 63 6f 64  ance(out, unicod
8d20: 65 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  e):.            
8d30: 6f 75 74 20 3d 20 6f 75 74 2e 65 6e 63 6f 64 65  out = out.encode
8d40: 28 72 65 73 70 6f 6e 73 65 2e 63 68 61 72 73 65  (response.charse
8d50: 74 29 0a 20 20 20 20 20 20 20 20 23 20 42 79 74  t).        # Byt
8d60: 65 20 53 74 72 69 6e 67 73 20 61 72 65 20 6a 75  e Strings are ju
8d70: 73 74 20 72 65 74 75 72 6e 65 64 0a 20 20 20 20  st returned.    
8d80: 20 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63      if isinstanc
8d90: 65 28 6f 75 74 2c 20 62 79 74 65 73 29 3a 0a 20  e(out, bytes):. 
8da0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 27 43             if 'C
8db0: 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 27 20 6e  ontent-Length' n
8dc0: 6f 74 20 69 6e 20 72 65 73 70 6f 6e 73 65 3a 0a  ot in response:.
8dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8de0: 72 65 73 70 6f 6e 73 65 5b 27 43 6f 6e 74 65 6e  response['Conten
8df0: 74 2d 4c 65 6e 67 74 68 27 5d 20 3d 20 6c 65 6e  t-Length'] = len
8e00: 28 6f 75 74 29 0a 20 20 20 20 20 20 20 20 20 20  (out).          
8e10: 20 20 72 65 74 75 72 6e 20 5b 6f 75 74 5d 0a 20    return [out]. 
8e20: 20 20 20 20 20 20 20 23 20 48 54 54 50 45 72 72         # HTTPErr
8e30: 6f 72 20 6f 72 20 48 54 54 50 45 78 63 65 70 74  or or HTTPExcept
8e40: 69 6f 6e 20 28 72 65 63 75 72 73 69 76 65 2c 20  ion (recursive, 
8e50: 62 65 63 61 75 73 65 20 74 68 65 79 20 6d 61 79  because they may
8e60: 20 77 72 61 70 20 61 6e 79 74 68 69 6e 67 29 0a   wrap anything).
8e70: 20 20 20 20 20 20 20 20 23 20 54 4f 44 4f 3a 20          # TODO: 
8e80: 48 61 6e 64 6c 65 20 74 68 65 73 65 20 65 78 70  Handle these exp
8e90: 6c 69 63 69 74 6c 79 20 69 6e 20 68 61 6e 64 6c  licitly in handl
8ea0: 65 28 29 20 6f 72 20 6d 61 6b 65 20 74 68 65 6d  e() or make them
8eb0: 20 69 74 65 72 61 62 6c 65 2e 0a 20 20 20 20 20   iterable..     
8ec0: 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63 65     if isinstance
8ed0: 28 6f 75 74 2c 20 48 54 54 50 45 72 72 6f 72 29  (out, HTTPError)
8ee0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6f 75  :.            ou
8ef0: 74 2e 61 70 70 6c 79 28 72 65 73 70 6f 6e 73 65  t.apply(response
8f00: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 6f 75  ).            ou
8f10: 74 20 3d 20 73 65 6c 66 2e 65 72 72 6f 72 5f 68  t = self.error_h
8f20: 61 6e 64 6c 65 72 2e 67 65 74 28 6f 75 74 2e 73  andler.get(out.s
8f30: 74 61 74 75 73 5f 63 6f 64 65 2c 20 73 65 6c 66  tatus_code, self
8f40: 2e 64 65 66 61 75 6c 74 5f 65 72 72 6f 72 5f 68  .default_error_h
8f50: 61 6e 64 6c 65 72 29 28 6f 75 74 29 0a 20 20 20  andler)(out).   
8f60: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
8f70: 73 65 6c 66 2e 5f 63 61 73 74 28 6f 75 74 29 0a  self._cast(out).
8f80: 20 20 20 20 20 20 20 20 69 66 20 69 73 69 6e 73          if isins
8f90: 74 61 6e 63 65 28 6f 75 74 2c 20 48 54 54 50 52  tance(out, HTTPR
8fa0: 65 73 70 6f 6e 73 65 29 3a 0a 20 20 20 20 20 20  esponse):.      
8fb0: 20 20 20 20 20 20 6f 75 74 2e 61 70 70 6c 79 28        out.apply(
8fc0: 72 65 73 70 6f 6e 73 65 29 0a 20 20 20 20 20 20  response).      
8fd0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
8fe0: 66 2e 5f 63 61 73 74 28 6f 75 74 2e 62 6f 64 79  f._cast(out.body
8ff0: 29 0a 0a 20 20 20 20 20 20 20 20 23 20 46 69 6c  )..        # Fil
9000: 65 2d 6c 69 6b 65 20 6f 62 6a 65 63 74 73 2e 0a  e-like objects..
9010: 20 20 20 20 20 20 20 20 69 66 20 68 61 73 61 74          if hasat
9020: 74 72 28 6f 75 74 2c 20 27 72 65 61 64 27 29 3a  tr(out, 'read'):
9030: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
9040: 27 77 73 67 69 2e 66 69 6c 65 5f 77 72 61 70 70  'wsgi.file_wrapp
9050: 65 72 27 20 69 6e 20 72 65 71 75 65 73 74 2e 65  er' in request.e
9060: 6e 76 69 72 6f 6e 3a 0a 20 20 20 20 20 20 20 20  nviron:.        
9070: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 72          return r
9080: 65 71 75 65 73 74 2e 65 6e 76 69 72 6f 6e 5b 27  equest.environ['
9090: 77 73 67 69 2e 66 69 6c 65 5f 77 72 61 70 70 65  wsgi.file_wrappe
90a0: 72 27 5d 28 6f 75 74 29 0a 20 20 20 20 20 20 20  r'](out).       
90b0: 20 20 20 20 20 65 6c 69 66 20 68 61 73 61 74 74       elif hasatt
90c0: 72 28 6f 75 74 2c 20 27 63 6c 6f 73 65 27 29 20  r(out, 'close') 
90d0: 6f 72 20 6e 6f 74 20 68 61 73 61 74 74 72 28 6f  or not hasattr(o
90e0: 75 74 2c 20 27 5f 5f 69 74 65 72 5f 5f 27 29 3a  ut, '__iter__'):
90f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9100: 20 72 65 74 75 72 6e 20 57 53 47 49 46 69 6c 65   return WSGIFile
9110: 57 72 61 70 70 65 72 28 6f 75 74 29 0a 0a 20 20  Wrapper(out)..  
9120: 20 20 20 20 20 20 23 20 48 61 6e 64 6c 65 20 49        # Handle I
9130: 74 65 72 61 62 6c 65 73 2e 20 57 65 20 70 65 65  terables. We pee
9140: 6b 20 69 6e 74 6f 20 74 68 65 6d 20 74 6f 20 64  k into them to d
9150: 65 74 65 63 74 20 74 68 65 69 72 20 69 6e 6e 65  etect their inne
9160: 72 20 74 79 70 65 2e 0a 20 20 20 20 20 20 20 20  r type..        
9170: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
9180: 20 69 6f 75 74 20 3d 20 69 74 65 72 28 6f 75 74   iout = iter(out
9190: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 69  ).            fi
91a0: 72 73 74 20 3d 20 6e 65 78 74 28 69 6f 75 74 29  rst = next(iout)
91b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 68 69  .            whi
91c0: 6c 65 20 6e 6f 74 20 66 69 72 73 74 3a 0a 20 20  le not first:.  
91d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 69                fi
91e0: 72 73 74 20 3d 20 6e 65 78 74 28 69 6f 75 74 29  rst = next(iout)
91f0: 0a 20 20 20 20 20 20 20 20 65 78 63 65 70 74 20  .        except 
9200: 53 74 6f 70 49 74 65 72 61 74 69 6f 6e 3a 0a 20  StopIteration:. 
9210: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
9220: 6e 20 73 65 6c 66 2e 5f 63 61 73 74 28 27 27 29  n self._cast('')
9230: 0a 20 20 20 20 20 20 20 20 65 78 63 65 70 74 20  .        except 
9240: 48 54 54 50 52 65 73 70 6f 6e 73 65 3a 0a 20 20  HTTPResponse:.  
9250: 20 20 20 20 20 20 20 20 20 20 66 69 72 73 74 20            first 
9260: 3d 20 5f 65 28 29 0a 20 20 20 20 20 20 20 20 65  = _e().        e
9270: 78 63 65 70 74 20 28 4b 65 79 62 6f 61 72 64 49  xcept (KeyboardI
9280: 6e 74 65 72 72 75 70 74 2c 20 53 79 73 74 65 6d  nterrupt, System
9290: 45 78 69 74 2c 20 4d 65 6d 6f 72 79 45 72 72 6f  Exit, MemoryErro
92a0: 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  r):.            
92b0: 72 61 69 73 65 0a 20 20 20 20 20 20 20 20 65 78  raise.        ex
92c0: 63 65 70 74 20 45 78 63 65 70 74 69 6f 6e 3a 0a  cept Exception:.
92d0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
92e0: 6f 74 20 73 65 6c 66 2e 63 61 74 63 68 61 6c 6c  ot self.catchall
92f0: 3a 20 72 61 69 73 65 0a 20 20 20 20 20 20 20 20  : raise.        
9300: 20 20 20 20 66 69 72 73 74 20 3d 20 48 54 54 50      first = HTTP
9310: 45 72 72 6f 72 28 35 30 30 2c 20 27 55 6e 68 61  Error(500, 'Unha
9320: 6e 64 6c 65 64 20 65 78 63 65 70 74 69 6f 6e 27  ndled exception'
9330: 2c 20 5f 65 28 29 2c 20 66 6f 72 6d 61 74 5f 65  , _e(), format_e
9340: 78 63 28 29 29 0a 0a 20 20 20 20 20 20 20 20 23  xc())..        #
9350: 20 54 68 65 73 65 20 61 72 65 20 74 68 65 20 69   These are the i
9360: 6e 6e 65 72 20 74 79 70 65 73 20 61 6c 6c 6f 77  nner types allow
9370: 65 64 20 69 6e 20 69 74 65 72 61 74 6f 72 20 6f  ed in iterator o
9380: 72 20 67 65 6e 65 72 61 74 6f 72 20 6f 62 6a 65  r generator obje
9390: 63 74 73 2e 0a 20 20 20 20 20 20 20 20 69 66 20  cts..        if 
93a0: 69 73 69 6e 73 74 61 6e 63 65 28 66 69 72 73 74  isinstance(first
93b0: 2c 20 48 54 54 50 52 65 73 70 6f 6e 73 65 29 3a  , HTTPResponse):
93c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
93d0: 75 72 6e 20 73 65 6c 66 2e 5f 63 61 73 74 28 66  urn self._cast(f
93e0: 69 72 73 74 29 0a 20 20 20 20 20 20 20 20 65 6c  irst).        el
93f0: 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 66 69  if isinstance(fi
9400: 72 73 74 2c 20 62 79 74 65 73 29 3a 0a 20 20 20  rst, bytes):.   
9410: 20 20 20 20 20 20 20 20 20 6e 65 77 5f 69 74 65           new_ite
9420: 72 20 3d 20 69 74 65 72 74 6f 6f 6c 73 2e 63 68  r = itertools.ch
9430: 61 69 6e 28 5b 66 69 72 73 74 5d 2c 20 69 6f 75  ain([first], iou
9440: 74 29 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20  t).        elif 
9450: 69 73 69 6e 73 74 61 6e 63 65 28 66 69 72 73 74  isinstance(first
9460: 2c 20 75 6e 69 63 6f 64 65 29 3a 0a 20 20 20 20  , unicode):.    
9470: 20 20 20 20 20 20 20 20 65 6e 63 6f 64 65 72 20          encoder 
9480: 3d 20 6c 61 6d 62 64 61 20 78 3a 20 78 2e 65 6e  = lambda x: x.en
9490: 63 6f 64 65 28 72 65 73 70 6f 6e 73 65 2e 63 68  code(response.ch
94a0: 61 72 73 65 74 29 0a 20 20 20 20 20 20 20 20 20  arset).         
94b0: 20 20 20 6e 65 77 5f 69 74 65 72 20 3d 20 69 6d     new_iter = im
94c0: 61 70 28 65 6e 63 6f 64 65 72 2c 20 69 74 65 72  ap(encoder, iter
94d0: 74 6f 6f 6c 73 2e 63 68 61 69 6e 28 5b 66 69 72  tools.chain([fir
94e0: 73 74 5d 2c 20 69 6f 75 74 29 29 0a 20 20 20 20  st], iout)).    
94f0: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
9500: 20 20 20 20 20 20 6d 73 67 20 3d 20 27 55 6e 73        msg = 'Uns
9510: 75 70 70 6f 72 74 65 64 20 72 65 73 70 6f 6e 73  upported respons
9520: 65 20 74 79 70 65 3a 20 25 73 27 20 25 20 74 79  e type: %s' % ty
9530: 70 65 28 66 69 72 73 74 29 0a 20 20 20 20 20 20  pe(first).      
9540: 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
9550: 66 2e 5f 63 61 73 74 28 48 54 54 50 45 72 72 6f  f._cast(HTTPErro
9560: 72 28 35 30 30 2c 20 6d 73 67 29 29 0a 20 20 20  r(500, msg)).   
9570: 20 20 20 20 20 69 66 20 68 61 73 61 74 74 72 28       if hasattr(
9580: 6f 75 74 2c 20 27 63 6c 6f 73 65 27 29 3a 0a 20  out, 'close'):. 
9590: 20 20 20 20 20 20 20 20 20 20 20 6e 65 77 5f 69             new_i
95a0: 74 65 72 20 3d 20 5f 63 6c 6f 73 65 69 74 65 72  ter = _closeiter
95b0: 28 6e 65 77 5f 69 74 65 72 2c 20 6f 75 74 2e 63  (new_iter, out.c
95c0: 6c 6f 73 65 29 0a 20 20 20 20 20 20 20 20 72 65  lose).        re
95d0: 74 75 72 6e 20 6e 65 77 5f 69 74 65 72 0a 0a 20  turn new_iter.. 
95e0: 20 20 20 64 65 66 20 77 73 67 69 28 73 65 6c 66     def wsgi(self
95f0: 2c 20 65 6e 76 69 72 6f 6e 2c 20 73 74 61 72 74  , environ, start
9600: 5f 72 65 73 70 6f 6e 73 65 29 3a 0a 20 20 20 20  _response):.    
9610: 20 20 20 20 22 22 22 20 54 68 65 20 62 6f 74 74      """ The bott
9620: 6c 65 20 57 53 47 49 2d 69 6e 74 65 72 66 61 63  le WSGI-interfac
9630: 65 2e 20 22 22 22 0a 20 20 20 20 20 20 20 20 74  e. """.        t
9640: 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ry:.            
9650: 6f 75 74 20 3d 20 73 65 6c 66 2e 5f 63 61 73 74  out = self._cast
9660: 28 73 65 6c 66 2e 5f 68 61 6e 64 6c 65 28 65 6e  (self._handle(en
9670: 76 69 72 6f 6e 29 29 0a 20 20 20 20 20 20 20 20  viron)).        
9680: 20 20 20 20 23 20 72 66 63 32 36 31 36 20 73 65      # rfc2616 se
9690: 63 74 69 6f 6e 20 34 2e 33 0a 20 20 20 20 20 20  ction 4.3.      
96a0: 20 20 20 20 20 20 69 66 20 72 65 73 70 6f 6e 73        if respons
96b0: 65 2e 5f 73 74 61 74 75 73 5f 63 6f 64 65 20 69  e._status_code i
96c0: 6e 20 28 31 30 30 2c 20 31 30 31 2c 20 32 30 34  n (100, 101, 204
96d0: 2c 20 33 30 34 29 5c 0a 20 20 20 20 20 20 20 20  , 304)\.        
96e0: 20 20 20 20 6f 72 20 65 6e 76 69 72 6f 6e 5b 27      or environ['
96f0: 52 45 51 55 45 53 54 5f 4d 45 54 48 4f 44 27 5d  REQUEST_METHOD']
9700: 20 3d 3d 20 27 48 45 41 44 27 3a 0a 20 20 20 20   == 'HEAD':.    
9710: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 68              if h
9720: 61 73 61 74 74 72 28 6f 75 74 2c 20 27 63 6c 6f  asattr(out, 'clo
9730: 73 65 27 29 3a 20 6f 75 74 2e 63 6c 6f 73 65 28  se'): out.close(
9740: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
9750: 20 20 6f 75 74 20 3d 20 5b 5d 0a 20 20 20 20 20    out = [].     
9760: 20 20 20 20 20 20 20 73 74 61 72 74 5f 72 65 73         start_res
9770: 70 6f 6e 73 65 28 72 65 73 70 6f 6e 73 65 2e 5f  ponse(response._
9780: 73 74 61 74 75 73 5f 6c 69 6e 65 2c 20 72 65 73  status_line, res
9790: 70 6f 6e 73 65 2e 68 65 61 64 65 72 6c 69 73 74  ponse.headerlist
97a0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  ).            re
97b0: 74 75 72 6e 20 6f 75 74 0a 20 20 20 20 20 20 20  turn out.       
97c0: 20 65 78 63 65 70 74 20 28 4b 65 79 62 6f 61 72   except (Keyboar
97d0: 64 49 6e 74 65 72 72 75 70 74 2c 20 53 79 73 74  dInterrupt, Syst
97e0: 65 6d 45 78 69 74 2c 20 4d 65 6d 6f 72 79 45 72  emExit, MemoryEr
97f0: 72 6f 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ror):.          
9800: 20 20 72 61 69 73 65 0a 20 20 20 20 20 20 20 20    raise.        
9810: 65 78 63 65 70 74 20 45 78 63 65 70 74 69 6f 6e  except Exception
9820: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
9830: 20 6e 6f 74 20 73 65 6c 66 2e 63 61 74 63 68 61   not self.catcha
9840: 6c 6c 3a 20 72 61 69 73 65 0a 20 20 20 20 20 20  ll: raise.      
9850: 20 20 20 20 20 20 65 72 72 20 3d 20 27 3c 68 31        err = '<h1
9860: 3e 43 72 69 74 69 63 61 6c 20 65 72 72 6f 72 20  >Critical error 
9870: 77 68 69 6c 65 20 70 72 6f 63 65 73 73 69 6e 67  while processing
9880: 20 72 65 71 75 65 73 74 3a 20 25 73 3c 2f 68 31   request: %s</h1
9890: 3e 27 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20  >' \.           
98a0: 20 20 20 20 20 20 20 25 20 68 74 6d 6c 5f 65 73         % html_es
98b0: 63 61 70 65 28 65 6e 76 69 72 6f 6e 2e 67 65 74  cape(environ.get
98c0: 28 27 50 41 54 48 5f 49 4e 46 4f 27 2c 20 27 2f  ('PATH_INFO', '/
98d0: 27 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ')).            
98e0: 69 66 20 44 45 42 55 47 3a 0a 20 20 20 20 20 20  if DEBUG:.      
98f0: 20 20 20 20 20 20 20 20 20 20 65 72 72 20 2b 3d            err +=
9900: 20 27 3c 68 32 3e 45 72 72 6f 72 3a 3c 2f 68 32   '<h2>Error:</h2
9910: 3e 5c 6e 3c 70 72 65 3e 5c 6e 25 73 5c 6e 3c 2f  >\n<pre>\n%s\n</
9920: 70 72 65 3e 5c 6e 27 20 5c 0a 20 20 20 20 20 20  pre>\n' \.      
9930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9940: 20 27 3c 68 32 3e 54 72 61 63 65 62 61 63 6b 3a   '<h2>Traceback:
9950: 3c 2f 68 32 3e 5c 6e 3c 70 72 65 3e 5c 6e 25 73  </h2>\n<pre>\n%s
9960: 5c 6e 3c 2f 70 72 65 3e 5c 6e 27 20 5c 0a 20 20  \n</pre>\n' \.  
9970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9980: 20 20 20 20 20 25 20 28 68 74 6d 6c 5f 65 73 63       % (html_esc
9990: 61 70 65 28 72 65 70 72 28 5f 65 28 29 29 29 2c  ape(repr(_e())),
99a0: 20 68 74 6d 6c 5f 65 73 63 61 70 65 28 66 6f 72   html_escape(for
99b0: 6d 61 74 5f 65 78 63 28 29 29 29 0a 20 20 20 20  mat_exc())).    
99c0: 20 20 20 20 20 20 20 20 65 6e 76 69 72 6f 6e 5b          environ[
99d0: 27 77 73 67 69 2e 65 72 72 6f 72 73 27 5d 2e 77  'wsgi.errors'].w
99e0: 72 69 74 65 28 65 72 72 29 0a 20 20 20 20 20 20  rite(err).      
99f0: 20 20 20 20 20 20 68 65 61 64 65 72 73 20 3d 20        headers = 
9a00: 5b 28 27 43 6f 6e 74 65 6e 74 2d 54 79 70 65 27  [('Content-Type'
9a10: 2c 20 27 74 65 78 74 2f 68 74 6d 6c 3b 20 63 68  , 'text/html; ch
9a20: 61 72 73 65 74 3d 55 54 46 2d 38 27 29 5d 0a 20  arset=UTF-8')]. 
9a30: 20 20 20 20 20 20 20 20 20 20 20 73 74 61 72 74             start
9a40: 5f 72 65 73 70 6f 6e 73 65 28 27 35 30 30 20 49  _response('500 I
9a50: 4e 54 45 52 4e 41 4c 20 53 45 52 56 45 52 20 45  NTERNAL SERVER E
9a60: 52 52 4f 52 27 2c 20 68 65 61 64 65 72 73 2c 20  RROR', headers, 
9a70: 73 79 73 2e 65 78 63 5f 69 6e 66 6f 28 29 29 0a  sys.exc_info()).
9a80: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
9a90: 72 6e 20 5b 74 6f 62 28 65 72 72 29 5d 0a 0a 20  rn [tob(err)].. 
9aa0: 20 20 20 64 65 66 20 5f 5f 63 61 6c 6c 5f 5f 28     def __call__(
9ab0: 73 65 6c 66 2c 20 65 6e 76 69 72 6f 6e 2c 20 73  self, environ, s
9ac0: 74 61 72 74 5f 72 65 73 70 6f 6e 73 65 29 3a 0a  tart_response):.
9ad0: 20 20 20 20 20 20 20 20 27 27 27 20 45 61 63 68          ''' Each
9ae0: 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 3a 63 6c   instance of :cl
9af0: 61 73 73 3a 27 42 6f 74 74 6c 65 27 20 69 73 20  ass:'Bottle' is 
9b00: 61 20 57 53 47 49 20 61 70 70 6c 69 63 61 74 69  a WSGI applicati
9b10: 6f 6e 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20  on. '''.        
9b20: 72 65 74 75 72 6e 20 73 65 6c 66 2e 77 73 67 69  return self.wsgi
9b30: 28 65 6e 76 69 72 6f 6e 2c 20 73 74 61 72 74 5f  (environ, start_
9b40: 72 65 73 70 6f 6e 73 65 29 0a 0a 0a 0a 0a 0a 0a  response).......
9b50: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9b60: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9b70: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9b80: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9b90: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 0a  ###############.
9ba0: 23 20 48 54 54 50 20 61 6e 64 20 57 53 47 49 20  # HTTP and WSGI 
9bb0: 54 6f 6f 6c 73 20 23 23 23 23 23 23 23 23 23 23  Tools ##########
9bc0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9bd0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9be0: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9bf0: 0a 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  .###############
9c00: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9c10: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9c20: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9c30: 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
9c40: 0a 0a 63 6c 61 73 73 20 42 61 73 65 52 65 71 75  ..class BaseRequ
9c50: 65 73 74 28 6f 62 6a 65 63 74 29 3a 0a 20 20 20  est(object):.   
9c60: 20 22 22 22 20 41 20 77 72 61 70 70 65 72 20 66   """ A wrapper f
9c70: 6f 72 20 57 53 47 49 20 65 6e 76 69 72 6f 6e 6d  or WSGI environm
9c80: 65 6e 74 20 64 69 63 74 69 6f 6e 61 72 69 65 73  ent dictionaries
9c90: 20 74 68 61 74 20 61 64 64 73 20 61 20 6c 6f 74   that adds a lot
9ca0: 20 6f 66 0a 20 20 20 20 20 20 20 20 63 6f 6e 76   of.        conv
9cb0: 65 6e 69 65 6e 74 20 61 63 63 65 73 73 20 6d 65  enient access me
9cc0: 74 68 6f 64 73 20 61 6e 64 20 70 72 6f 70 65 72  thods and proper
9cd0: 74 69 65 73 2e 20 4d 6f 73 74 20 6f 66 20 74 68  ties. Most of th
9ce0: 65 6d 20 61 72 65 20 72 65 61 64 2d 6f 6e 6c 79  em are read-only
9cf0: 2e 0a 0a 20 20 20 20 20 20 20 20 41 64 64 69 6e  ...        Addin
9d00: 67 20 6e 65 77 20 61 74 74 72 69 62 75 74 65 73  g new attributes
9d10: 20 74 6f 20 61 20 72 65 71 75 65 73 74 20 61 63   to a request ac
9d20: 74 75 61 6c 6c 79 20 61 64 64 73 20 74 68 65 6d  tually adds them
9d30: 20 74 6f 20 74 68 65 20 65 6e 76 69 72 6f 6e 0a   to the environ.
9d40: 20 20 20 20 20 20 20 20 64 69 63 74 69 6f 6e 61          dictiona
9d50: 72 79 20 28 61 73 20 27 62 6f 74 74 6c 65 2e 72  ry (as 'bottle.r
9d60: 65 71 75 65 73 74 2e 65 78 74 2e 3c 6e 61 6d 65  equest.ext.<name
9d70: 3e 27 29 2e 20 54 68 69 73 20 69 73 20 74 68 65  >'). This is the
9d80: 20 72 65 63 6f 6d 6d 65 6e 64 65 64 0a 20 20 20   recommended.   
9d90: 20 20 20 20 20 77 61 79 20 74 6f 20 73 74 6f 72       way to stor
9da0: 65 20 61 6e 64 20 61 63 63 65 73 73 20 72 65 71  e and access req
9db0: 75 65 73 74 2d 73 70 65 63 69 66 69 63 20 64 61  uest-specific da
9dc0: 74 61 2e 0a 20 20 20 20 22 22 22 0a 0a 20 20 20  ta..    """..   
9dd0: 20 5f 5f 73 6c 6f 74 73 5f 5f 20 3d 20 28 27 65   __slots__ = ('e
9de0: 6e 76 69 72 6f 6e 27 29 0a 0a 20 20 20 20 23 3a  nviron')..    #:
9df0: 20 4d 61 78 69 6d 75 6d 20 73 69 7a 65 20 6f 66   Maximum size of
9e00: 20 6d 65 6d 6f 72 79 20 62 75 66 66 65 72 20 66   memory buffer f
9e10: 6f 72 20 3a 61 74 74 72 3a 60 62 6f 64 79 60 20  or :attr:`body` 
9e20: 69 6e 20 62 79 74 65 73 2e 0a 20 20 20 20 4d 45  in bytes..    ME
9e30: 4d 46 49 4c 45 5f 4d 41 58 20 3d 20 31 30 32 34  MFILE_MAX = 1024
9e40: 30 30 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e  00..    def __in
9e50: 69 74 5f 5f 28 73 65 6c 66 2c 20 65 6e 76 69 72  it__(self, envir
9e60: 6f 6e 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20  on=None):.      
9e70: 20 20 22 22 22 20 57 72 61 70 20 61 20 57 53 47    """ Wrap a WSG
9e80: 49 20 65 6e 76 69 72 6f 6e 20 64 69 63 74 69 6f  I environ dictio
9e90: 6e 61 72 79 2e 20 22 22 22 0a 20 20 20 20 20 20  nary. """.      
9ea0: 20 20 23 3a 20 54 68 65 20 77 72 61 70 70 65 64    #: The wrapped
9eb0: 20 57 53 47 49 20 65 6e 76 69 72 6f 6e 20 64 69   WSGI environ di
9ec0: 63 74 69 6f 6e 61 72 79 2e 20 54 68 69 73 20 69  ctionary. This i
9ed0: 73 20 74 68 65 20 6f 6e 6c 79 20 72 65 61 6c 20  s the only real 
9ee0: 61 74 74 72 69 62 75 74 65 2e 0a 20 20 20 20 20  attribute..     
9ef0: 20 20 20 23 3a 20 41 6c 6c 20 6f 74 68 65 72 20     #: All other 
9f00: 61 74 74 72 69 62 75 74 65 73 20 61 63 74 75 61  attributes actua
9f10: 6c 6c 79 20 61 72 65 20 72 65 61 64 2d 6f 6e 6c  lly are read-onl
9f20: 79 20 70 72 6f 70 65 72 74 69 65 73 2e 0a 20 20  y properties..  
9f30: 20 20 20 20 20 20 73 65 6c 66 2e 65 6e 76 69 72        self.envir
9f40: 6f 6e 20 3d 20 7b 7d 20 69 66 20 65 6e 76 69 72  on = {} if envir
9f50: 6f 6e 20 69 73 20 4e 6f 6e 65 20 65 6c 73 65 20  on is None else 
9f60: 65 6e 76 69 72 6f 6e 0a 20 20 20 20 20 20 20 20  environ.        
9f70: 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 5b 27 62 6f  self.environ['bo
9f80: 74 74 6c 65 2e 72 65 71 75 65 73 74 27 5d 20 3d  ttle.request'] =
9f90: 20 73 65 6c 66 0a 0a 20 20 20 20 40 44 69 63 74   self..    @Dict
9fa0: 50 72 6f 70 65 72 74 79 28 27 65 6e 76 69 72 6f  Property('enviro
9fb0: 6e 27 2c 20 27 62 6f 74 74 6c 65 2e 61 70 70 27  n', 'bottle.app'
9fc0: 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d 54 72 75 65  , read_only=True
9fd0: 29 0a 20 20 20 20 64 65 66 20 61 70 70 28 73 65  ).    def app(se
9fe0: 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27  lf):.        '''
9ff0: 20 42 6f 74 74 6c 65 20 61 70 70 6c 69 63 61 74   Bottle applicat
a000: 69 6f 6e 20 68 61 6e 64 6c 69 6e 67 20 74 68 69  ion handling thi
a010: 73 20 72 65 71 75 65 73 74 2e 20 27 27 27 0a 20  s request. '''. 
a020: 20 20 20 20 20 20 20 72 61 69 73 65 20 52 75 6e         raise Run
a030: 74 69 6d 65 45 72 72 6f 72 28 27 54 68 69 73 20  timeError('This 
a040: 72 65 71 75 65 73 74 20 69 73 20 6e 6f 74 20 63  request is not c
a050: 6f 6e 6e 65 63 74 65 64 20 74 6f 20 61 6e 20 61  onnected to an a
a060: 70 70 6c 69 63 61 74 69 6f 6e 2e 27 29 0a 0a 20  pplication.').. 
a070: 20 20 20 40 44 69 63 74 50 72 6f 70 65 72 74 79     @DictProperty
a080: 28 27 65 6e 76 69 72 6f 6e 27 2c 20 27 62 6f 74  ('environ', 'bot
a090: 74 6c 65 2e 72 6f 75 74 65 27 2c 20 72 65 61 64  tle.route', read
a0a0: 5f 6f 6e 6c 79 3d 54 72 75 65 29 0a 20 20 20 20  _only=True).    
a0b0: 64 65 66 20 72 6f 75 74 65 28 73 65 6c 66 29 3a  def route(self):
a0c0: 0a 20 20 20 20 20 20 20 20 22 22 22 20 54 68 65  .        """ The
a0d0: 20 62 6f 74 74 6c 65 20 3a 63 6c 61 73 73 3a 60   bottle :class:`
a0e0: 52 6f 75 74 65 60 20 6f 62 6a 65 63 74 20 74 68  Route` object th
a0f0: 61 74 20 6d 61 74 63 68 65 73 20 74 68 69 73 20  at matches this 
a100: 72 65 71 75 65 73 74 2e 20 22 22 22 0a 20 20 20  request. """.   
a110: 20 20 20 20 20 72 61 69 73 65 20 52 75 6e 74 69       raise Runti
a120: 6d 65 45 72 72 6f 72 28 27 54 68 69 73 20 72 65  meError('This re
a130: 71 75 65 73 74 20 69 73 20 6e 6f 74 20 63 6f 6e  quest is not con
a140: 6e 65 63 74 65 64 20 74 6f 20 61 20 72 6f 75 74  nected to a rout
a150: 65 2e 27 29 0a 0a 20 20 20 20 40 44 69 63 74 50  e.')..    @DictP
a160: 72 6f 70 65 72 74 79 28 27 65 6e 76 69 72 6f 6e  roperty('environ
a170: 27 2c 20 27 72 6f 75 74 65 2e 75 72 6c 5f 61 72  ', 'route.url_ar
a180: 67 73 27 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d 54  gs', read_only=T
a190: 72 75 65 29 0a 20 20 20 20 64 65 66 20 75 72 6c  rue).    def url
a1a0: 5f 61 72 67 73 28 73 65 6c 66 29 3a 0a 20 20 20  _args(self):.   
a1b0: 20 20 20 20 20 22 22 22 20 54 68 65 20 61 72 67       """ The arg
a1c0: 75 6d 65 6e 74 73 20 65 78 74 72 61 63 74 65 64  uments extracted
a1d0: 20 66 72 6f 6d 20 74 68 65 20 55 52 4c 2e 20 22   from the URL. "
a1e0: 22 22 0a 20 20 20 20 20 20 20 20 72 61 69 73 65  "".        raise
a1f0: 20 52 75 6e 74 69 6d 65 45 72 72 6f 72 28 27 54   RuntimeError('T
a200: 68 69 73 20 72 65 71 75 65 73 74 20 69 73 20 6e  his request is n
a210: 6f 74 20 63 6f 6e 6e 65 63 74 65 64 20 74 6f 20  ot connected to 
a220: 61 20 72 6f 75 74 65 2e 27 29 0a 0a 20 20 20 20  a route.')..    
a230: 40 70 72 6f 70 65 72 74 79 0a 20 20 20 20 64 65  @property.    de
a240: 66 20 70 61 74 68 28 73 65 6c 66 29 3a 0a 20 20  f path(self):.  
a250: 20 20 20 20 20 20 27 27 27 20 54 68 65 20 76 61        ''' The va
a260: 6c 75 65 20 6f 66 20 60 60 50 41 54 48 5f 49 4e  lue of ``PATH_IN
a270: 46 4f 60 60 20 77 69 74 68 20 65 78 61 63 74 6c  FO`` with exactl
a280: 79 20 6f 6e 65 20 70 72 65 66 69 78 65 64 20 73  y one prefixed s
a290: 6c 61 73 68 20 28 74 6f 20 66 69 78 0a 20 20 20  lash (to fix.   
a2a0: 20 20 20 20 20 20 20 20 20 62 72 6f 6b 65 6e 20           broken 
a2b0: 63 6c 69 65 6e 74 73 20 61 6e 64 20 61 76 6f 69  clients and avoi
a2c0: 64 20 74 68 65 20 22 65 6d 70 74 79 20 70 61 74  d the "empty pat
a2d0: 68 22 20 65 64 67 65 20 63 61 73 65 29 2e 20 27  h" edge case). '
a2e0: 27 27 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ''.        retur
a2f0: 6e 20 27 2f 27 20 2b 20 73 65 6c 66 2e 65 6e 76  n '/' + self.env
a300: 69 72 6f 6e 2e 67 65 74 28 27 50 41 54 48 5f 49  iron.get('PATH_I
a310: 4e 46 4f 27 2c 27 27 29 2e 6c 73 74 72 69 70 28  NFO','').lstrip(
a320: 27 2f 27 29 0a 0a 20 20 20 20 40 70 72 6f 70 65  '/')..    @prope
a330: 72 74 79 0a 20 20 20 20 64 65 66 20 6d 65 74 68  rty.    def meth
a340: 6f 64 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20  od(self):.      
a350: 20 20 27 27 27 20 54 68 65 20 60 60 52 45 51 55    ''' The ``REQU
a360: 45 53 54 5f 4d 45 54 48 4f 44 60 60 20 76 61 6c  EST_METHOD`` val
a370: 75 65 20 61 73 20 61 6e 20 75 70 70 65 72 63 61  ue as an upperca
a380: 73 65 20 73 74 72 69 6e 67 2e 20 27 27 27 0a 20  se string. '''. 
a390: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65         return se
a3a0: 6c 66 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27  lf.environ.get('
a3b0: 52 45 51 55 45 53 54 5f 4d 45 54 48 4f 44 27 2c  REQUEST_METHOD',
a3c0: 20 27 47 45 54 27 29 2e 75 70 70 65 72 28 29 0a   'GET').upper().
a3d0: 0a 20 20 20 20 40 44 69 63 74 50 72 6f 70 65 72  .    @DictProper
a3e0: 74 79 28 27 65 6e 76 69 72 6f 6e 27 2c 20 27 62  ty('environ', 'b
a3f0: 6f 74 74 6c 65 2e 72 65 71 75 65 73 74 2e 68 65  ottle.request.he
a400: 61 64 65 72 73 27 2c 20 72 65 61 64 5f 6f 6e 6c  aders', read_onl
a410: 79 3d 54 72 75 65 29 0a 20 20 20 20 64 65 66 20  y=True).    def 
a420: 68 65 61 64 65 72 73 28 73 65 6c 66 29 3a 0a 20  headers(self):. 
a430: 20 20 20 20 20 20 20 27 27 27 20 41 20 3a 63 6c         ''' A :cl
a440: 61 73 73 3a 60 57 53 47 49 48 65 61 64 65 72 44  ass:`WSGIHeaderD
a450: 69 63 74 60 20 74 68 61 74 20 70 72 6f 76 69 64  ict` that provid
a460: 65 73 20 63 61 73 65 2d 69 6e 73 65 6e 73 69 74  es case-insensit
a470: 69 76 65 20 61 63 63 65 73 73 20 74 6f 0a 20 20  ive access to.  
a480: 20 20 20 20 20 20 20 20 20 20 48 54 54 50 20 72            HTTP r
a490: 65 71 75 65 73 74 20 68 65 61 64 65 72 73 2e 20  equest headers. 
a4a0: 27 27 27 0a 20 20 20 20 20 20 20 20 72 65 74 75  '''.        retu
a4b0: 72 6e 20 57 53 47 49 48 65 61 64 65 72 44 69 63  rn WSGIHeaderDic
a4c0: 74 28 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 29 0a  t(self.environ).
a4d0: 0a 20 20 20 20 64 65 66 20 67 65 74 5f 68 65 61  .    def get_hea
a4e0: 64 65 72 28 73 65 6c 66 2c 20 6e 61 6d 65 2c 20  der(self, name, 
a4f0: 64 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20  default=None):. 
a500: 20 20 20 20 20 20 20 27 27 27 20 52 65 74 75 72         ''' Retur
a510: 6e 20 74 68 65 20 76 61 6c 75 65 20 6f 66 20 61  n the value of a
a520: 20 72 65 71 75 65 73 74 20 68 65 61 64 65 72 2c   request header,
a530: 20 6f 72 20 61 20 67 69 76 65 6e 20 64 65 66 61   or a given defa
a540: 75 6c 74 20 76 61 6c 75 65 2e 20 27 27 27 0a 20  ult value. '''. 
a550: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65         return se
a560: 6c 66 2e 68 65 61 64 65 72 73 2e 67 65 74 28 6e  lf.headers.get(n
a570: 61 6d 65 2c 20 64 65 66 61 75 6c 74 29 0a 0a 20  ame, default).. 
a580: 20 20 20 40 44 69 63 74 50 72 6f 70 65 72 74 79     @DictProperty
a590: 28 27 65 6e 76 69 72 6f 6e 27 2c 20 27 62 6f 74  ('environ', 'bot
a5a0: 74 6c 65 2e 72 65 71 75 65 73 74 2e 63 6f 6f 6b  tle.request.cook
a5b0: 69 65 73 27 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d  ies', read_only=
a5c0: 54 72 75 65 29 0a 20 20 20 20 64 65 66 20 63 6f  True).    def co
a5d0: 6f 6b 69 65 73 28 73 65 6c 66 29 3a 0a 20 20 20  okies(self):.   
a5e0: 20 20 20 20 20 22 22 22 20 43 6f 6f 6b 69 65 73       """ Cookies
a5f0: 20 70 61 72 73 65 64 20 69 6e 74 6f 20 61 20 3a   parsed into a :
a600: 63 6c 61 73 73 3a 60 46 6f 72 6d 73 44 69 63 74  class:`FormsDict
a610: 60 2e 20 53 69 67 6e 65 64 20 63 6f 6f 6b 69 65  `. Signed cookie
a620: 73 20 61 72 65 20 4e 4f 54 0a 20 20 20 20 20 20  s are NOT.      
a630: 20 20 20 20 20 20 64 65 63 6f 64 65 64 2e 20 55        decoded. U
a640: 73 65 20 3a 6d 65 74 68 3a 60 67 65 74 5f 63 6f  se :meth:`get_co
a650: 6f 6b 69 65 60 20 69 66 20 79 6f 75 20 65 78 70  okie` if you exp
a660: 65 63 74 20 73 69 67 6e 65 64 20 63 6f 6f 6b 69  ect signed cooki
a670: 65 73 2e 20 22 22 22 0a 20 20 20 20 20 20 20 20  es. """.        
a680: 63 6f 6f 6b 69 65 73 20 3d 20 53 69 6d 70 6c 65  cookies = Simple
a690: 43 6f 6f 6b 69 65 28 73 65 6c 66 2e 65 6e 76 69  Cookie(self.envi
a6a0: 72 6f 6e 2e 67 65 74 28 27 48 54 54 50 5f 43 4f  ron.get('HTTP_CO
a6b0: 4f 4b 49 45 27 2c 27 27 29 29 2e 76 61 6c 75 65  OKIE','')).value
a6c0: 73 28 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  s().        retu
a6d0: 72 6e 20 46 6f 72 6d 73 44 69 63 74 28 28 63 2e  rn FormsDict((c.
a6e0: 6b 65 79 2c 20 63 2e 76 61 6c 75 65 29 20 66 6f  key, c.value) fo
a6f0: 72 20 63 20 69 6e 20 63 6f 6f 6b 69 65 73 29 0a  r c in cookies).
a700: 0a 20 20 20 20 64 65 66 20 67 65 74 5f 63 6f 6f  .    def get_coo
a710: 6b 69 65 28 73 65 6c 66 2c 20 6b 65 79 2c 20 64  kie(self, key, d
a720: 65 66 61 75 6c 74 3d 4e 6f 6e 65 2c 20 73 65 63  efault=None, sec
a730: 72 65 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20  ret=None):.     
a740: 20 20 20 22 22 22 20 52 65 74 75 72 6e 20 74 68     """ Return th
a750: 65 20 63 6f 6e 74 65 6e 74 20 6f 66 20 61 20 63  e content of a c
a760: 6f 6f 6b 69 65 2e 20 54 6f 20 72 65 61 64 20 61  ookie. To read a
a770: 20 60 53 69 67 6e 65 64 20 43 6f 6f 6b 69 65 60   `Signed Cookie`
a780: 2c 20 74 68 65 0a 20 20 20 20 20 20 20 20 20 20  , the.          
a790: 20 20 60 73 65 63 72 65 74 60 20 6d 75 73 74 20    `secret` must 
a7a0: 6d 61 74 63 68 20 74 68 65 20 6f 6e 65 20 75 73  match the one us
a7b0: 65 64 20 74 6f 20 63 72 65 61 74 65 20 74 68 65  ed to create the
a7c0: 20 63 6f 6f 6b 69 65 20 28 73 65 65 0a 20 20 20   cookie (see.   
a7d0: 20 20 20 20 20 20 20 20 20 3a 6d 65 74 68 3a 60           :meth:`
a7e0: 42 61 73 65 52 65 73 70 6f 6e 73 65 2e 73 65 74  BaseResponse.set
a7f0: 5f 63 6f 6f 6b 69 65 60 29 2e 20 49 66 20 61 6e  _cookie`). If an
a800: 79 74 68 69 6e 67 20 67 6f 65 73 20 77 72 6f 6e  ything goes wron
a810: 67 20 28 6d 69 73 73 69 6e 67 0a 20 20 20 20 20  g (missing.     
a820: 20 20 20 20 20 20 20 63 6f 6f 6b 69 65 20 6f 72         cookie or
a830: 20 77 72 6f 6e 67 20 73 69 67 6e 61 74 75 72 65   wrong signature
a840: 29 2c 20 72 65 74 75 72 6e 20 61 20 64 65 66 61  ), return a defa
a850: 75 6c 74 20 76 61 6c 75 65 2e 20 22 22 22 0a 20  ult value. """. 
a860: 20 20 20 20 20 20 20 76 61 6c 75 65 20 3d 20 73         value = s
a870: 65 6c 66 2e 63 6f 6f 6b 69 65 73 2e 67 65 74 28  elf.cookies.get(
a880: 6b 65 79 29 0a 20 20 20 20 20 20 20 20 69 66 20  key).        if 
a890: 73 65 63 72 65 74 20 61 6e 64 20 76 61 6c 75 65  secret and value
a8a0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 65  :.            de
a8b0: 63 20 3d 20 63 6f 6f 6b 69 65 5f 64 65 63 6f 64  c = cookie_decod
a8c0: 65 28 76 61 6c 75 65 2c 20 73 65 63 72 65 74 29  e(value, secret)
a8d0: 20 23 20 28 6b 65 79 2c 20 76 61 6c 75 65 29 20   # (key, value) 
a8e0: 74 75 70 6c 65 20 6f 72 20 4e 6f 6e 65 0a 20 20  tuple or None.  
a8f0: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
a900: 20 64 65 63 5b 31 5d 20 69 66 20 64 65 63 20 61   dec[1] if dec a
a910: 6e 64 20 64 65 63 5b 30 5d 20 3d 3d 20 6b 65 79  nd dec[0] == key
a920: 20 65 6c 73 65 20 64 65 66 61 75 6c 74 0a 20 20   else default.  
a930: 20 20 20 20 20 20 72 65 74 75 72 6e 20 76 61 6c        return val
a940: 75 65 20 6f 72 20 64 65 66 61 75 6c 74 0a 0a 20  ue or default.. 
a950: 20 20 20 40 44 69 63 74 50 72 6f 70 65 72 74 79     @DictProperty
a960: 28 27 65 6e 76 69 72 6f 6e 27 2c 20 27 62 6f 74  ('environ', 'bot
a970: 74 6c 65 2e 72 65 71 75 65 73 74 2e 71 75 65 72  tle.request.quer
a980: 79 27 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d 54 72  y', read_only=Tr
a990: 75 65 29 0a 20 20 20 20 64 65 66 20 71 75 65 72  ue).    def quer
a9a0: 79 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20  y(self):.       
a9b0: 20 27 27 27 20 54 68 65 20 3a 61 74 74 72 3a 60   ''' The :attr:`
a9c0: 71 75 65 72 79 5f 73 74 72 69 6e 67 60 20 70 61  query_string` pa
a9d0: 72 73 65 64 20 69 6e 74 6f 20 61 20 3a 63 6c 61  rsed into a :cla
a9e0: 73 73 3a 60 46 6f 72 6d 73 44 69 63 74 60 2e 20  ss:`FormsDict`. 
a9f0: 54 68 65 73 65 0a 20 20 20 20 20 20 20 20 20 20  These.          
aa00: 20 20 76 61 6c 75 65 73 20 61 72 65 20 73 6f 6d    values are som
aa10: 65 74 69 6d 65 73 20 63 61 6c 6c 65 64 20 22 55  etimes called "U
aa20: 52 4c 20 61 72 67 75 6d 65 6e 74 73 22 20 6f 72  RL arguments" or
aa30: 20 22 47 45 54 20 70 61 72 61 6d 65 74 65 72 73   "GET parameters
aa40: 22 2c 20 62 75 74 0a 20 20 20 20 20 20 20 20 20  ", but.         
aa50: 20 20 20 6e 6f 74 20 74 6f 20 62 65 20 63 6f 6e     not to be con
aa60: 66 75 73 65 64 20 77 69 74 68 20 22 55 52 4c 20  fused with "URL 
aa70: 77 69 6c 64 63 61 72 64 73 22 20 61 73 20 74 68  wildcards" as th
aa80: 65 79 20 61 72 65 20 70 72 6f 76 69 64 65 64 20  ey are provided 
aa90: 62 79 20 74 68 65 0a 20 20 20 20 20 20 20 20 20  by the.         
aaa0: 20 20 20 3a 63 6c 61 73 73 3a 60 52 6f 75 74 65     :class:`Route
aab0: 72 60 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20  r`. '''.        
aac0: 67 65 74 20 3d 20 73 65 6c 66 2e 65 6e 76 69 72  get = self.envir
aad0: 6f 6e 5b 27 62 6f 74 74 6c 65 2e 67 65 74 27 5d  on['bottle.get']
aae0: 20 3d 20 46 6f 72 6d 73 44 69 63 74 28 29 0a 20   = FormsDict(). 
aaf0: 20 20 20 20 20 20 20 70 61 69 72 73 20 3d 20 5f         pairs = _
ab00: 70 61 72 73 65 5f 71 73 6c 28 73 65 6c 66 2e 65  parse_qsl(self.e
ab10: 6e 76 69 72 6f 6e 2e 67 65 74 28 27 51 55 45 52  nviron.get('QUER
ab20: 59 5f 53 54 52 49 4e 47 27 2c 20 27 27 29 29 0a  Y_STRING', '')).
ab30: 20 20 20 20 20 20 20 20 66 6f 72 20 6b 65 79 2c          for key,
ab40: 20 76 61 6c 75 65 20 69 6e 20 70 61 69 72 73 3a   value in pairs:
ab50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 67 65 74  .            get
ab60: 5b 6b 65 79 5d 20 3d 20 76 61 6c 75 65 0a 20 20  [key] = value.  
ab70: 20 20 20 20 20 20 72 65 74 75 72 6e 20 67 65 74        return get
ab80: 0a 0a 20 20 20 20 40 44 69 63 74 50 72 6f 70 65  ..    @DictPrope
ab90: 72 74 79 28 27 65 6e 76 69 72 6f 6e 27 2c 20 27  rty('environ', '
aba0: 62 6f 74 74 6c 65 2e 72 65 71 75 65 73 74 2e 66  bottle.request.f
abb0: 6f 72 6d 73 27 2c 20 72 65 61 64 5f 6f 6e 6c 79  orms', read_only
abc0: 3d 54 72 75 65 29 0a 20 20 20 20 64 65 66 20 66  =True).    def f
abd0: 6f 72 6d 73 28 73 65 6c 66 29 3a 0a 20 20 20 20  orms(self):.    
abe0: 20 20 20 20 22 22 22 20 46 6f 72 6d 20 76 61 6c      """ Form val
abf0: 75 65 73 20 70 61 72 73 65 64 20 66 72 6f 6d 20  ues parsed from 
ac00: 61 6e 20 60 75 72 6c 2d 65 6e 63 6f 64 65 64 60  an `url-encoded`
ac10: 20 6f 72 20 60 6d 75 6c 74 69 70 61 72 74 2f 66   or `multipart/f
ac20: 6f 72 6d 2d 64 61 74 61 60 0a 20 20 20 20 20 20  orm-data`.      
ac30: 20 20 20 20 20 20 65 6e 63 6f 64 65 64 20 50 4f        encoded PO
ac40: 53 54 20 6f 72 20 50 55 54 20 72 65 71 75 65 73  ST or PUT reques
ac50: 74 20 62 6f 64 79 2e 20 54 68 65 20 72 65 73 75  t body. The resu
ac60: 6c 74 20 69 73 20 72 65 74 75 72 6e 65 64 20 61  lt is returned a
ac70: 73 20 61 0a 20 20 20 20 20 20 20 20 20 20 20 20  s a.            
ac80: 3a 63 6c 61 73 73 3a 60 46 6f 72 6d 73 44 69 63  :class:`FormsDic
ac90: 74 60 2e 20 41 6c 6c 20 6b 65 79 73 20 61 6e 64  t`. All keys and
aca0: 20 76 61 6c 75 65 73 20 61 72 65 20 73 74 72 69   values are stri
acb0: 6e 67 73 2e 20 46 69 6c 65 20 75 70 6c 6f 61 64  ngs. File upload
acc0: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 61 72  s.            ar
acd0: 65 20 73 74 6f 72 65 64 20 73 65 70 61 72 61 74  e stored separat
ace0: 65 6c 79 20 69 6e 20 3a 61 74 74 72 3a 60 66 69  ely in :attr:`fi
acf0: 6c 65 73 60 2e 20 22 22 22 0a 20 20 20 20 20 20  les`. """.      
ad00: 20 20 66 6f 72 6d 73 20 3d 20 46 6f 72 6d 73 44    forms = FormsD
ad10: 69 63 74 28 29 0a 20 20 20 20 20 20 20 20 66 6f  ict().        fo
ad20: 72 20 6e 61 6d 65 2c 20 69 74 65 6d 20 69 6e 20  r name, item in 
ad30: 73 65 6c 66 2e 50 4f 53 54 2e 61 6c 6c 69 74 65  self.POST.allite
ad40: 6d 73 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ms():.          
ad50: 20 20 69 66 20 6e 6f 74 20 69 73 69 6e 73 74 61    if not isinsta
ad60: 6e 63 65 28 69 74 65 6d 2c 20 46 69 6c 65 55 70  nce(item, FileUp
ad70: 6c 6f 61 64 29 3a 0a 20 20 20 20 20 20 20 20 20  load):.         
ad80: 20 20 20 20 20 20 20 66 6f 72 6d 73 5b 6e 61 6d         forms[nam
ad90: 65 5d 20 3d 20 69 74 65 6d 0a 20 20 20 20 20 20  e] = item.      
ada0: 20 20 72 65 74 75 72 6e 20 66 6f 72 6d 73 0a 0a    return forms..
adb0: 20 20 20 20 40 44 69 63 74 50 72 6f 70 65 72 74      @DictPropert
adc0: 79 28 27 65 6e 76 69 72 6f 6e 27 2c 20 27 62 6f  y('environ', 'bo
add0: 74 74 6c 65 2e 72 65 71 75 65 73 74 2e 70 61 72  ttle.request.par
ade0: 61 6d 73 27 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d  ams', read_only=
adf0: 54 72 75 65 29 0a 20 20 20 20 64 65 66 20 70 61  True).    def pa
ae00: 72 61 6d 73 28 73 65 6c 66 29 3a 0a 20 20 20 20  rams(self):.    
ae10: 20 20 20 20 22 22 22 20 41 20 3a 63 6c 61 73 73      """ A :class
ae20: 3a 60 46 6f 72 6d 73 44 69 63 74 60 20 77 69 74  :`FormsDict` wit
ae30: 68 20 74 68 65 20 63 6f 6d 62 69 6e 65 64 20 76  h the combined v
ae40: 61 6c 75 65 73 20 6f 66 20 3a 61 74 74 72 3a 60  alues of :attr:`
ae50: 71 75 65 72 79 60 20 61 6e 64 0a 20 20 20 20 20  query` and.     
ae60: 20 20 20 20 20 20 20 3a 61 74 74 72 3a 60 66 6f         :attr:`fo
ae70: 72 6d 73 60 2e 20 46 69 6c 65 20 75 70 6c 6f 61  rms`. File uploa
ae80: 64 73 20 61 72 65 20 73 74 6f 72 65 64 20 69 6e  ds are stored in
ae90: 20 3a 61 74 74 72 3a 60 66 69 6c 65 73 60 2e 20   :attr:`files`. 
aea0: 22 22 22 0a 20 20 20 20 20 20 20 20 70 61 72 61  """.        para
aeb0: 6d 73 20 3d 20 46 6f 72 6d 73 44 69 63 74 28 29  ms = FormsDict()
aec0: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 6b 65 79  .        for key
aed0: 2c 20 76 61 6c 75 65 20 69 6e 20 73 65 6c 66 2e  , value in self.
aee0: 71 75 65 72 79 2e 61 6c 6c 69 74 65 6d 73 28 29  query.allitems()
aef0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 61  :.            pa
af00: 72 61 6d 73 5b 6b 65 79 5d 20 3d 20 76 61 6c 75  rams[key] = valu
af10: 65 0a 20 20 20 20 20 20 20 20 66 6f 72 20 6b 65  e.        for ke
af20: 79 2c 20 76 61 6c 75 65 20 69 6e 20 73 65 6c 66  y, value in self
af30: 2e 66 6f 72 6d 73 2e 61 6c 6c 69 74 65 6d 73 28  .forms.allitems(
af40: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 70  ):.            p
af50: 61 72 61 6d 73 5b 6b 65 79 5d 20 3d 20 76 61 6c  arams[key] = val
af60: 75 65 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ue.        retur
af70: 6e 20 70 61 72 61 6d 73 0a 0a 20 20 20 20 40 44  n params..    @D
af80: 69 63 74 50 72 6f 70 65 72 74 79 28 27 65 6e 76  ictProperty('env
af90: 69 72 6f 6e 27 2c 20 27 62 6f 74 74 6c 65 2e 72  iron', 'bottle.r
afa0: 65 71 75 65 73 74 2e 66 69 6c 65 73 27 2c 20 72  equest.files', r
afb0: 65 61 64 5f 6f 6e 6c 79 3d 54 72 75 65 29 0a 20  ead_only=True). 
afc0: 20 20 20 64 65 66 20 66 69 6c 65 73 28 73 65 6c     def files(sel
afd0: 66 29 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20  f):.        """ 
afe0: 46 69 6c 65 20 75 70 6c 6f 61 64 73 20 70 61 72  File uploads par
aff0: 73 65 64 20 66 72 6f 6d 20 60 6d 75 6c 74 69 70  sed from `multip
b000: 61 72 74 2f 66 6f 72 6d 2d 64 61 74 61 60 20 65  art/form-data` e
b010: 6e 63 6f 64 65 64 20 50 4f 53 54 20 6f 72 20 50  ncoded POST or P
b020: 55 54 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  UT.            r
b030: 65 71 75 65 73 74 20 62 6f 64 79 2e 20 54 68 65  equest body. The
b040: 20 76 61 6c 75 65 73 20 61 72 65 20 69 6e 73 74   values are inst
b050: 61 6e 63 65 73 20 6f 66 20 3a 63 6c 61 73 73 3a  ances of :class:
b060: 60 46 69 6c 65 55 70 6c 6f 61 64 60 2e 0a 0a 20  `FileUpload`... 
b070: 20 20 20 20 20 20 20 22 22 22 0a 20 20 20 20 20         """.     
b080: 20 20 20 66 69 6c 65 73 20 3d 20 46 6f 72 6d 73     files = Forms
b090: 44 69 63 74 28 29 0a 20 20 20 20 20 20 20 20 66  Dict().        f
b0a0: 6f 72 20 6e 61 6d 65 2c 20 69 74 65 6d 20 69 6e  or name, item in
b0b0: 20 73 65 6c 66 2e 50 4f 53 54 2e 61 6c 6c 69 74   self.POST.allit
b0c0: 65 6d 73 28 29 3a 0a 20 20 20 20 20 20 20 20 20  ems():.         
b0d0: 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63 65     if isinstance
b0e0: 28 69 74 65 6d 2c 20 46 69 6c 65 55 70 6c 6f 61  (item, FileUploa
b0f0: 64 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  d):.            
b100: 20 20 20 20 66 69 6c 65 73 5b 6e 61 6d 65 5d 20      files[name] 
b110: 3d 20 69 74 65 6d 0a 20 20 20 20 20 20 20 20 72  = item.        r
b120: 65 74 75 72 6e 20 66 69 6c 65 73 0a 0a 20 20 20  eturn files..   
b130: 20 40 44 69 63 74 50 72 6f 70 65 72 74 79 28 27   @DictProperty('
b140: 65 6e 76 69 72 6f 6e 27 2c 20 27 62 6f 74 74 6c  environ', 'bottl
b150: 65 2e 72 65 71 75 65 73 74 2e 6a 73 6f 6e 27 2c  e.request.json',
b160: 20 72 65 61 64 5f 6f 6e 6c 79 3d 54 72 75 65 29   read_only=True)
b170: 0a 20 20 20 20 64 65 66 20 6a 73 6f 6e 28 73 65  .    def json(se
b180: 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27  lf):.        '''
b190: 20 49 66 20 74 68 65 20 60 60 43 6f 6e 74 65 6e   If the ``Conten
b1a0: 74 2d 54 79 70 65 60 60 20 68 65 61 64 65 72 20  t-Type`` header 
b1b0: 69 73 20 60 60 61 70 70 6c 69 63 61 74 69 6f 6e  is ``application
b1c0: 2f 6a 73 6f 6e 60 60 2c 20 74 68 69 73 0a 20 20  /json``, this.  
b1d0: 20 20 20 20 20 20 20 20 20 20 70 72 6f 70 65 72            proper
b1e0: 74 79 20 68 6f 6c 64 73 20 74 68 65 20 70 61 72  ty holds the par
b1f0: 73 65 64 20 63 6f 6e 74 65 6e 74 20 6f 66 20 74  sed content of t
b200: 68 65 20 72 65 71 75 65 73 74 20 62 6f 64 79 2e  he request body.
b210: 20 4f 6e 6c 79 20 72 65 71 75 65 73 74 73 0a 20   Only requests. 
b220: 20 20 20 20 20 20 20 20 20 20 20 73 6d 61 6c 6c             small
b230: 65 72 20 74 68 61 6e 20 3a 61 74 74 72 3a 60 4d  er than :attr:`M
b240: 45 4d 46 49 4c 45 5f 4d 41 58 60 20 61 72 65 20  EMFILE_MAX` are 
b250: 70 72 6f 63 65 73 73 65 64 20 74 6f 20 61 76 6f  processed to avo
b260: 69 64 20 6d 65 6d 6f 72 79 0a 20 20 20 20 20 20  id memory.      
b270: 20 20 20 20 20 20 65 78 68 61 75 73 74 69 6f 6e        exhaustion
b280: 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20 63 74  . '''.        ct
b290: 79 70 65 20 3d 20 73 65 6c 66 2e 65 6e 76 69 72  ype = self.envir
b2a0: 6f 6e 2e 67 65 74 28 27 43 4f 4e 54 45 4e 54 5f  on.get('CONTENT_
b2b0: 54 59 50 45 27 2c 20 27 27 29 2e 6c 6f 77 65 72  TYPE', '').lower
b2c0: 28 29 2e 73 70 6c 69 74 28 27 3b 27 29 5b 30 5d  ().split(';')[0]
b2d0: 0a 20 20 20 20 20 20 20 20 69 66 20 63 74 79 70  .        if ctyp
b2e0: 65 20 3d 3d 20 27 61 70 70 6c 69 63 61 74 69 6f  e == 'applicatio
b2f0: 6e 2f 6a 73 6f 6e 27 3a 0a 20 20 20 20 20 20 20  n/json':.       
b300: 20 20 20 20 20 62 20 3d 20 73 65 6c 66 2e 5f 67       b = self._g
b310: 65 74 5f 62 6f 64 79 5f 73 74 72 69 6e 67 28 29  et_body_string()
b320: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
b330: 6e 6f 74 20 62 3a 0a 20 20 20 20 20 20 20 20 20  not b:.         
b340: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f         return No
b350: 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  ne.            r
b360: 65 74 75 72 6e 20 6a 73 6f 6e 5f 6c 6f 61 64 73  eturn json_loads
b370: 28 62 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  (b).        retu
b380: 72 6e 20 4e 6f 6e 65 0a 0a 20 20 20 20 64 65 66  rn None..    def
b390: 20 5f 69 74 65 72 5f 62 6f 64 79 28 73 65 6c 66   _iter_body(self
b3a0: 2c 20 72 65 61 64 2c 20 62 75 66 73 69 7a 65 29  , read, bufsize)
b3b0: 3a 0a 20 20 20 20 20 20 20 20 6d 61 78 72 65 61  :.        maxrea
b3c0: 64 20 3d 20 6d 61 78 28 30 2c 20 73 65 6c 66 2e  d = max(0, self.
b3d0: 63 6f 6e 74 65 6e 74 5f 6c 65 6e 67 74 68 29 0a  content_length).
b3e0: 20 20 20 20 20 20 20 20 77 68 69 6c 65 20 6d 61          while ma
b3f0: 78 72 65 61 64 3a 0a 20 20 20 20 20 20 20 20 20  xread:.         
b400: 20 20 20 70 61 72 74 20 3d 20 72 65 61 64 28 6d     part = read(m
b410: 69 6e 28 6d 61 78 72 65 61 64 2c 20 62 75 66 73  in(maxread, bufs
b420: 69 7a 65 29 29 0a 20 20 20 20 20 20 20 20 20 20  ize)).          
b430: 20 20 69 66 20 6e 6f 74 20 70 61 72 74 3a 20 62    if not part: b
b440: 72 65 61 6b 0a 20 20 20 20 20 20 20 20 20 20 20  reak.           
b450: 20 79 69 65 6c 64 20 70 61 72 74 0a 20 20 20 20   yield part.    
b460: 20 20 20 20 20 20 20 20 6d 61 78 72 65 61 64 20          maxread 
b470: 2d 3d 20 6c 65 6e 28 70 61 72 74 29 0a 0a 20 20  -= len(part)..  
b480: 20 20 64 65 66 20 5f 69 74 65 72 5f 63 68 75 6e    def _iter_chun
b490: 6b 65 64 28 73 65 6c 66 2c 20 72 65 61 64 2c 20  ked(self, read, 
b4a0: 62 75 66 73 69 7a 65 29 3a 0a 20 20 20 20 20 20  bufsize):.      
b4b0: 20 20 65 72 72 20 3d 20 48 54 54 50 45 72 72 6f    err = HTTPErro
b4c0: 72 28 34 30 30 2c 20 27 45 72 72 6f 72 20 77 68  r(400, 'Error wh
b4d0: 69 6c 65 20 70 61 72 73 69 6e 67 20 63 68 75 6e  ile parsing chun
b4e0: 6b 65 64 20 74 72 61 6e 73 66 65 72 20 62 6f 64  ked transfer bod
b4f0: 79 2e 27 29 0a 20 20 20 20 20 20 20 20 72 6e 2c  y.').        rn,
b500: 20 73 65 6d 2c 20 62 73 20 3d 20 74 6f 62 28 27   sem, bs = tob('
b510: 5c 72 5c 6e 27 29 2c 20 74 6f 62 28 27 3b 27 29  \r\n'), tob(';')
b520: 2c 20 74 6f 62 28 27 27 29 0a 20 20 20 20 20 20  , tob('').      
b530: 20 20 77 68 69 6c 65 20 54 72 75 65 3a 0a 20 20    while True:.  
b540: 20 20 20 20 20 20 20 20 20 20 68 65 61 64 65 72            header
b550: 20 3d 20 72 65 61 64 28 31 29 0a 20 20 20 20 20   = read(1).     
b560: 20 20 20 20 20 20 20 77 68 69 6c 65 20 68 65 61         while hea
b570: 64 65 72 5b 2d 32 3a 5d 20 21 3d 20 72 6e 3a 0a  der[-2:] != rn:.
b580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b590: 63 20 3d 20 72 65 61 64 28 31 29 0a 20 20 20 20  c = read(1).    
b5a0: 20 20 20 20 20 20 20 20 20 20 20 20 68 65 61 64              head
b5b0: 65 72 20 2b 3d 20 63 0a 20 20 20 20 20 20 20 20  er += c.        
b5c0: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 63          if not c
b5d0: 3a 20 72 61 69 73 65 20 65 72 72 0a 20 20 20 20  : raise err.    
b5e0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6c              if l
b5f0: 65 6e 28 68 65 61 64 65 72 29 20 3e 20 62 75 66  en(header) > buf
b600: 73 69 7a 65 3a 20 72 61 69 73 65 20 65 72 72 0a  size: raise err.
b610: 20 20 20 20 20 20 20 20 20 20 20 20 73 69 7a 65              size
b620: 2c 20 5f 2c 20 5f 20 3d 20 68 65 61 64 65 72 2e  , _, _ = header.
b630: 70 61 72 74 69 74 69 6f 6e 28 73 65 6d 29 0a 20  partition(sem). 
b640: 20 20 20 20 20 20 20 20 20 20 20 74 72 79 3a 0a             try:.
b650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b660: 6d 61 78 72 65 61 64 20 3d 20 69 6e 74 28 74 6f  maxread = int(to
b670: 6e 61 74 28 73 69 7a 65 2e 73 74 72 69 70 28 29  nat(size.strip()
b680: 29 2c 20 31 36 29 0a 20 20 20 20 20 20 20 20 20  ), 16).         
b690: 20 20 20 65 78 63 65 70 74 20 56 61 6c 75 65 45     except ValueE
b6a0: 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20  rror:.          
b6b0: 20 20 20 20 20 20 72 61 69 73 65 20 65 72 72 0a        raise err.
b6c0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6d              if m
b6d0: 61 78 72 65 61 64 20 3d 3d 20 30 3a 20 62 72 65  axread == 0: bre
b6e0: 61 6b 0a 20 20 20 20 20 20 20 20 20 20 20 20 62  ak.            b
b6f0: 75 66 66 20 3d 20 62 73 0a 20 20 20 20 20 20 20  uff = bs.       
b700: 20 20 20 20 20 77 68 69 6c 65 20 6d 61 78 72 65       while maxre
b710: 61 64 20 3e 20 30 3a 0a 20 20 20 20 20 20 20 20  ad > 0:.        
b720: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 62          if not b
b730: 75 66 66 3a 0a 20 20 20 20 20 20 20 20 20 20 20  uff:.           
b740: 20 20 20 20 20 20 20 20 20 62 75 66 66 20 3d 20           buff = 
b750: 72 65 61 64 28 6d 69 6e 28 6d 61 78 72 65 61 64  read(min(maxread
b760: 2c 20 62 75 66 73 69 7a 65 29 29 0a 20 20 20 20  , bufsize)).    
b770: 20 20 20 20 20 20 20 20 20 20 20 20 70 61 72 74              part
b780: 2c 20 62 75 66 66 20 3d 20 62 75 66 66 5b 3a 6d  , buff = buff[:m
b790: 61 78 72 65 61 64 5d 2c 20 62 75 66 66 5b 6d 61  axread], buff[ma
b7a0: 78 72 65 61 64 3a 5d 0a 20 20 20 20 20 20 20 20  xread:].        
b7b0: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 70          if not p
b7c0: 61 72 74 3a 20 72 61 69 73 65 20 65 72 72 0a 20  art: raise err. 
b7d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79                 y
b7e0: 69 65 6c 64 20 70 61 72 74 0a 20 20 20 20 20 20  ield part.      
b7f0: 20 20 20 20 20 20 20 20 20 20 6d 61 78 72 65 61            maxrea
b800: 64 20 2d 3d 20 6c 65 6e 28 70 61 72 74 29 0a 20  d -= len(part). 
b810: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 72 65             if re
b820: 61 64 28 32 29 20 21 3d 20 72 6e 3a 0a 20 20 20  ad(2) != rn:.   
b830: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 61 69               rai
b840: 73 65 20 65 72 72 0a 0a 20 20 20 20 40 44 69 63  se err..    @Dic
b850: 74 50 72 6f 70 65 72 74 79 28 27 65 6e 76 69 72  tProperty('envir
b860: 6f 6e 27 2c 20 27 62 6f 74 74 6c 65 2e 72 65 71  on', 'bottle.req
b870: 75 65 73 74 2e 62 6f 64 79 27 2c 20 72 65 61 64  uest.body', read
b880: 5f 6f 6e 6c 79 3d 54 72 75 65 29 0a 20 20 20 20  _only=True).    
b890: 64 65 66 20 5f 62 6f 64 79 28 73 65 6c 66 29 3a  def _body(self):
b8a0: 0a 20 20 20 20 20 20 20 20 62 6f 64 79 5f 69 74  .        body_it
b8b0: 65 72 20 3d 20 73 65 6c 66 2e 5f 69 74 65 72 5f  er = self._iter_
b8c0: 63 68 75 6e 6b 65 64 20 69 66 20 73 65 6c 66 2e  chunked if self.
b8d0: 63 68 75 6e 6b 65 64 20 65 6c 73 65 20 73 65 6c  chunked else sel
b8e0: 66 2e 5f 69 74 65 72 5f 62 6f 64 79 0a 20 20 20  f._iter_body.   
b8f0: 20 20 20 20 20 72 65 61 64 5f 66 75 6e 63 20 3d       read_func =
b900: 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 5b 27 77   self.environ['w
b910: 73 67 69 2e 69 6e 70 75 74 27 5d 2e 72 65 61 64  sgi.input'].read
b920: 0a 20 20 20 20 20 20 20 20 62 6f 64 79 2c 20 62  .        body, b
b930: 6f 64 79 5f 73 69 7a 65 2c 20 69 73 5f 74 65 6d  ody_size, is_tem
b940: 70 5f 66 69 6c 65 20 3d 20 42 79 74 65 73 49 4f  p_file = BytesIO
b950: 28 29 2c 20 30 2c 20 46 61 6c 73 65 0a 20 20 20  (), 0, False.   
b960: 20 20 20 20 20 66 6f 72 20 70 61 72 74 20 69 6e       for part in
b970: 20 62 6f 64 79 5f 69 74 65 72 28 72 65 61 64 5f   body_iter(read_
b980: 66 75 6e 63 2c 20 73 65 6c 66 2e 4d 45 4d 46 49  func, self.MEMFI
b990: 4c 45 5f 4d 41 58 29 3a 0a 20 20 20 20 20 20 20  LE_MAX):.       
b9a0: 20 20 20 20 20 62 6f 64 79 2e 77 72 69 74 65 28       body.write(
b9b0: 70 61 72 74 29 0a 20 20 20 20 20 20 20 20 20 20  part).          
b9c0: 20 20 62 6f 64 79 5f 73 69 7a 65 20 2b 3d 20 6c    body_size += l
b9d0: 65 6e 28 70 61 72 74 29 0a 20 20 20 20 20 20 20  en(part).       
b9e0: 20 20 20 20 20 69 66 20 6e 6f 74 20 69 73 5f 74       if not is_t
b9f0: 65 6d 70 5f 66 69 6c 65 20 61 6e 64 20 62 6f 64  emp_file and bod
ba00: 79 5f 73 69 7a 65 20 3e 20 73 65 6c 66 2e 4d 45  y_size > self.ME
ba10: 4d 46 49 4c 45 5f 4d 41 58 3a 0a 20 20 20 20 20  MFILE_MAX:.     
ba20: 20 20 20 20 20 20 20 20 20 20 20 62 6f 64 79 2c             body,
ba30: 20 74 6d 70 20 3d 20 54 65 6d 70 6f 72 61 72 79   tmp = Temporary
ba40: 46 69 6c 65 28 6d 6f 64 65 3d 27 77 2b 62 27 29  File(mode='w+b')
ba50: 2c 20 62 6f 64 79 0a 20 20 20 20 20 20 20 20 20  , body.         
ba60: 20 20 20 20 20 20 20 62 6f 64 79 2e 77 72 69 74         body.writ
ba70: 65 28 74 6d 70 2e 67 65 74 76 61 6c 75 65 28 29  e(tmp.getvalue()
ba80: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
ba90: 20 20 64 65 6c 20 74 6d 70 0a 20 20 20 20 20 20    del tmp.      
baa0: 20 20 20 20 20 20 20 20 20 20 69 73 5f 74 65 6d            is_tem
bab0: 70 5f 66 69 6c 65 20 3d 20 54 72 75 65 0a 20 20  p_file = True.  
bac0: 20 20 20 20 20 20 73 65 6c 66 2e 65 6e 76 69 72        self.envir
bad0: 6f 6e 5b 27 77 73 67 69 2e 69 6e 70 75 74 27 5d  on['wsgi.input']
bae0: 20 3d 20 62 6f 64 79 0a 20 20 20 20 20 20 20 20   = body.        
baf0: 62 6f 64 79 2e 73 65 65 6b 28 30 29 0a 20 20 20  body.seek(0).   
bb00: 20 20 20 20 20 72 65 74 75 72 6e 20 62 6f 64 79       return body
bb10: 0a 0a 20 20 20 20 64 65 66 20 5f 67 65 74 5f 62  ..    def _get_b
bb20: 6f 64 79 5f 73 74 72 69 6e 67 28 73 65 6c 66 29  ody_string(self)
bb30: 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 72 65  :.        ''' re
bb40: 61 64 20 62 6f 64 79 20 75 6e 74 69 6c 20 63 6f  ad body until co
bb50: 6e 74 65 6e 74 2d 6c 65 6e 67 74 68 20 6f 72 20  ntent-length or 
bb60: 4d 45 4d 46 49 4c 45 5f 4d 41 58 20 69 6e 74 6f  MEMFILE_MAX into
bb70: 20 61 20 73 74 72 69 6e 67 2e 20 52 61 69 73 65   a string. Raise
bb80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 48 54 54  .            HTT
bb90: 50 45 72 72 6f 72 28 34 31 33 29 20 6f 6e 20 72  PError(413) on r
bba0: 65 71 75 65 73 74 73 20 74 68 61 74 20 61 72 65  equests that are
bbb0: 20 74 6f 20 6c 61 72 67 65 2e 20 27 27 27 0a 20   to large. '''. 
bbc0: 20 20 20 20 20 20 20 63 6c 65 6e 20 3d 20 73 65         clen = se
bbd0: 6c 66 2e 63 6f 6e 74 65 6e 74 5f 6c 65 6e 67 74  lf.content_lengt
bbe0: 68 0a 20 20 20 20 20 20 20 20 69 66 20 63 6c 65  h.        if cle
bbf0: 6e 20 3e 20 73 65 6c 66 2e 4d 45 4d 46 49 4c 45  n > self.MEMFILE
bc00: 5f 4d 41 58 3a 0a 20 20 20 20 20 20 20 20 20 20  _MAX:.          
bc10: 20 20 72 61 69 73 65 20 48 54 54 50 45 72 72 6f    raise HTTPErro
bc20: 72 28 34 31 33 2c 20 27 52 65 71 75 65 73 74 20  r(413, 'Request 
bc30: 74 6f 20 6c 61 72 67 65 27 29 0a 20 20 20 20 20  to large').     
bc40: 20 20 20 69 66 20 63 6c 65 6e 20 3c 20 30 3a 20     if clen < 0: 
bc50: 63 6c 65 6e 20 3d 20 73 65 6c 66 2e 4d 45 4d 46  clen = self.MEMF
bc60: 49 4c 45 5f 4d 41 58 20 2b 20 31 0a 20 20 20 20  ILE_MAX + 1.    
bc70: 20 20 20 20 64 61 74 61 20 3d 20 73 65 6c 66 2e      data = self.
bc80: 62 6f 64 79 2e 72 65 61 64 28 63 6c 65 6e 29 0a  body.read(clen).
bc90: 20 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 64          if len(d
bca0: 61 74 61 29 20 3e 20 73 65 6c 66 2e 4d 45 4d 46  ata) > self.MEMF
bcb0: 49 4c 45 5f 4d 41 58 3a 20 23 20 46 61 69 6c 20  ILE_MAX: # Fail 
bcc0: 66 61 73 74 0a 20 20 20 20 20 20 20 20 20 20 20  fast.           
bcd0: 20 72 61 69 73 65 20 48 54 54 50 45 72 72 6f 72   raise HTTPError
bce0: 28 34 31 33 2c 20 27 52 65 71 75 65 73 74 20 74  (413, 'Request t
bcf0: 6f 20 6c 61 72 67 65 27 29 0a 20 20 20 20 20 20  o large').      
bd00: 20 20 72 65 74 75 72 6e 20 64 61 74 61 0a 0a 20    return data.. 
bd10: 20 20 20 40 70 72 6f 70 65 72 74 79 0a 20 20 20     @property.   
bd20: 20 64 65 66 20 62 6f 64 79 28 73 65 6c 66 29 3a   def body(self):
bd30: 0a 20 20 20 20 20 20 20 20 22 22 22 20 54 68 65  .        """ The
bd40: 20 48 54 54 50 20 72 65 71 75 65 73 74 20 62 6f   HTTP request bo
bd50: 64 79 20 61 73 20 61 20 73 65 65 6b 2d 61 62 6c  dy as a seek-abl
bd60: 65 20 66 69 6c 65 2d 6c 69 6b 65 20 6f 62 6a 65  e file-like obje
bd70: 63 74 2e 20 44 65 70 65 6e 64 69 6e 67 20 6f 6e  ct. Depending on
bd80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a 61 74  .            :at
bd90: 74 72 3a 60 4d 45 4d 46 49 4c 45 5f 4d 41 58 60  tr:`MEMFILE_MAX`
bda0: 2c 20 74 68 69 73 20 69 73 20 65 69 74 68 65 72  , this is either
bdb0: 20 61 20 74 65 6d 70 6f 72 61 72 79 20 66 69 6c   a temporary fil
bdc0: 65 20 6f 72 20 61 0a 20 20 20 20 20 20 20 20 20  e or a.         
bdd0: 20 20 20 3a 63 6c 61 73 73 3a 60 69 6f 2e 42 79     :class:`io.By
bde0: 74 65 73 49 4f 60 20 69 6e 73 74 61 6e 63 65 2e  tesIO` instance.
bdf0: 20 41 63 63 65 73 73 69 6e 67 20 74 68 69 73 20   Accessing this 
be00: 70 72 6f 70 65 72 74 79 20 66 6f 72 20 74 68 65  property for the
be10: 20 66 69 72 73 74 0a 20 20 20 20 20 20 20 20 20   first.         
be20: 20 20 20 74 69 6d 65 20 72 65 61 64 73 20 61 6e     time reads an
be30: 64 20 72 65 70 6c 61 63 65 73 20 74 68 65 20 60  d replaces the `
be40: 60 77 73 67 69 2e 69 6e 70 75 74 60 60 20 65 6e  `wsgi.input`` en
be50: 76 69 72 6f 6e 20 76 61 72 69 61 62 6c 65 2e 0a  viron variable..
be60: 20 20 20 20 20 20 20 20 20 20 20 20 53 75 62 73              Subs
be70: 65 71 75 65 6e 74 20 61 63 63 65 73 73 65 73 20  equent accesses 
be80: 6a 75 73 74 20 64 6f 20 61 20 60 73 65 65 6b 28  just do a `seek(
be90: 30 29 60 20 6f 6e 20 74 68 65 20 66 69 6c 65 20  0)` on the file 
bea0: 6f 62 6a 65 63 74 2e 20 22 22 22 0a 20 20 20 20  object. """.    
beb0: 20 20 20 20 73 65 6c 66 2e 5f 62 6f 64 79 2e 73      self._body.s
bec0: 65 65 6b 28 30 29 0a 20 20 20 20 20 20 20 20 72  eek(0).        r
bed0: 65 74 75 72 6e 20 73 65 6c 66 2e 5f 62 6f 64 79  eturn self._body
bee0: 0a 0a 20 20 20 20 40 70 72 6f 70 65 72 74 79 0a  ..    @property.
bef0: 20 20 20 20 64 65 66 20 63 68 75 6e 6b 65 64 28      def chunked(
bf00: 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 27  self):.        '
bf10: 27 27 20 54 72 75 65 20 69 66 20 43 68 75 6e 6b  '' True if Chunk
bf20: 65 64 20 74 72 61 6e 73 66 65 72 20 65 6e 63 6f  ed transfer enco
bf30: 64 69 6e 67 20 77 61 73 2e 20 27 27 27 0a 20 20  ding was. '''.  
bf40: 20 20 20 20 20 20 72 65 74 75 72 6e 20 27 63 68        return 'ch
bf50: 75 6e 6b 65 64 27 20 69 6e 20 73 65 6c 66 2e 65  unked' in self.e
bf60: 6e 76 69 72 6f 6e 2e 67 65 74 28 27 48 54 54 50  nviron.get('HTTP
bf70: 5f 54 52 41 4e 53 46 45 52 5f 45 4e 43 4f 44 49  _TRANSFER_ENCODI
bf80: 4e 47 27 2c 20 27 27 29 2e 6c 6f 77 65 72 28 29  NG', '').lower()
bf90: 0a 0a 20 20 20 20 23 3a 20 41 6e 20 61 6c 69 61  ..    #: An alia
bfa0: 73 20 66 6f 72 20 3a 61 74 74 72 3a 60 71 75 65  s for :attr:`que
bfb0: 72 79 60 2e 0a 20 20 20 20 47 45 54 20 3d 20 71  ry`..    GET = q
bfc0: 75 65 72 79 0a 0a 20 20 20 20 40 44 69 63 74 50  uery..    @DictP
bfd0: 72 6f 70 65 72 74 79 28 27 65 6e 76 69 72 6f 6e  roperty('environ
bfe0: 27 2c 20 27 62 6f 74 74 6c 65 2e 72 65 71 75 65  ', 'bottle.reque
bff0: 73 74 2e 70 6f 73 74 27 2c 20 72 65 61 64 5f 6f  st.post', read_o
c000: 6e 6c 79 3d 54 72 75 65 29 0a 20 20 20 20 64 65  nly=True).    de
c010: 66 20 50 4f 53 54 28 73 65 6c 66 29 3a 0a 20 20  f POST(self):.  
c020: 20 20 20 20 20 20 22 22 22 20 54 68 65 20 76 61        """ The va
c030: 6c 75 65 73 20 6f 66 20 3a 61 74 74 72 3a 60 66  lues of :attr:`f
c040: 6f 72 6d 73 60 20 61 6e 64 20 3a 61 74 74 72 3a  orms` and :attr:
c050: 60 66 69 6c 65 73 60 20 63 6f 6d 62 69 6e 65 64  `files` combined
c060: 20 69 6e 74 6f 20 61 20 73 69 6e 67 6c 65 0a 20   into a single. 
c070: 20 20 20 20 20 20 20 20 20 20 20 3a 63 6c 61 73             :clas
c080: 73 3a 60 46 6f 72 6d 73 44 69 63 74 60 2e 20 56  s:`FormsDict`. V
c090: 61 6c 75 65 73 20 61 72 65 20 65 69 74 68 65 72  alues are either
c0a0: 20 73 74 72 69 6e 67 73 20 28 66 6f 72 6d 20 76   strings (form v
c0b0: 61 6c 75 65 73 29 20 6f 72 0a 20 20 20 20 20 20  alues) or.      
c0c0: 20 20 20 20 20 20 69 6e 73 74 61 6e 63 65 73 20        instances 
c0d0: 6f 66 20 3a 63 6c 61 73 73 3a 60 63 67 69 2e 46  of :class:`cgi.F
c0e0: 69 65 6c 64 53 74 6f 72 61 67 65 60 20 28 66 69  ieldStorage` (fi
c0f0: 6c 65 20 75 70 6c 6f 61 64 73 29 2e 0a 20 20 20  le uploads)..   
c100: 20 20 20 20 20 22 22 22 0a 20 20 20 20 20 20 20       """.       
c110: 20 70 6f 73 74 20 3d 20 46 6f 72 6d 73 44 69 63   post = FormsDic
c120: 74 28 29 0a 20 20 20 20 20 20 20 20 23 20 57 65  t().        # We
c130: 20 64 65 66 61 75 6c 74 20 74 6f 20 61 70 70 6c   default to appl
c140: 69 63 61 74 69 6f 6e 2f 78 2d 77 77 77 2d 66 6f  ication/x-www-fo
c150: 72 6d 2d 75 72 6c 65 6e 63 6f 64 65 64 20 66 6f  rm-urlencoded fo
c160: 72 20 65 76 65 72 79 74 68 69 6e 67 20 74 68 61  r everything tha
c170: 74 0a 20 20 20 20 20 20 20 20 23 20 69 73 20 6e  t.        # is n
c180: 6f 74 20 6d 75 6c 74 69 70 61 72 74 20 61 6e 64  ot multipart and
c190: 20 74 61 6b 65 20 74 68 65 20 66 61 73 74 20 70   take the fast p
c1a0: 61 74 68 20 28 61 6c 73 6f 3a 20 33 2e 31 20 77  ath (also: 3.1 w
c1b0: 6f 72 6b 61 72 6f 75 6e 64 29 0a 20 20 20 20 20  orkaround).     
c1c0: 20 20 20 69 66 20 6e 6f 74 20 73 65 6c 66 2e 63     if not self.c
c1d0: 6f 6e 74 65 6e 74 5f 74 79 70 65 2e 73 74 61 72  ontent_type.star
c1e0: 74 73 77 69 74 68 28 27 6d 75 6c 74 69 70 61 72  tswith('multipar
c1f0: 74 2f 27 29 3a 0a 20 20 20 20 20 20 20 20 20 20  t/'):.          
c200: 20 20 70 61 69 72 73 20 3d 20 5f 70 61 72 73 65    pairs = _parse
c210: 5f 71 73 6c 28 74 6f 6e 61 74 28 73 65 6c 66 2e  _qsl(tonat(self.
c220: 5f 67 65 74 5f 62 6f 64 79 5f 73 74 72 69 6e 67  _get_body_string
c230: 28 29 2c 20 27 6c 61 74 69 6e 31 27 29 29 0a 20  (), 'latin1')). 
c240: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 6b             for k
c250: 65 79 2c 20 76 61 6c 75 65 20 69 6e 20 70 61 69  ey, value in pai
c260: 72 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  rs:.            
c270: 20 20 20 20 70 6f 73 74 5b 6b 65 79 5d 20 3d 20      post[key] = 
c280: 76 61 6c 75 65 0a 20 20 20 20 20 20 20 20 20 20  value.          
c290: 20 20 72 65 74 75 72 6e 20 70 6f 73 74 0a 0a 20    return post.. 
c2a0: 20 20 20 20 20 20 20 73 61 66 65 5f 65 6e 76 20         safe_env 
c2b0: 3d 20 7b 27 51 55 45 52 59 5f 53 54 52 49 4e 47  = {'QUERY_STRING
c2c0: 27 3a 27 27 7d 20 23 20 42 75 69 6c 64 20 61 20  ':''} # Build a 
c2d0: 73 61 66 65 20 65 6e 76 69 72 6f 6e 6d 65 6e 74  safe environment
c2e0: 20 66 6f 72 20 63 67 69 0a 20 20 20 20 20 20 20   for cgi.       
c2f0: 20 66 6f 72 20 6b 65 79 20 69 6e 20 28 27 52 45   for key in ('RE
c300: 51 55 45 53 54 5f 4d 45 54 48 4f 44 27 2c 20 27  QUEST_METHOD', '
c310: 43 4f 4e 54 45 4e 54 5f 54 59 50 45 27 2c 20 27  CONTENT_TYPE', '
c320: 43 4f 4e 54 45 4e 54 5f 4c 45 4e 47 54 48 27 29  CONTENT_LENGTH')
c330: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
c340: 20 6b 65 79 20 69 6e 20 73 65 6c 66 2e 65 6e 76   key in self.env
c350: 69 72 6f 6e 3a 20 73 61 66 65 5f 65 6e 76 5b 6b  iron: safe_env[k
c360: 65 79 5d 20 3d 20 73 65 6c 66 2e 65 6e 76 69 72  ey] = self.envir
c370: 6f 6e 5b 6b 65 79 5d 0a 20 20 20 20 20 20 20 20  on[key].        
c380: 61 72 67 73 20 3d 20 64 69 63 74 28 66 70 3d 73  args = dict(fp=s
c390: 65 6c 66 2e 62 6f 64 79 2c 20 65 6e 76 69 72 6f  elf.body, enviro
c3a0: 6e 3d 73 61 66 65 5f 65 6e 76 2c 20 6b 65 65 70  n=safe_env, keep
c3b0: 5f 62 6c 61 6e 6b 5f 76 61 6c 75 65 73 3d 54 72  _blank_values=Tr
c3c0: 75 65 29 0a 20 20 20 20 20 20 20 20 69 66 20 70  ue).        if p
c3d0: 79 33 31 3a 0a 20 20 20 20 20 20 20 20 20 20 20  y31:.           
c3e0: 20 61 72 67 73 5b 27 66 70 27 5d 20 3d 20 4e 43   args['fp'] = NC
c3f0: 54 65 78 74 49 4f 57 72 61 70 70 65 72 28 61 72  TextIOWrapper(ar
c400: 67 73 5b 27 66 70 27 5d 2c 20 65 6e 63 6f 64 69  gs['fp'], encodi
c410: 6e 67 3d 27 75 74 66 38 27 2c 0a 20 20 20 20 20  ng='utf8',.     
c420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c440: 20 20 20 20 6e 65 77 6c 69 6e 65 3d 27 5c 6e 27      newline='\n'
c450: 29 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 70  ).        elif p
c460: 79 33 6b 3a 0a 20 20 20 20 20 20 20 20 20 20 20  y3k:.           
c470: 20 61 72 67 73 5b 27 65 6e 63 6f 64 69 6e 67 27   args['encoding'
c480: 5d 20 3d 20 27 75 74 66 38 27 0a 20 20 20 20 20  ] = 'utf8'.     
c490: 20 20 20 64 61 74 61 20 3d 20 63 67 69 2e 46 69     data = cgi.Fi
c4a0: 65 6c 64 53 74 6f 72 61 67 65 28 2a 2a 61 72 67  eldStorage(**arg
c4b0: 73 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 5b  s).        self[
c4c0: 27 5f 63 67 69 2e 46 69 65 6c 64 53 74 6f 72 61  '_cgi.FieldStora
c4d0: 67 65 27 5d 20 3d 20 64 61 74 61 20 23 68 74 74  ge'] = data #htt
c4e0: 70 3a 2f 2f 62 75 67 73 2e 70 79 74 68 6f 6e 2e  p://bugs.python.
c4f0: 6f 72 67 2f 69 73 73 75 65 31 38 33 39 34 23 6d  org/issue18394#m
c500: 73 67 32 30 37 39 35 38 0a 20 20 20 20 20 20 20  sg207958.       
c510: 20 64 61 74 61 20 3d 20 64 61 74 61 2e 6c 69 73   data = data.lis
c520: 74 20 6f 72 20 5b 5d 0a 20 20 20 20 20 20 20 20  t or [].        
c530: 66 6f 72 20 69 74 65 6d 20 69 6e 20 64 61 74 61  for item in data
c540: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
c550: 20 69 74 65 6d 2e 66 69 6c 65 6e 61 6d 65 3a 0a   item.filename:.
c560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c570: 70 6f 73 74 5b 69 74 65 6d 2e 6e 61 6d 65 5d 20  post[item.name] 
c580: 3d 20 46 69 6c 65 55 70 6c 6f 61 64 28 69 74 65  = FileUpload(ite
c590: 6d 2e 66 69 6c 65 2c 20 69 74 65 6d 2e 6e 61 6d  m.file, item.nam
c5a0: 65 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e,.             
c5b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c5c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c5d0: 69 74 65 6d 2e 66 69 6c 65 6e 61 6d 65 2c 20 69  item.filename, i
c5e0: 74 65 6d 2e 68 65 61 64 65 72 73 29 0a 20 20 20  tem.headers).   
c5f0: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
c600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
c610: 6f 73 74 5b 69 74 65 6d 2e 6e 61 6d 65 5d 20 3d  ost[item.name] =
c620: 20 69 74 65 6d 2e 76 61 6c 75 65 0a 20 20 20 20   item.value.    
c630: 20 20 20 20 72 65 74 75 72 6e 20 70 6f 73 74 0a      return post.
c640: 0a 20 20 20 20 40 70 72 6f 70 65 72 74 79 0a 20  .    @property. 
c650: 20 20 20 64 65 66 20 75 72 6c 28 73 65 6c 66 29     def url(self)
c660: 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20 54 68  :.        """ Th
c670: 65 20 66 75 6c 6c 20 72 65 71 75 65 73 74 20 55  e full request U
c680: 52 49 20 69 6e 63 6c 75 64 69 6e 67 20 68 6f 73  RI including hos
c690: 74 6e 61 6d 65 20 61 6e 64 20 73 63 68 65 6d 65  tname and scheme
c6a0: 2e 20 49 66 20 79 6f 75 72 20 61 70 70 0a 20 20  . If your app.  
c6b0: 20 20 20 20 20 20 20 20 20 20 6c 69 76 65 73 20            lives 
c6c0: 62 65 68 69 6e 64 20 61 20 72 65 76 65 72 73 65  behind a reverse
c6d0: 20 70 72 6f 78 79 20 6f 72 20 6c 6f 61 64 20 62   proxy or load b
c6e0: 61 6c 61 6e 63 65 72 20 61 6e 64 20 79 6f 75 20  alancer and you 
c6f0: 67 65 74 20 63 6f 6e 66 75 73 69 6e 67 0a 20 20  get confusing.  
c700: 20 20 20 20 20 20 20 20 20 20 72 65 73 75 6c 74            result
c710: 73 2c 20 6d 61 6b 65 20 73 75 72 65 20 74 68 61  s, make sure tha
c720: 74 20 74 68 65 20 60 60 58 2d 46 6f 72 77 61 72  t the ``X-Forwar
c730: 64 65 64 2d 48 6f 73 74 60 60 20 68 65 61 64 65  ded-Host`` heade
c740: 72 20 69 73 20 73 65 74 0a 20 20 20 20 20 20 20  r is set.       
c750: 20 20 20 20 20 63 6f 72 72 65 63 74 6c 79 2e 20       correctly. 
c760: 22 22 22 0a 20 20 20 20 20 20 20 20 72 65 74 75  """.        retu
c770: 72 6e 20 73 65 6c 66 2e 75 72 6c 70 61 72 74 73  rn self.urlparts
c780: 2e 67 65 74 75 72 6c 28 29 0a 0a 20 20 20 20 40  .geturl()..    @
c790: 44 69 63 74 50 72 6f 70 65 72 74 79 28 27 65 6e  DictProperty('en
c7a0: 76 69 72 6f 6e 27 2c 20 27 62 6f 74 74 6c 65 2e  viron', 'bottle.
c7b0: 72 65 71 75 65 73 74 2e 75 72 6c 70 61 72 74 73  request.urlparts
c7c0: 27 2c 20 72 65 61 64 5f 6f 6e 6c 79 3d 54 72 75  ', read_only=Tru
c7d0: 65 29 0a 20 20 20 20 64 65 66 20 75 72 6c 70 61  e).    def urlpa
c7e0: 72 74 73 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  rts(self):.     
c7f0: 20 20 20 27 27 27 20 54 68 65 20 3a 61 74 74 72     ''' The :attr
c800: 3a 60 75 72 6c 60 20 73 74 72 69 6e 67 20 61 73  :`url` string as
c810: 20 61 6e 20 3a 63 6c 61 73 73 3a 60 75 72 6c 70   an :class:`urlp
c820: 61 72 73 65 2e 53 70 6c 69 74 52 65 73 75 6c 74  arse.SplitResult
c830: 60 20 74 75 70 6c 65 2e 0a 20 20 20 20 20 20 20  ` tuple..       
c840: 20 20 20 20 20 54 68 65 20 74 75 70 6c 65 20 63       The tuple c
c850: 6f 6e 74 61 69 6e 73 20 28 73 63 68 65 6d 65 2c  ontains (scheme,
c860: 20 68 6f 73 74 2c 20 70 61 74 68 2c 20 71 75 65   host, path, que
c870: 72 79 5f 73 74 72 69 6e 67 20 61 6e 64 20 66 72  ry_string and fr
c880: 61 67 6d 65 6e 74 29 2c 0a 20 20 20 20 20 20 20  agment),.       
c890: 20 20 20 20 20 62 75 74 20 74 68 65 20 66 72 61       but the fra
c8a0: 67 6d 65 6e 74 20 69 73 20 61 6c 77 61 79 73 20  gment is always 
c8b0: 65 6d 70 74 79 20 62 65 63 61 75 73 65 20 69 74  empty because it
c8c0: 20 69 73 20 6e 6f 74 20 76 69 73 69 62 6c 65 20   is not visible 
c8d0: 74 6f 20 74 68 65 0a 20 20 20 20 20 20 20 20 20  to the.         
c8e0: 20 20 20 73 65 72 76 65 72 2e 20 27 27 27 0a 20     server. '''. 
c8f0: 20 20 20 20 20 20 20 65 6e 76 20 3d 20 73 65 6c         env = sel
c900: 66 2e 65 6e 76 69 72 6f 6e 0a 20 20 20 20 20 20  f.environ.      
c910: 20 20 68 74 74 70 20 3d 20 65 6e 76 2e 67 65 74    http = env.get
c920: 28 27 48 54 54 50 5f 58 5f 46 4f 52 57 41 52 44  ('HTTP_X_FORWARD
c930: 45 44 5f 50 52 4f 54 4f 27 29 20 6f 72 20 65 6e  ED_PROTO') or en
c940: 76 2e 67 65 74 28 27 77 73 67 69 2e 75 72 6c 5f  v.get('wsgi.url_
c950: 73 63 68 65 6d 65 27 2c 20 27 68 74 74 70 27 29  scheme', 'http')
c960: 0a 20 20 20 20 20 20 20 20 68 6f 73 74 20 3d 20  .        host = 
c970: 65 6e 76 2e 67 65 74 28 27 48 54 54 50 5f 58 5f  env.get('HTTP_X_
c980: 46 4f 52 57 41 52 44 45 44 5f 48 4f 53 54 27 29  FORWARDED_HOST')
c990: 20 6f 72 20 65 6e 76 2e 67 65 74 28 27 48 54 54   or env.get('HTT
c9a0: 50 5f 48 4f 53 54 27 29 0a 20 20 20 20 20 20 20  P_HOST').       
c9b0: 20 69 66 20 6e 6f 74 20 68 6f 73 74 3a 0a 20 20   if not host:.  
c9c0: 20 20 20 20 20 20 20 20 20 20 23 20 48 54 54 50            # HTTP
c9d0: 20 31 2e 31 20 72 65 71 75 69 72 65 73 20 61 20   1.1 requires a 
c9e0: 48 6f 73 74 2d 68 65 61 64 65 72 2e 20 54 68 69  Host-header. Thi
c9f0: 73 20 69 73 20 66 6f 72 20 48 54 54 50 2f 31 2e  s is for HTTP/1.
ca00: 30 20 63 6c 69 65 6e 74 73 2e 0a 20 20 20 20 20  0 clients..     
ca10: 20 20 20 20 20 20 20 68 6f 73 74 20 3d 20 65 6e         host = en
ca20: 76 2e 67 65 74 28 27 53 45 52 56 45 52 5f 4e 41  v.get('SERVER_NA
ca30: 4d 45 27 2c 20 27 31 32 37 2e 30 2e 30 2e 31 27  ME', '127.0.0.1'
ca40: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 6f  ).            po
ca50: 72 74 20 3d 20 65 6e 76 2e 67 65 74 28 27 53 45  rt = env.get('SE
ca60: 52 56 45 52 5f 50 4f 52 54 27 29 0a 20 20 20 20  RVER_PORT').    
ca70: 20 20 20 20 20 20 20 20 69 66 20 70 6f 72 74 20          if port 
ca80: 61 6e 64 20 70 6f 72 74 20 21 3d 20 28 27 38 30  and port != ('80
ca90: 27 20 69 66 20 68 74 74 70 20 3d 3d 20 27 68 74  ' if http == 'ht
caa0: 74 70 27 20 65 6c 73 65 20 27 34 34 33 27 29 3a  tp' else '443'):
cab0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
cac0: 20 68 6f 73 74 20 2b 3d 20 27 3a 27 20 2b 20 70   host += ':' + p
cad0: 6f 72 74 0a 20 20 20 20 20 20 20 20 70 61 74 68  ort.        path
cae0: 20 3d 20 75 72 6c 71 75 6f 74 65 28 73 65 6c 66   = urlquote(self
caf0: 2e 66 75 6c 6c 70 61 74 68 29 0a 20 20 20 20 20  .fullpath).     
cb00: 20 20 20 72 65 74 75 72 6e 20 55 72 6c 53 70 6c     return UrlSpl
cb10: 69 74 52 65 73 75 6c 74 28 68 74 74 70 2c 20 68  itResult(http, h
cb20: 6f 73 74 2c 20 70 61 74 68 2c 20 65 6e 76 2e 67  ost, path, env.g
cb30: 65 74 28 27 51 55 45 52 59 5f 53 54 52 49 4e 47  et('QUERY_STRING
cb40: 27 29 2c 20 27 27 29 0a 0a 20 20 20 20 40 70 72  '), '')..    @pr
cb50: 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20 66  operty.    def f
cb60: 75 6c 6c 70 61 74 68 28 73 65 6c 66 29 3a 0a 20  ullpath(self):. 
cb70: 20 20 20 20 20 20 20 22 22 22 20 52 65 71 75 65         """ Reque
cb80: 73 74 20 70 61 74 68 20 69 6e 63 6c 75 64 69 6e  st path includin
cb90: 67 20 3a 61 74 74 72 3a 60 73 63 72 69 70 74 5f  g :attr:`script_
cba0: 6e 61 6d 65 60 20 28 69 66 20 70 72 65 73 65 6e  name` (if presen
cbb0: 74 29 2e 20 22 22 22 0a 20 20 20 20 20 20 20 20  t). """.        
cbc0: 72 65 74 75 72 6e 20 75 72 6c 6a 6f 69 6e 28 73  return urljoin(s
cbd0: 65 6c 66 2e 73 63 72 69 70 74 5f 6e 61 6d 65 2c  elf.script_name,
cbe0: 20 73 65 6c 66 2e 70 61 74 68 2e 6c 73 74 72 69   self.path.lstri
cbf0: 70 28 27 2f 27 29 29 0a 0a 20 20 20 20 40 70 72  p('/'))..    @pr
cc00: 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20 71  operty.    def q
cc10: 75 65 72 79 5f 73 74 72 69 6e 67 28 73 65 6c 66  uery_string(self
cc20: 29 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20 54  ):.        """ T
cc30: 68 65 20 72 61 77 20 3a 61 74 74 72 3a 60 71 75  he raw :attr:`qu
cc40: 65 72 79 60 20 70 61 72 74 20 6f 66 20 74 68 65  ery` part of the
cc50: 20 55 52 4c 20 28 65 76 65 72 79 74 68 69 6e 67   URL (everything
cc60: 20 69 6e 20 62 65 74 77 65 65 6e 20 60 60 3f 60   in between ``?`
cc70: 60 0a 20 20 20 20 20 20 20 20 20 20 20 20 61 6e  `.            an
cc80: 64 20 60 60 23 60 60 29 20 61 73 20 61 20 73 74  d ``#``) as a st
cc90: 72 69 6e 67 2e 20 22 22 22 0a 20 20 20 20 20 20  ring. """.      
cca0: 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 65 6e    return self.en
ccb0: 76 69 72 6f 6e 2e 67 65 74 28 27 51 55 45 52 59  viron.get('QUERY
ccc0: 5f 53 54 52 49 4e 47 27 2c 20 27 27 29 0a 0a 20  _STRING', '').. 
ccd0: 20 20 20 40 70 72 6f 70 65 72 74 79 0a 20 20 20     @property.   
cce0: 20 64 65 66 20 73 63 72 69 70 74 5f 6e 61 6d 65   def script_name
ccf0: 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20  (self):.        
cd00: 27 27 27 20 54 68 65 20 69 6e 69 74 69 61 6c 20  ''' The initial 
cd10: 70 6f 72 74 69 6f 6e 20 6f 66 20 74 68 65 20 55  portion of the U
cd20: 52 4c 27 73 20 60 70 61 74 68 60 20 74 68 61 74  RL's `path` that
cd30: 20 77 61 73 20 72 65 6d 6f 76 65 64 20 62 79 20   was removed by 
cd40: 61 20 68 69 67 68 65 72 0a 20 20 20 20 20 20 20  a higher.       
cd50: 20 20 20 20 20 6c 65 76 65 6c 20 28 73 65 72 76       level (serv
cd60: 65 72 20 6f 72 20 72 6f 75 74 69 6e 67 20 6d 69  er or routing mi
cd70: 64 64 6c 65 77 61 72 65 29 20 62 65 66 6f 72 65  ddleware) before
cd80: 20 74 68 65 20 61 70 70 6c 69 63 61 74 69 6f 6e   the application
cd90: 20 77 61 73 0a 20 20 20 20 20 20 20 20 20 20 20   was.           
cda0: 20 63 61 6c 6c 65 64 2e 20 54 68 69 73 20 73 63   called. This sc
cdb0: 72 69 70 74 20 70 61 74 68 20 69 73 20 72 65 74  ript path is ret
cdc0: 75 72 6e 65 64 20 77 69 74 68 20 6c 65 61 64 69  urned with leadi
cdd0: 6e 67 20 61 6e 64 20 74 61 69 6c 69 6e 67 0a 20  ng and tailing. 
cde0: 20 20 20 20 20 20 20 20 20 20 20 73 6c 61 73 68             slash
cdf0: 65 73 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20  es. '''.        
ce00: 73 63 72 69 70 74 5f 6e 61 6d 65 20 3d 20 73 65  script_name = se
ce10: 6c 66 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27  lf.environ.get('
ce20: 53 43 52 49 50 54 5f 4e 41 4d 45 27 2c 20 27 27  SCRIPT_NAME', ''
ce30: 29 2e 73 74 72 69 70 28 27 2f 27 29 0a 20 20 20  ).strip('/').   
ce40: 20 20 20 20 20 72 65 74 75 72 6e 20 27 2f 27 20       return '/' 
ce50: 2b 20 73 63 72 69 70 74 5f 6e 61 6d 65 20 2b 20  + script_name + 
ce60: 27 2f 27 20 69 66 20 73 63 72 69 70 74 5f 6e 61  '/' if script_na
ce70: 6d 65 20 65 6c 73 65 20 27 2f 27 0a 0a 20 20 20  me else '/'..   
ce80: 20 64 65 66 20 70 61 74 68 5f 73 68 69 66 74 28   def path_shift(
ce90: 73 65 6c 66 2c 20 73 68 69 66 74 3d 31 29 3a 0a  self, shift=1):.
cea0: 20 20 20 20 20 20 20 20 27 27 27 20 53 68 69 66          ''' Shif
ceb0: 74 20 70 61 74 68 20 73 65 67 6d 65 6e 74 73 20  t path segments 
cec0: 66 72 6f 6d 20 3a 61 74 74 72 3a 60 70 61 74 68  from :attr:`path
ced0: 60 20 74 6f 20 3a 61 74 74 72 3a 60 73 63 72 69  ` to :attr:`scri
cee0: 70 74 5f 6e 61 6d 65 60 20 61 6e 64 0a 20 20 20  pt_name` and.   
cef0: 20 20 20 20 20 20 20 20 20 76 69 63 65 20 76 65           vice ve
cf00: 72 73 61 2e 0a 0a 20 20 20 20 20 20 20 20 20 20  rsa...          
cf10: 20 3a 70 61 72 61 6d 20 73 68 69 66 74 3a 20 54   :param shift: T
cf20: 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 70 61 74  he number of pat
cf30: 68 20 73 65 67 6d 65 6e 74 73 20 74 6f 20 73 68  h segments to sh
cf40: 69 66 74 2e 20 4d 61 79 20 62 65 20 6e 65 67 61  ift. May be nega
cf50: 74 69 76 65 0a 20 20 20 20 20 20 20 20 20 20 20  tive.           
cf60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 74 6f                to
cf70: 20 63 68 61 6e 67 65 20 74 68 65 20 73 68 69 66   change the shif
cf80: 74 20 64 69 72 65 63 74 69 6f 6e 2e 20 28 64 65  t direction. (de
cf90: 66 61 75 6c 74 3a 20 31 29 0a 20 20 20 20 20 20  fault: 1).      
cfa0: 20 20 27 27 27 0a 20 20 20 20 20 20 20 20 73 63    '''.        sc
cfb0: 72 69 70 74 20 3d 20 73 65 6c 66 2e 65 6e 76 69  ript = self.envi
cfc0: 72 6f 6e 2e 67 65 74 28 27 53 43 52 49 50 54 5f  ron.get('SCRIPT_
cfd0: 4e 41 4d 45 27 2c 27 2f 27 29 0a 20 20 20 20 20  NAME','/').     
cfe0: 20 20 20 73 65 6c 66 5b 27 53 43 52 49 50 54 5f     self['SCRIPT_
cff0: 4e 41 4d 45 27 5d 2c 20 73 65 6c 66 5b 27 50 41  NAME'], self['PA
d000: 54 48 5f 49 4e 46 4f 27 5d 20 3d 20 70 61 74 68  TH_INFO'] = path
d010: 5f 73 68 69 66 74 28 73 63 72 69 70 74 2c 20 73  _shift(script, s
d020: 65 6c 66 2e 70 61 74 68 2c 20 73 68 69 66 74 29  elf.path, shift)
d030: 0a 0a 20 20 20 20 40 70 72 6f 70 65 72 74 79 0a  ..    @property.
d040: 20 20 20 20 64 65 66 20 63 6f 6e 74 65 6e 74 5f      def content_
d050: 6c 65 6e 67 74 68 28 73 65 6c 66 29 3a 0a 20 20  length(self):.  
d060: 20 20 20 20 20 20 27 27 27 20 54 68 65 20 72 65        ''' The re
d070: 71 75 65 73 74 20 62 6f 64 79 20 6c 65 6e 67 74  quest body lengt
d080: 68 20 61 73 20 61 6e 20 69 6e 74 65 67 65 72 2e  h as an integer.
d090: 20 54 68 65 20 63 6c 69 65 6e 74 20 69 73 20 72   The client is r
d0a0: 65 73 70 6f 6e 73 69 62 6c 65 20 74 6f 0a 20 20  esponsible to.  
d0b0: 20 20 20 20 20 20 20 20 20 20 73 65 74 20 74 68            set th
d0c0: 69 73 20 68 65 61 64 65 72 2e 20 4f 74 68 65 72  is header. Other
d0d0: 77 69 73 65 2c 20 74 68 65 20 72 65 61 6c 20 6c  wise, the real l
d0e0: 65 6e 67 74 68 20 6f 66 20 74 68 65 20 62 6f 64  ength of the bod
d0f0: 79 20 69 73 20 75 6e 6b 6e 6f 77 6e 0a 20 20 20  y is unknown.   
d100: 20 20 20 20 20 20 20 20 20 61 6e 64 20 2d 31 20           and -1 
d110: 69 73 20 72 65 74 75 72 6e 65 64 2e 20 49 6e 20  is returned. In 
d120: 74 68 69 73 20 63 61 73 65 2c 20 3a 61 74 74 72  this case, :attr
d130: 3a 60 62 6f 64 79 60 20 77 69 6c 6c 20 62 65 20  :`body` will be 
d140: 65 6d 70 74 79 2e 20 27 27 27 0a 20 20 20 20 20  empty. '''.     
d150: 20 20 20 72 65 74 75 72 6e 20 69 6e 74 28 73 65     return int(se
d160: 6c 66 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27  lf.environ.get('
d170: 43 4f 4e 54 45 4e 54 5f 4c 45 4e 47 54 48 27 29  CONTENT_LENGTH')
d180: 20 6f 72 20 2d 31 29 0a 0a 20 20 20 20 40 70 72   or -1)..    @pr
d190: 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20 63  operty.    def c
d1a0: 6f 6e 74 65 6e 74 5f 74 79 70 65 28 73 65 6c 66  ontent_type(self
d1b0: 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 54  ):.        ''' T
d1c0: 68 65 20 43 6f 6e 74 65 6e 74 2d 54 79 70 65 20  he Content-Type 
d1d0: 68 65 61 64 65 72 20 61 73 20 61 20 6c 6f 77 65  header as a lowe
d1e0: 72 63 61 73 65 2d 73 74 72 69 6e 67 20 28 64 65  rcase-string (de
d1f0: 66 61 75 6c 74 3a 20 65 6d 70 74 79 29 2e 20 27  fault: empty). '
d200: 27 27 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ''.        retur
d210: 6e 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 2e 67  n self.environ.g
d220: 65 74 28 27 43 4f 4e 54 45 4e 54 5f 54 59 50 45  et('CONTENT_TYPE
d230: 27 2c 20 27 27 29 2e 6c 6f 77 65 72 28 29 0a 0a  ', '').lower()..
d240: 20 20 20 20 40 70 72 6f 70 65 72 74 79 0a 20 20      @property.  
d250: 20 20 64 65 66 20 69 73 5f 78 68 72 28 73 65 6c    def is_xhr(sel
d260: 66 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20  f):.        ''' 
d270: 54 72 75 65 20 69 66 20 74 68 65 20 72 65 71 75  True if the requ
d280: 65 73 74 20 77 61 73 20 74 72 69 67 67 65 72 65  est was triggere
d290: 64 20 62 79 20 61 20 58 4d 4c 48 74 74 70 52 65  d by a XMLHttpRe
d2a0: 71 75 65 73 74 2e 20 54 68 69 73 20 6f 6e 6c 79  quest. This only
d2b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 6f 72  .            wor
d2c0: 6b 73 20 77 69 74 68 20 4a 61 76 61 53 63 72 69  ks with JavaScri
d2d0: 70 74 20 6c 69 62 72 61 72 69 65 73 20 74 68 61  pt libraries tha
d2e0: 74 20 73 75 70 70 6f 72 74 20 74 68 65 20 60 58  t support the `X
d2f0: 2d 52 65 71 75 65 73 74 65 64 2d 57 69 74 68 60  -Requested-With`
d300: 0a 20 20 20 20 20 20 20 20 20 20 20 20 68 65 61  .            hea
d310: 64 65 72 20 28 6d 6f 73 74 20 6f 66 20 74 68 65  der (most of the
d320: 20 70 6f 70 75 6c 61 72 20 6c 69 62 72 61 72 69   popular librari
d330: 65 73 20 64 6f 29 2e 20 27 27 27 0a 20 20 20 20  es do). '''.    
d340: 20 20 20 20 72 65 71 75 65 73 74 65 64 5f 77 69      requested_wi
d350: 74 68 20 3d 20 73 65 6c 66 2e 65 6e 76 69 72 6f  th = self.enviro
d360: 6e 2e 67 65 74 28 27 48 54 54 50 5f 58 5f 52 45  n.get('HTTP_X_RE
d370: 51 55 45 53 54 45 44 5f 57 49 54 48 27 2c 27 27  QUESTED_WITH',''
d380: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
d390: 20 72 65 71 75 65 73 74 65 64 5f 77 69 74 68 2e   requested_with.
d3a0: 6c 6f 77 65 72 28 29 20 3d 3d 20 27 78 6d 6c 68  lower() == 'xmlh
d3b0: 74 74 70 72 65 71 75 65 73 74 27 0a 0a 20 20 20  ttprequest'..   
d3c0: 20 40 70 72 6f 70 65 72 74 79 0a 20 20 20 20 64   @property.    d
d3d0: 65 66 20 69 73 5f 61 6a 61 78 28 73 65 6c 66 29  ef is_ajax(self)
d3e0: 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 41 6c  :.        ''' Al
d3f0: 69 61 73 20 66 6f 72 20 3a 61 74 74 72 3a 60 69  ias for :attr:`i
d400: 73 5f 78 68 72 60 2e 20 22 41 6a 61 78 22 20 69  s_xhr`. "Ajax" i
d410: 73 20 6e 6f 74 20 74 68 65 20 72 69 67 68 74 20  s not the right 
d420: 74 65 72 6d 2e 20 27 27 27 0a 20 20 20 20 20 20  term. '''.      
d430: 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 69 73    return self.is
d440: 5f 78 68 72 0a 0a 20 20 20 20 40 70 72 6f 70 65  _xhr..    @prope
d450: 72 74 79 0a 20 20 20 20 64 65 66 20 61 75 74 68  rty.    def auth
d460: 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20  (self):.        
d470: 22 22 22 20 48 54 54 50 20 61 75 74 68 65 6e 74  """ HTTP authent
d480: 69 63 61 74 69 6f 6e 20 64 61 74 61 20 61 73 20  ication data as 
d490: 61 20 28 75 73 65 72 2c 20 70 61 73 73 77 6f 72  a (user, passwor
d4a0: 64 29 20 74 75 70 6c 65 2e 20 54 68 69 73 0a 20  d) tuple. This. 
d4b0: 20 20 20 20 20 20 20 20 20 20 20 69 6d 70 6c 65             imple
d4c0: 6d 65 6e 74 61 74 69 6f 6e 20 63 75 72 72 65 6e  mentation curren
d4d0: 74 6c 79 20 73 75 70 70 6f 72 74 73 20 62 61 73  tly supports bas
d4e0: 69 63 20 28 6e 6f 74 20 64 69 67 65 73 74 29 20  ic (not digest) 
d4f0: 61 75 74 68 65 6e 74 69 63 61 74 69 6f 6e 0a 20  authentication. 
d500: 20 20 20 20 20 20 20 20 20 20 20 6f 6e 6c 79 2e             only.
d510: 20 49 66 20 74 68 65 20 61 75 74 68 65 6e 74 69   If the authenti
d520: 63 61 74 69 6f 6e 20 68 61 70 70 65 6e 65 64 20  cation happened 
d530: 61 74 20 61 20 68 69 67 68 65 72 20 6c 65 76 65  at a higher leve
d540: 6c 20 28 65 2e 67 2e 20 69 6e 20 74 68 65 0a 20  l (e.g. in the. 
d550: 20 20 20 20 20 20 20 20 20 20 20 66 72 6f 6e 74             front
d560: 20 77 65 62 2d 73 65 72 76 65 72 20 6f 72 20 61   web-server or a
d570: 20 6d 69 64 64 6c 65 77 61 72 65 29 2c 20 74 68   middleware), th
d580: 65 20 70 61 73 73 77 6f 72 64 20 66 69 65 6c 64  e password field
d590: 20 69 73 20 4e 6f 6e 65 2c 20 62 75 74 0a 20 20   is None, but.  
d5a0: 20 20 20 20 20 20 20 20 20 20 74 68 65 20 75 73            the us
d5b0: 65 72 20 66 69 65 6c 64 20 69 73 20 6c 6f 6f 6b  er field is look
d5c0: 65 64 20 75 70 20 66 72 6f 6d 20 74 68 65 20 60  ed up from the `
d5d0: 60 52 45 4d 4f 54 45 5f 55 53 45 52 60 60 20 65  `REMOTE_USER`` e
d5e0: 6e 76 69 72 6f 6e 0a 20 20 20 20 20 20 20 20 20  nviron.         
d5f0: 20 20 20 76 61 72 69 61 62 6c 65 2e 20 4f 6e 20     variable. On 
d600: 61 6e 79 20 65 72 72 6f 72 73 2c 20 4e 6f 6e 65  any errors, None
d610: 20 69 73 20 72 65 74 75 72 6e 65 64 2e 20 22 22   is returned. ""
d620: 22 0a 20 20 20 20 20 20 20 20 62 61 73 69 63 20  ".        basic 
d630: 3d 20 70 61 72 73 65 5f 61 75 74 68 28 73 65 6c  = parse_auth(sel
d640: 66 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27 48  f.environ.get('H
d650: 54 54 50 5f 41 55 54 48 4f 52 49 5a 41 54 49 4f  TTP_AUTHORIZATIO
d660: 4e 27 2c 27 27 29 29 0a 20 20 20 20 20 20 20 20  N','')).        
d670: 69 66 20 62 61 73 69 63 3a 20 72 65 74 75 72 6e  if basic: return
d680: 20 62 61 73 69 63 0a 20 20 20 20 20 20 20 20 72   basic.        r
d690: 75 73 65 72 20 3d 20 73 65 6c 66 2e 65 6e 76 69  user = self.envi
d6a0: 72 6f 6e 2e 67 65 74 28 27 52 45 4d 4f 54 45 5f  ron.get('REMOTE_
d6b0: 55 53 45 52 27 29 0a 20 20 20 20 20 20 20 20 69  USER').        i
d6c0: 66 20 72 75 73 65 72 3a 20 72 65 74 75 72 6e 20  f ruser: return 
d6d0: 28 72 75 73 65 72 2c 20 4e 6f 6e 65 29 0a 20 20  (ruser, None).  
d6e0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e        return Non
d6f0: 65 0a 0a 20 20 20 20 40 70 72 6f 70 65 72 74 79  e..    @property
d700: 0a 20 20 20 20 64 65 66 20 72 65 6d 6f 74 65 5f  .    def remote_
d710: 72 6f 75 74 65 28 73 65 6c 66 29 3a 0a 20 20 20  route(self):.   
d720: 20 20 20 20 20 22 22 22 20 41 20 6c 69 73 74 20       """ A list 
d730: 6f 66 20 61 6c 6c 20 49 50 73 20 74 68 61 74 20  of all IPs that 
d740: 77 65 72 65 20 69 6e 76 6f 6c 76 65 64 20 69 6e  were involved in
d750: 20 74 68 69 73 20 72 65 71 75 65 73 74 2c 20 73   this request, s
d760: 74 61 72 74 69 6e 67 20 77 69 74 68 0a 20 20 20  tarting with.   
d770: 20 20 20 20 20 20 20 20 20 74 68 65 20 63 6c 69           the cli
d780: 65 6e 74 20 49 50 20 61 6e 64 20 66 6f 6c 6c 6f  ent IP and follo
d790: 77 65 64 20 62 79 20 7a 65 72 6f 20 6f 72 20 6d  wed by zero or m
d7a0: 6f 72 65 20 70 72 6f 78 69 65 73 2e 20 54 68 69  ore proxies. Thi
d7b0: 73 20 64 6f 65 73 20 6f 6e 6c 79 0a 20 20 20 20  s does only.    
d7c0: 20 20 20 20 20 20 20 20 77 6f 72 6b 20 69 66 20          work if 
d7d0: 61 6c 6c 20 70 72 6f 78 69 65 73 20 73 75 70 70  all proxies supp
d7e0: 6f 72 74 20 74 68 65 20 60 60 60 58 2d 46 6f 72  ort the ```X-For
d7f0: 77 61 72 64 65 64 2d 46 6f 72 60 60 20 68 65 61  warded-For`` hea
d800: 64 65 72 2e 20 4e 6f 74 65 0a 20 20 20 20 20 20  der. Note.      
d810: 20 20 20 20 20 20 74 68 61 74 20 74 68 69 73 20        that this 
d820: 69 6e 66 6f 72 6d 61 74 69 6f 6e 20 63 61 6e 20  information can 
d830: 62 65 20 66 6f 72 67 65 64 20 62 79 20 6d 61 6c  be forged by mal
d840: 69 63 69 6f 75 73 20 63 6c 69 65 6e 74 73 2e 20  icious clients. 
d850: 22 22 22 0a 20 20 20 20 20 20 20 20 70 72 6f 78  """.        prox
d860: 79 20 3d 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e  y = self.environ
d870: 2e 67 65 74 28 27 48 54 54 50 5f 58 5f 46 4f 52  .get('HTTP_X_FOR
d880: 57 41 52 44 45 44 5f 46 4f 52 27 29 0a 20 20 20  WARDED_FOR').   
d890: 20 20 20 20 20 69 66 20 70 72 6f 78 79 3a 20 72       if proxy: r
d8a0: 65 74 75 72 6e 20 5b 69 70 2e 73 74 72 69 70 28  eturn [ip.strip(
d8b0: 29 20 66 6f 72 20 69 70 20 69 6e 20 70 72 6f 78  ) for ip in prox
d8c0: 79 2e 73 70 6c 69 74 28 27 2c 27 29 5d 0a 20 20  y.split(',')].  
d8d0: 20 20 20 20 20 20 72 65 6d 6f 74 65 20 3d 20 73        remote = s
d8e0: 65 6c 66 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28  elf.environ.get(
d8f0: 27 52 45 4d 4f 54 45 5f 41 44 44 52 27 29 0a 20  'REMOTE_ADDR'). 
d900: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 72         return [r
d910: 65 6d 6f 74 65 5d 20 69 66 20 72 65 6d 6f 74 65  emote] if remote
d920: 20 65 6c 73 65 20 5b 5d 0a 0a 20 20 20 20 40 70   else []..    @p
d930: 72 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20  roperty.    def 
d940: 72 65 6d 6f 74 65 5f 61 64 64 72 28 73 65 6c 66  remote_addr(self
d950: 29 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20 54  ):.        """ T
d960: 68 65 20 63 6c 69 65 6e 74 20 49 50 20 61 73 20  he client IP as 
d970: 61 20 73 74 72 69 6e 67 2e 20 4e 6f 74 65 20 74  a string. Note t
d980: 68 61 74 20 74 68 69 73 20 69 6e 66 6f 72 6d 61  hat this informa
d990: 74 69 6f 6e 20 63 61 6e 20 62 65 20 66 6f 72 67  tion can be forg
d9a0: 65 64 0a 20 20 20 20 20 20 20 20 20 20 20 20 62  ed.            b
d9b0: 79 20 6d 61 6c 69 63 69 6f 75 73 20 63 6c 69 65  y malicious clie
d9c0: 6e 74 73 2e 20 22 22 22 0a 20 20 20 20 20 20 20  nts. """.       
d9d0: 20 72 6f 75 74 65 20 3d 20 73 65 6c 66 2e 72 65   route = self.re
d9e0: 6d 6f 74 65 5f 72 6f 75 74 65 0a 20 20 20 20 20  mote_route.     
d9f0: 20 20 20 72 65 74 75 72 6e 20 72 6f 75 74 65 5b     return route[
da00: 30 5d 20 69 66 20 72 6f 75 74 65 20 65 6c 73 65  0] if route else
da10: 20 4e 6f 6e 65 0a 0a 20 20 20 20 64 65 66 20 63   None..    def c
da20: 6f 70 79 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  opy(self):.     
da30: 20 20 20 22 22 22 20 52 65 74 75 72 6e 20 61 20     """ Return a 
da40: 6e 65 77 20 3a 63 6c 61 73 73 3a 60 52 65 71 75  new :class:`Requ
da50: 65 73 74 60 20 77 69 74 68 20 61 20 73 68 61 6c  est` with a shal
da60: 6c 6f 77 20 3a 61 74 74 72 3a 60 65 6e 76 69 72  low :attr:`envir
da70: 6f 6e 60 20 63 6f 70 79 2e 20 22 22 22 0a 20 20  on` copy. """.  
da80: 20 20 20 20 20 20 72 65 74 75 72 6e 20 52 65 71        return Req
da90: 75 65 73 74 28 73 65 6c 66 2e 65 6e 76 69 72 6f  uest(self.enviro
daa0: 6e 2e 63 6f 70 79 28 29 29 0a 0a 20 20 20 20 64  n.copy())..    d
dab0: 65 66 20 67 65 74 28 73 65 6c 66 2c 20 76 61 6c  ef get(self, val
dac0: 75 65 2c 20 64 65 66 61 75 6c 74 3d 4e 6f 6e 65  ue, default=None
dad0: 29 3a 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 65  ): return self.e
dae0: 6e 76 69 72 6f 6e 2e 67 65 74 28 76 61 6c 75 65  nviron.get(value
daf0: 2c 20 64 65 66 61 75 6c 74 29 0a 20 20 20 20 64  , default).    d
db00: 65 66 20 5f 5f 67 65 74 69 74 65 6d 5f 5f 28 73  ef __getitem__(s
db10: 65 6c 66 2c 20 6b 65 79 29 3a 20 72 65 74 75 72  elf, key): retur
db20: 6e 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 5b 6b  n self.environ[k
db30: 65 79 5d 0a 20 20 20 20 64 65 66 20 5f 5f 64 65  ey].    def __de
db40: 6c 69 74 65 6d 5f 5f 28 73 65 6c 66 2c 20 6b 65  litem__(self, ke
db50: 79 29 3a 20 73 65 6c 66 5b 6b 65 79 5d 20 3d 20  y): self[key] = 
db60: 22 22 3b 20 64 65 6c 28 73 65 6c 66 2e 65 6e 76  ""; del(self.env
db70: 69 72 6f 6e 5b 6b 65 79 5d 29 0a 20 20 20 20 64  iron[key]).    d
db80: 65 66 20 5f 5f 69 74 65 72 5f 5f 28 73 65 6c 66  ef __iter__(self
db90: 29 3a 20 72 65 74 75 72 6e 20 69 74 65 72 28 73  ): return iter(s
dba0: 65 6c 66 2e 65 6e 76 69 72 6f 6e 29 0a 20 20 20  elf.environ).   
dbb0: 20 64 65 66 20 5f 5f 6c 65 6e 5f 5f 28 73 65 6c   def __len__(sel
dbc0: 66 29 3a 20 72 65 74 75 72 6e 20 6c 65 6e 28 73  f): return len(s
dbd0: 65 6c 66 2e 65 6e 76 69 72 6f 6e 29 0a 20 20 20  elf.environ).   
dbe0: 20 64 65 66 20 6b 65 79 73 28 73 65 6c 66 29 3a   def keys(self):
dbf0: 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 65 6e 76   return self.env
dc00: 69 72 6f 6e 2e 6b 65 79 73 28 29 0a 20 20 20 20  iron.keys().    
dc10: 64 65 66 20 5f 5f 73 65 74 69 74 65 6d 5f 5f 28  def __setitem__(
dc20: 73 65 6c 66 2c 20 6b 65 79 2c 20 76 61 6c 75 65  self, key, value
dc30: 29 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20 43  ):.        """ C
dc40: 68 61 6e 67 65 20 61 6e 20 65 6e 76 69 72 6f 6e  hange an environ
dc50: 20 76 61 6c 75 65 20 61 6e 64 20 63 6c 65 61 72   value and clear
dc60: 20 61 6c 6c 20 63 61 63 68 65 73 20 74 68 61 74   all caches that
dc70: 20 64 65 70 65 6e 64 20 6f 6e 20 69 74 2e 20 22   depend on it. "
dc80: 22 22 0a 0a 20 20 20 20 20 20 20 20 69 66 20 73  ""..        if s
dc90: 65 6c 66 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28  elf.environ.get(
dca0: 27 62 6f 74 74 6c 65 2e 72 65 71 75 65 73 74 2e  'bottle.request.
dcb0: 72 65 61 64 6f 6e 6c 79 27 29 3a 0a 20 20 20 20  readonly'):.    
dcc0: 20 20 20 20 20 20 20 20 72 61 69 73 65 20 4b 65          raise Ke
dcd0: 79 45 72 72 6f 72 28 27 54 68 65 20 65 6e 76 69  yError('The envi
dce0: 72 6f 6e 20 64 69 63 74 69 6f 6e 61 72 79 20 69  ron dictionary i
dcf0: 73 20 72 65 61 64 2d 6f 6e 6c 79 2e 27 29 0a 0a  s read-only.')..
dd00: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 65 6e 76          self.env
dd10: 69 72 6f 6e 5b 6b 65 79 5d 20 3d 20 76 61 6c 75  iron[key] = valu
dd20: 65 0a 20 20 20 20 20 20 20 20 74 6f 64 65 6c 65  e.        todele
dd30: 74 65 20 3d 20 28 29 0a 0a 20 20 20 20 20 20 20  te = ()..       
dd40: 20 69 66 20 6b 65 79 20 3d 3d 20 27 77 73 67 69   if key == 'wsgi
dd50: 2e 69 6e 70 75 74 27 3a 0a 20 20 20 20 20 20 20  .input':.       
dd60: 20 20 20 20 20 74 6f 64 65 6c 65 74 65 20 3d 20       todelete = 
dd70: 28 27 62 6f 64 79 27 2c 20 27 66 6f 72 6d 73 27  ('body', 'forms'
dd80: 2c 20 27 66 69 6c 65 73 27 2c 20 27 70 61 72 61  , 'files', 'para
dd90: 6d 73 27 2c 20 27 70 6f 73 74 27 2c 20 27 6a 73  ms', 'post', 'js
dda0: 6f 6e 27 29 0a 20 20 20 20 20 20 20 20 65 6c 69  on').        eli
ddb0: 66 20 6b 65 79 20 3d 3d 20 27 51 55 45 52 59 5f  f key == 'QUERY_
ddc0: 53 54 52 49 4e 47 27 3a 0a 20 20 20 20 20 20 20  STRING':.       
ddd0: 20 20 20 20 20 74 6f 64 65 6c 65 74 65 20 3d 20       todelete = 
dde0: 28 27 71 75 65 72 79 27 2c 20 27 70 61 72 61 6d  ('query', 'param
ddf0: 73 27 29 0a 20 20 20 20 20 20 20 20 65 6c 69 66  s').        elif
de00: 20 6b 65 79 2e 73 74 61 72 74 73 77 69 74 68 28   key.startswith(
de10: 27 48 54 54 50 5f 27 29 3a 0a 20 20 20 20 20 20  'HTTP_'):.      
de20: 20 20 20 20 20 20 74 6f 64 65 6c 65 74 65 20 3d        todelete =
de30: 20 28 27 68 65 61 64 65 72 73 27 2c 20 27 63 6f   ('headers', 'co
de40: 6f 6b 69 65 73 27 29 0a 0a 20 20 20 20 20 20 20  okies')..       
de50: 20 66 6f 72 20 6b 65 79 20 69 6e 20 74 6f 64 65   for key in tode
de60: 6c 65 74 65 3a 0a 20 20 20 20 20 20 20 20 20 20  lete:.          
de70: 20 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 2e 70    self.environ.p
de80: 6f 70 28 27 62 6f 74 74 6c 65 2e 72 65 71 75 65  op('bottle.reque
de90: 73 74 2e 27 2b 6b 65 79 2c 20 4e 6f 6e 65 29 0a  st.'+key, None).
dea0: 0a 20 20 20 20 64 65 66 20 5f 5f 72 65 70 72 5f  .    def __repr_
deb0: 5f 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20  _(self):.       
dec0: 20 72 65 74 75 72 6e 20 27 3c 25 73 3a 20 25 73   return '<%s: %s
ded0: 20 25 73 3e 27 20 25 20 28 73 65 6c 66 2e 5f 5f   %s>' % (self.__
dee0: 63 6c 61 73 73 5f 5f 2e 5f 5f 6e 61 6d 65 5f 5f  class__.__name__
def0: 2c 20 73 65 6c 66 2e 6d 65 74 68 6f 64 2c 20 73  , self.method, s
df00: 65 6c 66 2e 75 72 6c 29 0a 0a 20 20 20 20 64 65  elf.url)..    de
df10: 66 20 5f 5f 67 65 74 61 74 74 72 5f 5f 28 73 65  f __getattr__(se
df20: 6c 66 2c 20 6e 61 6d 65 29 3a 0a 20 20 20 20 20  lf, name):.     
df30: 20 20 20 27 27 27 20 53 65 61 72 63 68 20 69 6e     ''' Search in
df40: 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 20 66 6f   self.environ fo
df50: 72 20 61 64 64 69 74 69 6f 6e 61 6c 20 75 73 65  r additional use
df60: 72 20 64 65 66 69 6e 65 64 20 61 74 74 72 69 62  r defined attrib
df70: 75 74 65 73 2e 20 27 27 27 0a 20 20 20 20 20 20  utes. '''.      
df80: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20    try:.         
df90: 20 20 20 76 61 72 20 3d 20 73 65 6c 66 2e 65 6e     var = self.en
dfa0: 76 69 72 6f 6e 5b 27 62 6f 74 74 6c 65 2e 72 65  viron['bottle.re
dfb0: 71 75 65 73 74 2e 65 78 74 2e 25 73 27 25 6e 61  quest.ext.%s'%na
dfc0: 6d 65 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  me].            
dfd0: 72 65 74 75 72 6e 20 76 61 72 2e 5f 5f 67 65 74  return var.__get
dfe0: 5f 5f 28 73 65 6c 66 29 20 69 66 20 68 61 73 61  __(self) if hasa
dff0: 74 74 72 28 76 61 72 2c 20 27 5f 5f 67 65 74 5f  ttr(var, '__get_
e000: 5f 27 29 20 65 6c 73 65 20 76 61 72 0a 20 20 20  _') else var.   
e010: 20 20 20 20 20 65 78 63 65 70 74 20 4b 65 79 45       except KeyE
e020: 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20  rror:.          
e030: 20 20 72 61 69 73 65 20 41 74 74 72 69 62 75 74    raise Attribut
e040: 65 45 72 72 6f 72 28 27 41 74 74 72 69 62 75 74  eError('Attribut
e050: 65 20 25 72 20 6e 6f 74 20 64 65 66 69 6e 65 64  e %r not defined
e060: 2e 27 20 25 20 6e 61 6d 65 29 0a 0a 20 20 20 20  .' % name)..    
e070: 64 65 66 20 5f 5f 73 65 74 61 74 74 72 5f 5f 28  def __setattr__(
e080: 73 65 6c 66 2c 20 6e 61 6d 65 2c 20 76 61 6c 75  self, name, valu
e090: 65 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6e  e):.        if n
e0a0: 61 6d 65 20 3d 3d 20 27 65 6e 76 69 72 6f 6e 27  ame == 'environ'
e0b0: 3a 20 72 65 74 75 72 6e 20 6f 62 6a 65 63 74 2e  : return object.
e0c0: 5f 5f 73 65 74 61 74 74 72 5f 5f 28 73 65 6c 66  __setattr__(self
e0d0: 2c 20 6e 61 6d 65 2c 20 76 61 6c 75 65 29 0a 20  , name, value). 
e0e0: 20 20 20 20 20 20 20 73 65 6c 66 2e 65 6e 76 69         self.envi
e0f0: 72 6f 6e 5b 27 62 6f 74 74 6c 65 2e 72 65 71 75  ron['bottle.requ
e100: 65 73 74 2e 65 78 74 2e 25 73 27 25 6e 61 6d 65  est.ext.%s'%name
e110: 5d 20 3d 20 76 61 6c 75 65 0a 0a 0a 64 65 66 20  ] = value...def 
e120: 5f 68 6b 65 79 28 6b 65 79 29 3a 0a 20 20 20 20  _hkey(key):.    
e130: 69 66 20 27 5c 6e 27 20 69 6e 20 6b 65 79 20 6f  if '\n' in key o
e140: 72 20 27 5c 72 27 20 69 6e 20 6b 65 79 20 6f 72  r '\r' in key or
e150: 20 27 5c 30 27 20 69 6e 20 6b 65 79 3a 0a 20 20   '\0' in key:.  
e160: 20 20 20 20 20 20 72 61 69 73 65 20 56 61 6c 75        raise Valu
e170: 65 45 72 72 6f 72 28 22 48 65 61 64 65 72 20 6e  eError("Header n
e180: 61 6d 65 73 20 6d 75 73 74 20 6e 6f 74 20 63 6f  ames must not co
e190: 6e 74 61 69 6e 20 63 6f 6e 74 72 6f 6c 20 63 68  ntain control ch
e1a0: 61 72 61 63 74 65 72 73 3a 20 25 72 22 20 25 20  aracters: %r" % 
e1b0: 6b 65 79 29 0a 20 20 20 20 72 65 74 75 72 6e 20  key).    return 
e1c0: 6b 65 79 2e 74 69 74 6c 65 28 29 2e 72 65 70 6c  key.title().repl
e1d0: 61 63 65 28 27 5f 27 2c 20 27 2d 27 29 0a 0a 0a  ace('_', '-')...
e1e0: 64 65 66 20 5f 68 76 61 6c 28 76 61 6c 75 65 29  def _hval(value)
e1f0: 3a 0a 20 20 20 20 76 61 6c 75 65 20 3d 20 74 6f  :.    value = to
e200: 6e 61 74 28 76 61 6c 75 65 29 0a 20 20 20 20 69  nat(value).    i
e210: 66 20 27 5c 6e 27 20 69 6e 20 76 61 6c 75 65 20  f '\n' in value 
e220: 6f 72 20 27 5c 72 27 20 69 6e 20 76 61 6c 75 65  or '\r' in value
e230: 20 6f 72 20 27 5c 30 27 20 69 6e 20 76 61 6c 75   or '\0' in valu
e240: 65 3a 0a 20 20 20 20 20 20 20 20 72 61 69 73 65  e:.        raise
e250: 20 56 61 6c 75 65 45 72 72 6f 72 28 22 48 65 61   ValueError("Hea
e260: 64 65 72 20 76 61 6c 75 65 20 6d 75 73 74 20 6e  der value must n
e270: 6f 74 20 63 6f 6e 74 61 69 6e 20 63 6f 6e 74 72  ot contain contr
e280: 6f 6c 20 63 68 61 72 61 63 74 65 72 73 3a 20 25  ol characters: %
e290: 72 22 20 25 20 76 61 6c 75 65 29 0a 20 20 20 20  r" % value).    
e2a0: 72 65 74 75 72 6e 20 76 61 6c 75 65 0a 0a 0a 0a  return value....
e2b0: 63 6c 61 73 73 20 48 65 61 64 65 72 50 72 6f 70  class HeaderProp
e2c0: 65 72 74 79 28 6f 62 6a 65 63 74 29 3a 0a 20 20  erty(object):.  
e2d0: 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 28 73    def __init__(s
e2e0: 65 6c 66 2c 20 6e 61 6d 65 2c 20 72 65 61 64 65  elf, name, reade
e2f0: 72 3d 4e 6f 6e 65 2c 20 77 72 69 74 65 72 3d 4e  r=None, writer=N
e300: 6f 6e 65 2c 20 64 65 66 61 75 6c 74 3d 27 27 29  one, default='')
e310: 3a 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e  :.        self.n
e320: 61 6d 65 2c 20 73 65 6c 66 2e 64 65 66 61 75 6c  ame, self.defaul
e330: 74 20 3d 20 6e 61 6d 65 2c 20 64 65 66 61 75 6c  t = name, defaul
e340: 74 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 72  t.        self.r
e350: 65 61 64 65 72 2c 20 73 65 6c 66 2e 77 72 69 74  eader, self.writ
e360: 65 72 20 3d 20 72 65 61 64 65 72 2c 20 77 72 69  er = reader, wri
e370: 74 65 72 0a 20 20 20 20 20 20 20 20 73 65 6c 66  ter.        self
e380: 2e 5f 5f 64 6f 63 5f 5f 20 3d 20 27 43 75 72 72  .__doc__ = 'Curr
e390: 65 6e 74 20 76 61 6c 75 65 20 6f 66 20 74 68 65  ent value of the
e3a0: 20 25 72 20 68 65 61 64 65 72 2e 27 20 25 20 6e   %r header.' % n
e3b0: 61 6d 65 2e 74 69 74 6c 65 28 29 0a 0a 20 20 20  ame.title()..   
e3c0: 20 64 65 66 20 5f 5f 67 65 74 5f 5f 28 73 65 6c   def __get__(sel
e3d0: 66 2c 20 6f 62 6a 2c 20 63 6c 73 29 3a 0a 20 20  f, obj, cls):.  
e3e0: 20 20 20 20 20 20 69 66 20 6f 62 6a 20 69 73 20        if obj is 
e3f0: 4e 6f 6e 65 3a 20 72 65 74 75 72 6e 20 73 65 6c  None: return sel
e400: 66 0a 20 20 20 20 20 20 20 20 76 61 6c 75 65 20  f.        value 
e410: 3d 20 6f 62 6a 2e 67 65 74 5f 68 65 61 64 65 72  = obj.get_header
e420: 28 73 65 6c 66 2e 6e 61 6d 65 2c 20 73 65 6c 66  (self.name, self
e430: 2e 64 65 66 61 75 6c 74 29 0a 20 20 20 20 20 20  .default).      
e440: 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 72 65    return self.re
e450: 61 64 65 72 28 76 61 6c 75 65 29 20 69 66 20 73  ader(value) if s
e460: 65 6c 66 2e 72 65 61 64 65 72 20 65 6c 73 65 20  elf.reader else 
e470: 76 61 6c 75 65 0a 0a 20 20 20 20 64 65 66 20 5f  value..    def _
e480: 5f 73 65 74 5f 5f 28 73 65 6c 66 2c 20 6f 62 6a  _set__(self, obj
e490: 2c 20 76 61 6c 75 65 29 3a 0a 20 20 20 20 20 20  , value):.      
e4a0: 20 20 6f 62 6a 5b 73 65 6c 66 2e 6e 61 6d 65 5d    obj[self.name]
e4b0: 20 3d 20 73 65 6c 66 2e 77 72 69 74 65 72 28 76   = self.writer(v
e4c0: 61 6c 75 65 29 20 69 66 20 73 65 6c 66 2e 77 72  alue) if self.wr
e4d0: 69 74 65 72 20 65 6c 73 65 20 76 61 6c 75 65 0a  iter else value.
e4e0: 0a 20 20 20 20 64 65 66 20 5f 5f 64 65 6c 65 74  .    def __delet
e4f0: 65 5f 5f 28 73 65 6c 66 2c 20 6f 62 6a 29 3a 0a  e__(self, obj):.
e500: 20 20 20 20 20 20 20 20 64 65 6c 20 6f 62 6a 5b          del obj[
e510: 73 65 6c 66 2e 6e 61 6d 65 5d 0a 0a 0a 63 6c 61  self.name]...cla
e520: 73 73 20 42 61 73 65 52 65 73 70 6f 6e 73 65 28  ss BaseResponse(
e530: 6f 62 6a 65 63 74 29 3a 0a 20 20 20 20 22 22 22  object):.    """
e540: 20 53 74 6f 72 61 67 65 20 63 6c 61 73 73 20 66   Storage class f
e550: 6f 72 20 61 20 72 65 73 70 6f 6e 73 65 20 62 6f  or a response bo
e560: 64 79 20 61 73 20 77 65 6c 6c 20 61 73 20 68 65  dy as well as he
e570: 61 64 65 72 73 20 61 6e 64 20 63 6f 6f 6b 69 65  aders and cookie
e580: 73 2e 0a 0a 20 20 20 20 20 20 20 20 54 68 69 73  s...        This
e590: 20 63 6c 61 73 73 20 64 6f 65 73 20 73 75 70 70   class does supp
e5a0: 6f 72 74 20 64 69 63 74 2d 6c 69 6b 65 20 63 61  ort dict-like ca
e5b0: 73 65 2d 69 6e 73 65 6e 73 69 74 69 76 65 20 69  se-insensitive i
e5c0: 74 65 6d 2d 61 63 63 65 73 73 20 74 6f 0a 20 20  tem-access to.  
e5d0: 20 20 20 20 20 20 68 65 61 64 65 72 73 2c 20 62        headers, b
e5e0: 75 74 20 69 73 20 4e 4f 54 20 61 20 64 69 63 74  ut is NOT a dict
e5f0: 2e 20 4d 6f 73 74 20 6e 6f 74 61 62 6c 79 2c 20  . Most notably, 
e600: 69 74 65 72 61 74 69 6e 67 20 6f 76 65 72 20 61  iterating over a
e610: 20 72 65 73 70 6f 6e 73 65 0a 20 20 20 20 20 20   response.      
e620: 20 20 79 69 65 6c 64 73 20 70 61 72 74 73 20 6f    yields parts o
e630: 66 20 74 68 65 20 62 6f 64 79 20 61 6e 64 20 6e  f the body and n
e640: 6f 74 20 74 68 65 20 68 65 61 64 65 72 73 2e 0a  ot the headers..
e650: 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20  .        :param 
e660: 62 6f 64 79 3a 20 54 68 65 20 72 65 73 70 6f 6e  body: The respon
e670: 73 65 20 62 6f 64 79 20 61 73 20 6f 6e 65 20 6f  se body as one o
e680: 66 20 74 68 65 20 73 75 70 70 6f 72 74 65 64 20  f the supported 
e690: 74 79 70 65 73 2e 0a 20 20 20 20 20 20 20 20 3a  types..        :
e6a0: 70 61 72 61 6d 20 73 74 61 74 75 73 3a 20 45 69  param status: Ei
e6b0: 74 68 65 72 20 61 6e 20 48 54 54 50 20 73 74 61  ther an HTTP sta
e6c0: 74 75 73 20 63 6f 64 65 20 28 65 2e 67 2e 20 32  tus code (e.g. 2
e6d0: 30 30 29 20 6f 72 20 61 20 73 74 61 74 75 73 20  00) or a status 
e6e0: 6c 69 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20  line.           
e6f0: 20 20 20 20 20 20 20 20 20 20 20 20 69 6e 63 6c              incl
e700: 75 64 69 6e 67 20 74 68 65 20 72 65 61 73 6f 6e  uding the reason
e710: 20 70 68 72 61 73 65 20 28 65 2e 67 2e 20 27 32   phrase (e.g. '2
e720: 30 30 20 4f 4b 27 29 2e 0a 20 20 20 20 20 20 20  00 OK')..       
e730: 20 3a 70 61 72 61 6d 20 68 65 61 64 65 72 73 3a   :param headers:
e740: 20 41 20 64 69 63 74 69 6f 6e 61 72 79 20 6f 72   A dictionary or
e750: 20 61 20 6c 69 73 74 20 6f 66 20 6e 61 6d 65 2d   a list of name-
e760: 76 61 6c 75 65 20 70 61 69 72 73 2e 0a 0a 20 20  value pairs...  
e770: 20 20 20 20 20 20 41 64 64 69 74 69 6f 6e 61 6c        Additional
e780: 20 6b 65 79 77 6f 72 64 20 61 72 67 75 6d 65 6e   keyword argumen
e790: 74 73 20 61 72 65 20 61 64 64 65 64 20 74 6f 20  ts are added to 
e7a0: 74 68 65 20 6c 69 73 74 20 6f 66 20 68 65 61 64  the list of head
e7b0: 65 72 73 2e 0a 20 20 20 20 20 20 20 20 55 6e 64  ers..        Und
e7c0: 65 72 73 63 6f 72 65 73 20 69 6e 20 74 68 65 20  erscores in the 
e7d0: 68 65 61 64 65 72 20 6e 61 6d 65 20 61 72 65 20  header name are 
e7e0: 72 65 70 6c 61 63 65 64 20 77 69 74 68 20 64 61  replaced with da
e7f0: 73 68 65 73 2e 0a 20 20 20 20 22 22 22 0a 0a 20  shes..    """.. 
e800: 20 20 20 64 65 66 61 75 6c 74 5f 73 74 61 74 75     default_statu
e810: 73 20 3d 20 32 30 30 0a 20 20 20 20 64 65 66 61  s = 200.    defa
e820: 75 6c 74 5f 63 6f 6e 74 65 6e 74 5f 74 79 70 65  ult_content_type
e830: 20 3d 20 27 74 65 78 74 2f 68 74 6d 6c 3b 20 63   = 'text/html; c
e840: 68 61 72 73 65 74 3d 55 54 46 2d 38 27 0a 0a 20  harset=UTF-8'.. 
e850: 20 20 20 23 20 48 65 61 64 65 72 20 62 6c 61 63     # Header blac
e860: 6b 6c 69 73 74 20 66 6f 72 20 73 70 65 63 69 66  klist for specif
e870: 69 63 20 72 65 73 70 6f 6e 73 65 20 63 6f 64 65  ic response code
e880: 73 0a 20 20 20 20 23 20 28 72 66 63 32 36 31 36  s.    # (rfc2616
e890: 20 73 65 63 74 69 6f 6e 20 31 30 2e 32 2e 33 20   section 10.2.3 
e8a0: 61 6e 64 20 31 30 2e 33 2e 35 29 0a 20 20 20 20  and 10.3.5).    
e8b0: 62 61 64 5f 68 65 61 64 65 72 73 20 3d 20 7b 0a  bad_headers = {.
e8c0: 20 20 20 20 20 20 20 20 32 30 34 3a 20 73 65 74          204: set
e8d0: 28 28 27 43 6f 6e 74 65 6e 74 2d 54 79 70 65 27  (('Content-Type'
e8e0: 2c 29 29 2c 0a 20 20 20 20 20 20 20 20 33 30 34  ,)),.        304
e8f0: 3a 20 73 65 74 28 28 27 41 6c 6c 6f 77 27 2c 20  : set(('Allow', 
e900: 27 43 6f 6e 74 65 6e 74 2d 45 6e 63 6f 64 69 6e  'Content-Encodin
e910: 67 27 2c 20 27 43 6f 6e 74 65 6e 74 2d 4c 61 6e  g', 'Content-Lan
e920: 67 75 61 67 65 27 2c 0a 20 20 20 20 20 20 20 20  guage',.        
e930: 20 20 20 20 20 20 20 20 20 20 27 43 6f 6e 74 65            'Conte
e940: 6e 74 2d 4c 65 6e 67 74 68 27 2c 20 27 43 6f 6e  nt-Length', 'Con
e950: 74 65 6e 74 2d 52 61 6e 67 65 27 2c 20 27 43 6f  tent-Range', 'Co
e960: 6e 74 65 6e 74 2d 54 79 70 65 27 2c 0a 20 20 20  ntent-Type',.   
e970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27                 '
e980: 43 6f 6e 74 65 6e 74 2d 4d 64 35 27 2c 20 27 4c  Content-Md5', 'L
e990: 61 73 74 2d 4d 6f 64 69 66 69 65 64 27 29 29 7d  ast-Modified'))}
e9a0: 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e 69 74  ..    def __init
e9b0: 5f 5f 28 73 65 6c 66 2c 20 62 6f 64 79 3d 27 27  __(self, body=''
e9c0: 2c 20 73 74 61 74 75 73 3d 4e 6f 6e 65 2c 20 68  , status=None, h
e9d0: 65 61 64 65 72 73 3d 4e 6f 6e 65 2c 20 2a 2a 6d  eaders=None, **m
e9e0: 6f 72 65 5f 68 65 61 64 65 72 73 29 3a 0a 20 20  ore_headers):.  
e9f0: 20 20 20 20 20 20 73 65 6c 66 2e 5f 63 6f 6f 6b        self._cook
ea00: 69 65 73 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20  ies = None.     
ea10: 20 20 20 73 65 6c 66 2e 5f 68 65 61 64 65 72 73     self._headers
ea20: 20 3d 20 7b 7d 0a 20 20 20 20 20 20 20 20 73 65   = {}.        se
ea30: 6c 66 2e 62 6f 64 79 20 3d 20 62 6f 64 79 0a 20  lf.body = body. 
ea40: 20 20 20 20 20 20 20 73 65 6c 66 2e 73 74 61 74         self.stat
ea50: 75 73 20 3d 20 73 74 61 74 75 73 20 6f 72 20 73  us = status or s
ea60: 65 6c 66 2e 64 65 66 61 75 6c 74 5f 73 74 61 74  elf.default_stat
ea70: 75 73 0a 20 20 20 20 20 20 20 20 69 66 20 68 65  us.        if he
ea80: 61 64 65 72 73 3a 0a 20 20 20 20 20 20 20 20 20  aders:.         
ea90: 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63 65     if isinstance
eaa0: 28 68 65 61 64 65 72 73 2c 20 64 69 63 74 29 3a  (headers, dict):
eab0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
eac0: 20 68 65 61 64 65 72 73 20 3d 20 68 65 61 64 65   headers = heade
ead0: 72 73 2e 69 74 65 6d 73 28 29 0a 20 20 20 20 20  rs.items().     
eae0: 20 20 20 20 20 20 20 66 6f 72 20 6e 61 6d 65 2c         for name,
eaf0: 20 76 61 6c 75 65 20 69 6e 20 68 65 61 64 65 72   value in header
eb00: 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  s:.             
eb10: 20 20 20 73 65 6c 66 2e 61 64 64 5f 68 65 61 64     self.add_head
eb20: 65 72 28 6e 61 6d 65 2c 20 76 61 6c 75 65 29 0a  er(name, value).
eb30: 20 20 20 20 20 20 20 20 69 66 20 6d 6f 72 65 5f          if more_
eb40: 68 65 61 64 65 72 73 3a 0a 20 20 20 20 20 20 20  headers:.       
eb50: 20 20 20 20 20 66 6f 72 20 6e 61 6d 65 2c 20 76       for name, v
eb60: 61 6c 75 65 20 69 6e 20 6d 6f 72 65 5f 68 65 61  alue in more_hea
eb70: 64 65 72 73 2e 69 74 65 6d 73 28 29 3a 0a 20 20  ders.items():.  
eb80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
eb90: 6c 66 2e 61 64 64 5f 68 65 61 64 65 72 28 6e 61  lf.add_header(na
eba0: 6d 65 2c 20 76 61 6c 75 65 29 0a 0a 20 20 20 20  me, value)..    
ebb0: 64 65 66 20 63 6f 70 79 28 73 65 6c 66 2c 20 63  def copy(self, c
ebc0: 6c 73 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20  ls=None):.      
ebd0: 20 20 27 27 27 20 52 65 74 75 72 6e 73 20 61 20    ''' Returns a 
ebe0: 63 6f 70 79 20 6f 66 20 73 65 6c 66 2e 20 27 27  copy of self. ''
ebf0: 27 0a 20 20 20 20 20 20 20 20 63 6c 73 20 3d 20  '.        cls = 
ec00: 63 6c 73 20 6f 72 20 42 61 73 65 52 65 73 70 6f  cls or BaseRespo
ec10: 6e 73 65 0a 20 20 20 20 20 20 20 20 61 73 73 65  nse.        asse
ec20: 72 74 20 69 73 73 75 62 63 6c 61 73 73 28 63 6c  rt issubclass(cl
ec30: 73 2c 20 42 61 73 65 52 65 73 70 6f 6e 73 65 29  s, BaseResponse)
ec40: 0a 20 20 20 20 20 20 20 20 63 6f 70 79 20 3d 20  .        copy = 
ec50: 63 6c 73 28 29 0a 20 20 20 20 20 20 20 20 63 6f  cls().        co
ec60: 70 79 2e 73 74 61 74 75 73 20 3d 20 73 65 6c 66  py.status = self
ec70: 2e 73 74 61 74 75 73 0a 20 20 20 20 20 20 20 20  .status.        
ec80: 63 6f 70 79 2e 5f 68 65 61 64 65 72 73 20 3d 20  copy._headers = 
ec90: 64 69 63 74 28 28 6b 2c 20 76 5b 3a 5d 29 20 66  dict((k, v[:]) f
eca0: 6f 72 20 28 6b 2c 20 76 29 20 69 6e 20 73 65 6c  or (k, v) in sel
ecb0: 66 2e 5f 68 65 61 64 65 72 73 2e 69 74 65 6d 73  f._headers.items
ecc0: 28 29 29 0a 20 20 20 20 20 20 20 20 69 66 20 73  ()).        if s
ecd0: 65 6c 66 2e 5f 63 6f 6f 6b 69 65 73 3a 0a 20 20  elf._cookies:.  
ece0: 20 20 20 20 20 20 20 20 20 20 63 6f 70 79 2e 5f            copy._
ecf0: 63 6f 6f 6b 69 65 73 20 3d 20 53 69 6d 70 6c 65  cookies = Simple
ed00: 43 6f 6f 6b 69 65 28 29 0a 20 20 20 20 20 20 20  Cookie().       
ed10: 20 20 20 20 20 63 6f 70 79 2e 5f 63 6f 6f 6b 69       copy._cooki
ed20: 65 73 2e 6c 6f 61 64 28 73 65 6c 66 2e 5f 63 6f  es.load(self._co
ed30: 6f 6b 69 65 73 2e 6f 75 74 70 75 74 28 68 65 61  okies.output(hea
ed40: 64 65 72 3d 27 27 29 29 0a 20 20 20 20 20 20 20  der='')).       
ed50: 20 72 65 74 75 72 6e 20 63 6f 70 79 0a 0a 20 20   return copy..  
ed60: 20 20 64 65 66 20 5f 5f 69 74 65 72 5f 5f 28 73    def __iter__(s
ed70: 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 72 65  elf):.        re
ed80: 74 75 72 6e 20 69 74 65 72 28 73 65 6c 66 2e 62  turn iter(self.b
ed90: 6f 64 79 29 0a 0a 20 20 20 20 64 65 66 20 63 6c  ody)..    def cl
eda0: 6f 73 65 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  ose(self):.     
edb0: 20 20 20 69 66 20 68 61 73 61 74 74 72 28 73 65     if hasattr(se
edc0: 6c 66 2e 62 6f 64 79 2c 20 27 63 6c 6f 73 65 27  lf.body, 'close'
edd0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ):.            s
ede0: 65 6c 66 2e 62 6f 64 79 2e 63 6c 6f 73 65 28 29  elf.body.close()
edf0: 0a 0a 20 20 20 20 40 70 72 6f 70 65 72 74 79 0a  ..    @property.
ee00: 20 20 20 20 64 65 66 20 73 74 61 74 75 73 5f 6c      def status_l
ee10: 69 6e 65 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  ine(self):.     
ee20: 20 20 20 27 27 27 20 54 68 65 20 48 54 54 50 20     ''' The HTTP 
ee30: 73 74 61 74 75 73 20 6c 69 6e 65 20 61 73 20 61  status line as a
ee40: 20 73 74 72 69 6e 67 20 28 65 2e 67 2e 20 60 60   string (e.g. ``
ee50: 34 30 34 20 4e 6f 74 20 46 6f 75 6e 64 60 60 29  404 Not Found``)
ee60: 2e 27 27 27 0a 20 20 20 20 20 20 20 20 72 65 74  .'''.        ret
ee70: 75 72 6e 20 73 65 6c 66 2e 5f 73 74 61 74 75 73  urn self._status
ee80: 5f 6c 69 6e 65 0a 0a 20 20 20 20 40 70 72 6f 70  _line..    @prop
ee90: 65 72 74 79 0a 20 20 20 20 64 65 66 20 73 74 61  erty.    def sta
eea0: 74 75 73 5f 63 6f 64 65 28 73 65 6c 66 29 3a 0a  tus_code(self):.
eeb0: 20 20 20 20 20 20 20 20 27 27 27 20 54 68 65 20          ''' The 
eec0: 48 54 54 50 20 73 74 61 74 75 73 20 63 6f 64 65  HTTP status code
eed0: 20 61 73 20 61 6e 20 69 6e 74 65 67 65 72 20 28   as an integer (
eee0: 65 2e 67 2e 20 34 30 34 29 2e 27 27 27 0a 20 20  e.g. 404).'''.  
eef0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
ef00: 66 2e 5f 73 74 61 74 75 73 5f 63 6f 64 65 0a 0a  f._status_code..
ef10: 20 20 20 20 64 65 66 20 5f 73 65 74 5f 73 74 61      def _set_sta
ef20: 74 75 73 28 73 65 6c 66 2c 20 73 74 61 74 75 73  tus(self, status
ef30: 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 69 73  ):.        if is
ef40: 69 6e 73 74 61 6e 63 65 28 73 74 61 74 75 73 2c  instance(status,
ef50: 20 69 6e 74 29 3a 0a 20 20 20 20 20 20 20 20 20   int):.         
ef60: 20 20 20 63 6f 64 65 2c 20 73 74 61 74 75 73 20     code, status 
ef70: 3d 20 73 74 61 74 75 73 2c 20 5f 48 54 54 50 5f  = status, _HTTP_
ef80: 53 54 41 54 55 53 5f 4c 49 4e 45 53 2e 67 65 74  STATUS_LINES.get
ef90: 28 73 74 61 74 75 73 29 0a 20 20 20 20 20 20 20  (status).       
efa0: 20 65 6c 69 66 20 27 20 27 20 69 6e 20 73 74 61   elif ' ' in sta
efb0: 74 75 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20  tus:.           
efc0: 20 73 74 61 74 75 73 20 3d 20 73 74 61 74 75 73   status = status
efd0: 2e 73 74 72 69 70 28 29 0a 20 20 20 20 20 20 20  .strip().       
efe0: 20 20 20 20 20 63 6f 64 65 20 20 20 3d 20 69 6e       code   = in
eff0: 74 28 73 74 61 74 75 73 2e 73 70 6c 69 74 28 29  t(status.split()
f000: 5b 30 5d 29 0a 20 20 20 20 20 20 20 20 65 6c 73  [0]).        els
f010: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  e:.            r
f020: 61 69 73 65 20 56 61 6c 75 65 45 72 72 6f 72 28  aise ValueError(
f030: 27 53 74 72 69 6e 67 20 73 74 61 74 75 73 20 6c  'String status l
f040: 69 6e 65 20 77 69 74 68 6f 75 74 20 61 20 72 65  ine without a re
f050: 61 73 6f 6e 20 70 68 72 61 73 65 2e 27 29 0a 20  ason phrase.'). 
f060: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 31 30         if not 10
f070: 30 20 3c 3d 20 63 6f 64 65 20 3c 3d 20 39 39 39  0 <= code <= 999
f080: 3a 20 72 61 69 73 65 20 56 61 6c 75 65 45 72 72  : raise ValueErr
f090: 6f 72 28 27 53 74 61 74 75 73 20 63 6f 64 65 20  or('Status code 
f0a0: 6f 75 74 20 6f 66 20 72 61 6e 67 65 2e 27 29 0a  out of range.').
f0b0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 74          self._st
f0c0: 61 74 75 73 5f 63 6f 64 65 20 3d 20 63 6f 64 65  atus_code = code
f0d0: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73  .        self._s
f0e0: 74 61 74 75 73 5f 6c 69 6e 65 20 3d 20 73 74 72  tatus_line = str
f0f0: 28 73 74 61 74 75 73 20 6f 72 20 28 27 25 64 20  (status or ('%d 
f100: 55 6e 6b 6e 6f 77 6e 27 20 25 20 63 6f 64 65 29  Unknown' % code)
f110: 29 0a 0a 20 20 20 20 64 65 66 20 5f 67 65 74 5f  )..    def _get_
f120: 73 74 61 74 75 73 28 73 65 6c 66 29 3a 0a 20 20  status(self):.  
f130: 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
f140: 66 2e 5f 73 74 61 74 75 73 5f 6c 69 6e 65 0a 0a  f._status_line..
f150: 20 20 20 20 73 74 61 74 75 73 20 3d 20 70 72 6f      status = pro
f160: 70 65 72 74 79 28 5f 67 65 74 5f 73 74 61 74 75  perty(_get_statu
f170: 73 2c 20 5f 73 65 74 5f 73 74 61 74 75 73 2c 20  s, _set_status, 
f180: 4e 6f 6e 65 2c 0a 20 20 20 20 20 20 20 20 27 27  None,.        ''
f190: 27 20 41 20 77 72 69 74 65 61 62 6c 65 20 70 72  ' A writeable pr
f1a0: 6f 70 65 72 74 79 20 74 6f 20 63 68 61 6e 67 65  operty to change
f1b0: 20 74 68 65 20 48 54 54 50 20 72 65 73 70 6f 6e   the HTTP respon
f1c0: 73 65 20 73 74 61 74 75 73 2e 20 49 74 20 61 63  se status. It ac
f1d0: 63 65 70 74 73 0a 20 20 20 20 20 20 20 20 20 20  cepts.          
f1e0: 20 20 65 69 74 68 65 72 20 61 20 6e 75 6d 65 72    either a numer
f1f0: 69 63 20 63 6f 64 65 20 28 31 30 30 2d 39 39 39  ic code (100-999
f200: 29 20 6f 72 20 61 20 73 74 72 69 6e 67 20 77 69  ) or a string wi
f210: 74 68 20 61 20 63 75 73 74 6f 6d 20 72 65 61 73  th a custom reas
f220: 6f 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 70  on.            p
f230: 68 72 61 73 65 20 28 65 2e 67 2e 20 22 34 30 34  hrase (e.g. "404
f240: 20 42 72 61 69 6e 20 6e 6f 74 20 66 6f 75 6e 64   Brain not found
f250: 22 29 2e 20 42 6f 74 68 20 3a 64 61 74 61 3a 60  "). Both :data:`
f260: 73 74 61 74 75 73 5f 6c 69 6e 65 60 20 61 6e 64  status_line` and
f270: 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a 64 61  .            :da
f280: 74 61 3a 60 73 74 61 74 75 73 5f 63 6f 64 65 60  ta:`status_code`
f290: 20 61 72 65 20 75 70 64 61 74 65 64 20 61 63 63   are updated acc
f2a0: 6f 72 64 69 6e 67 6c 79 2e 20 54 68 65 20 72 65  ordingly. The re
f2b0: 74 75 72 6e 20 76 61 6c 75 65 20 69 73 0a 20 20  turn value is.  
f2c0: 20 20 20 20 20 20 20 20 20 20 61 6c 77 61 79 73            always
f2d0: 20 61 20 73 74 61 74 75 73 20 73 74 72 69 6e 67   a status string
f2e0: 2e 20 27 27 27 29 0a 20 20 20 20 64 65 6c 20 5f  . ''').    del _
f2f0: 67 65 74 5f 73 74 61 74 75 73 2c 20 5f 73 65 74  get_status, _set
f300: 5f 73 74 61 74 75 73 0a 0a 20 20 20 20 40 70 72  _status..    @pr
f310: 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20 68  operty.    def h
f320: 65 61 64 65 72 73 28 73 65 6c 66 29 3a 0a 20 20  eaders(self):.  
f330: 20 20 20 20 20 20 27 27 27 20 41 6e 20 69 6e 73        ''' An ins
f340: 74 61 6e 63 65 20 6f 66 20 3a 63 6c 61 73 73 3a  tance of :class:
f350: 60 48 65 61 64 65 72 44 69 63 74 60 2c 20 61 20  `HeaderDict`, a 
f360: 63 61 73 65 2d 69 6e 73 65 6e 73 69 74 69 76 65  case-insensitive
f370: 20 64 69 63 74 2d 6c 69 6b 65 0a 20 20 20 20 20   dict-like.     
f380: 20 20 20 20 20 20 20 76 69 65 77 20 6f 6e 20 74         view on t
f390: 68 65 20 72 65 73 70 6f 6e 73 65 20 68 65 61 64  he response head
f3a0: 65 72 73 2e 20 27 27 27 0a 20 20 20 20 20 20 20  ers. '''.       
f3b0: 20 68 64 69 63 74 20 3d 20 48 65 61 64 65 72 44   hdict = HeaderD
f3c0: 69 63 74 28 29 0a 20 20 20 20 20 20 20 20 68 64  ict().        hd
f3d0: 69 63 74 2e 64 69 63 74 20 3d 20 73 65 6c 66 2e  ict.dict = self.
f3e0: 5f 68 65 61 64 65 72 73 0a 20 20 20 20 20 20 20  _headers.       
f3f0: 20 72 65 74 75 72 6e 20 68 64 69 63 74 0a 0a 20   return hdict.. 
f400: 20 20 20 64 65 66 20 5f 5f 63 6f 6e 74 61 69 6e     def __contain
f410: 73 5f 5f 28 73 65 6c 66 2c 20 6e 61 6d 65 29 3a  s__(self, name):
f420: 20 72 65 74 75 72 6e 20 5f 68 6b 65 79 28 6e 61   return _hkey(na
f430: 6d 65 29 20 69 6e 20 73 65 6c 66 2e 5f 68 65 61  me) in self._hea
f440: 64 65 72 73 0a 20 20 20 20 64 65 66 20 5f 5f 64  ders.    def __d
f450: 65 6c 69 74 65 6d 5f 5f 28 73 65 6c 66 2c 20 6e  elitem__(self, n
f460: 61 6d 65 29 3a 20 20 64 65 6c 20 73 65 6c 66 2e  ame):  del self.
f470: 5f 68 65 61 64 65 72 73 5b 5f 68 6b 65 79 28 6e  _headers[_hkey(n
f480: 61 6d 65 29 5d 0a 20 20 20 20 64 65 66 20 5f 5f  ame)].    def __
f490: 67 65 74 69 74 65 6d 5f 5f 28 73 65 6c 66 2c 20  getitem__(self, 
f4a0: 6e 61 6d 65 29 3a 20 20 72 65 74 75 72 6e 20 73  name):  return s
f4b0: 65 6c 66 2e 5f 68 65 61 64 65 72 73 5b 5f 68 6b  elf._headers[_hk
f4c0: 65 79 28 6e 61 6d 65 29 5d 5b 2d 31 5d 0a 20 20  ey(name)][-1].  
f4d0: 20 20 64 65 66 20 5f 5f 73 65 74 69 74 65 6d 5f    def __setitem_
f4e0: 5f 28 73 65 6c 66 2c 20 6e 61 6d 65 2c 20 76 61  _(self, name, va
f4f0: 6c 75 65 29 3a 20 73 65 6c 66 2e 5f 68 65 61 64  lue): self._head
f500: 65 72 73 5b 5f 68 6b 65 79 28 6e 61 6d 65 29 5d  ers[_hkey(name)]
f510: 20 3d 20 5b 5f 68 76 61 6c 28 76 61 6c 75 65 29   = [_hval(value)
f520: 5d 0a 0a 20 20 20 20 64 65 66 20 67 65 74 5f 68  ]..    def get_h
f530: 65 61 64 65 72 28 73 65 6c 66 2c 20 6e 61 6d 65  eader(self, name
f540: 2c 20 64 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a  , default=None):
f550: 0a 20 20 20 20 20 20 20 20 27 27 27 20 52 65 74  .        ''' Ret
f560: 75 72 6e 20 74 68 65 20 76 61 6c 75 65 20 6f 66  urn the value of
f570: 20 61 20 70 72 65 76 69 6f 75 73 6c 79 20 64 65   a previously de
f580: 66 69 6e 65 64 20 68 65 61 64 65 72 2e 20 49 66  fined header. If
f590: 20 74 68 65 72 65 20 69 73 20 6e 6f 0a 20 20 20   there is no.   
f5a0: 20 20 20 20 20 20 20 20 20 68 65 61 64 65 72 20           header 
f5b0: 77 69 74 68 20 74 68 61 74 20 6e 61 6d 65 2c 20  with that name, 
f5c0: 72 65 74 75 72 6e 20 61 20 64 65 66 61 75 6c 74  return a default
f5d0: 20 76 61 6c 75 65 2e 20 27 27 27 0a 20 20 20 20   value. '''.    
f5e0: 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e      return self.
f5f0: 5f 68 65 61 64 65 72 73 2e 67 65 74 28 5f 68 6b  _headers.get(_hk
f600: 65 79 28 6e 61 6d 65 29 2c 20 5b 64 65 66 61 75  ey(name), [defau
f610: 6c 74 5d 29 5b 2d 31 5d 0a 0a 20 20 20 20 64 65  lt])[-1]..    de
f620: 66 20 73 65 74 5f 68 65 61 64 65 72 28 73 65 6c  f set_header(sel
f630: 66 2c 20 6e 61 6d 65 2c 20 76 61 6c 75 65 29 3a  f, name, value):
f640: 0a 20 20 20 20 20 20 20 20 27 27 27 20 43 72 65  .        ''' Cre
f650: 61 74 65 20 61 20 6e 65 77 20 72 65 73 70 6f 6e  ate a new respon
f660: 73 65 20 68 65 61 64 65 72 2c 20 72 65 70 6c 61  se header, repla
f670: 63 69 6e 67 20 61 6e 79 20 70 72 65 76 69 6f 75  cing any previou
f680: 73 6c 79 20 64 65 66 69 6e 65 64 0a 20 20 20 20  sly defined.    
f690: 20 20 20 20 20 20 20 20 68 65 61 64 65 72 73 20          headers 
f6a0: 77 69 74 68 20 74 68 65 20 73 61 6d 65 20 6e 61  with the same na
f6b0: 6d 65 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20  me. '''.        
f6c0: 73 65 6c 66 2e 5f 68 65 61 64 65 72 73 5b 5f 68  self._headers[_h
f6d0: 6b 65 79 28 6e 61 6d 65 29 5d 20 3d 20 5b 5f 68  key(name)] = [_h
f6e0: 76 61 6c 28 76 61 6c 75 65 29 5d 0a 0a 20 20 20  val(value)]..   
f6f0: 20 64 65 66 20 61 64 64 5f 68 65 61 64 65 72 28   def add_header(
f700: 73 65 6c 66 2c 20 6e 61 6d 65 2c 20 76 61 6c 75  self, name, valu
f710: 65 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20  e):.        ''' 
f720: 41 64 64 20 61 6e 20 61 64 64 69 74 69 6f 6e 61  Add an additiona
f730: 6c 20 72 65 73 70 6f 6e 73 65 20 68 65 61 64 65  l response heade
f740: 72 2c 20 6e 6f 74 20 72 65 6d 6f 76 69 6e 67 20  r, not removing 
f750: 64 75 70 6c 69 63 61 74 65 73 2e 20 27 27 27 0a  duplicates. '''.
f760: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 68 65          self._he
f770: 61 64 65 72 73 2e 73 65 74 64 65 66 61 75 6c 74  aders.setdefault
f780: 28 5f 68 6b 65 79 28 6e 61 6d 65 29 2c 20 5b 5d  (_hkey(name), []
f790: 29 2e 61 70 70 65 6e 64 28 5f 68 76 61 6c 28 76  ).append(_hval(v
f7a0: 61 6c 75 65 29 29 0a 0a 20 20 20 20 64 65 66 20  alue))..    def 
f7b0: 69 74 65 72 5f 68 65 61 64 65 72 73 28 73 65 6c  iter_headers(sel
f7c0: 66 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20  f):.        ''' 
f7d0: 59 69 65 6c 64 20 28 68 65 61 64 65 72 2c 20 76  Yield (header, v
f7e0: 61 6c 75 65 29 20 74 75 70 6c 65 73 2c 20 73 6b  alue) tuples, sk
f7f0: 69 70 70 69 6e 67 20 68 65 61 64 65 72 73 20 74  ipping headers t
f800: 68 61 74 20 61 72 65 20 6e 6f 74 0a 20 20 20 20  hat are not.    
f810: 20 20 20 20 20 20 20 20 61 6c 6c 6f 77 65 64 20          allowed 
f820: 77 69 74 68 20 74 68 65 20 63 75 72 72 65 6e 74  with the current
f830: 20 72 65 73 70 6f 6e 73 65 20 73 74 61 74 75 73   response status
f840: 20 63 6f 64 65 2e 20 27 27 27 0a 20 20 20 20 20   code. '''.     
f850: 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 68     return self.h
f860: 65 61 64 65 72 6c 69 73 74 0a 0a 20 20 20 20 40  eaderlist..    @
f870: 70 72 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66  property.    def
f880: 20 68 65 61 64 65 72 6c 69 73 74 28 73 65 6c 66   headerlist(self
f890: 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 57  ):.        ''' W
f8a0: 53 47 49 20 63 6f 6e 66 6f 72 6d 20 6c 69 73 74  SGI conform list
f8b0: 20 6f 66 20 28 68 65 61 64 65 72 2c 20 76 61 6c   of (header, val
f8c0: 75 65 29 20 74 75 70 6c 65 73 2e 20 27 27 27 0a  ue) tuples. '''.
f8d0: 20 20 20 20 20 20 20 20 6f 75 74 20 3d 20 5b 5d          out = []
f8e0: 0a 20 20 20 20 20 20 20 20 68 65 61 64 65 72 73  .        headers
f8f0: 20 3d 20 6c 69 73 74 28 73 65 6c 66 2e 5f 68 65   = list(self._he
f900: 61 64 65 72 73 2e 69 74 65 6d 73 28 29 29 0a 20  aders.items()). 
f910: 20 20 20 20 20 20 20 69 66 20 27 43 6f 6e 74 65         if 'Conte
f920: 6e 74 2d 54 79 70 65 27 20 6e 6f 74 20 69 6e 20  nt-Type' not in 
f930: 73 65 6c 66 2e 5f 68 65 61 64 65 72 73 3a 0a 20  self._headers:. 
f940: 20 20 20 20 20 20 20 20 20 20 20 68 65 61 64 65             heade
f950: 72 73 2e 61 70 70 65 6e 64 28 28 27 43 6f 6e 74  rs.append(('Cont
f960: 65 6e 74 2d 54 79 70 65 27 2c 20 5b 73 65 6c 66  ent-Type', [self
f970: 2e 64 65 66 61 75 6c 74 5f 63 6f 6e 74 65 6e 74  .default_content
f980: 5f 74 79 70 65 5d 29 29 0a 20 20 20 20 20 20 20  _type])).       
f990: 20 69 66 20 73 65 6c 66 2e 5f 73 74 61 74 75 73   if self._status
f9a0: 5f 63 6f 64 65 20 69 6e 20 73 65 6c 66 2e 62 61  _code in self.ba
f9b0: 64 5f 68 65 61 64 65 72 73 3a 0a 20 20 20 20 20  d_headers:.     
f9c0: 20 20 20 20 20 20 20 62 61 64 5f 68 65 61 64 65         bad_heade
f9d0: 72 73 20 3d 20 73 65 6c 66 2e 62 61 64 5f 68 65  rs = self.bad_he
f9e0: 61 64 65 72 73 5b 73 65 6c 66 2e 5f 73 74 61 74  aders[self._stat
f9f0: 75 73 5f 63 6f 64 65 5d 0a 20 20 20 20 20 20 20  us_code].       
fa00: 20 20 20 20 20 68 65 61 64 65 72 73 20 3d 20 5b       headers = [
fa10: 68 20 66 6f 72 20 68 20 69 6e 20 68 65 61 64 65  h for h in heade
fa20: 72 73 20 69 66 20 68 5b 30 5d 20 6e 6f 74 20 69  rs if h[0] not i
fa30: 6e 20 62 61 64 5f 68 65 61 64 65 72 73 5d 0a 20  n bad_headers]. 
fa40: 20 20 20 20 20 20 20 6f 75 74 20 2b 3d 20 5b 28         out += [(
fa50: 6e 61 6d 65 2c 20 76 61 6c 29 20 66 6f 72 20 6e  name, val) for n
fa60: 61 6d 65 2c 20 76 61 6c 73 20 69 6e 20 68 65 61  ame, vals in hea
fa70: 64 65 72 73 20 66 6f 72 20 76 61 6c 20 69 6e 20  ders for val in 
fa80: 76 61 6c 73 5d 0a 20 20 20 20 20 20 20 20 69 66  vals].        if
fa90: 20 73 65 6c 66 2e 5f 63 6f 6f 6b 69 65 73 3a 0a   self._cookies:.
faa0: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
fab0: 63 20 69 6e 20 73 65 6c 66 2e 5f 63 6f 6f 6b 69  c in self._cooki
fac0: 65 73 2e 76 61 6c 75 65 73 28 29 3a 0a 20 20 20  es.values():.   
fad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 6f 75 74               out
fae0: 2e 61 70 70 65 6e 64 28 28 27 53 65 74 2d 43 6f  .append(('Set-Co
faf0: 6f 6b 69 65 27 2c 20 63 2e 4f 75 74 70 75 74 53  okie', c.OutputS
fb00: 74 72 69 6e 67 28 29 29 29 0a 20 20 20 20 20 20  tring())).      
fb10: 20 20 72 65 74 75 72 6e 20 6f 75 74 0a 0a 20 20    return out..  
fb20: 20 20 63 6f 6e 74 65 6e 74 5f 74 79 70 65 20 3d    content_type =
fb30: 20 48 65 61 64 65 72 50 72 6f 70 65 72 74 79 28   HeaderProperty(
fb40: 27 43 6f 6e 74 65 6e 74 2d 54 79 70 65 27 29 0a  'Content-Type').
fb50: 20 20 20 20 63 6f 6e 74 65 6e 74 5f 6c 65 6e 67      content_leng
fb60: 74 68 20 3d 20 48 65 61 64 65 72 50 72 6f 70 65  th = HeaderPrope
fb70: 72 74 79 28 27 43 6f 6e 74 65 6e 74 2d 4c 65 6e  rty('Content-Len
fb80: 67 74 68 27 2c 20 72 65 61 64 65 72 3d 69 6e 74  gth', reader=int
fb90: 29 0a 20 20 20 20 65 78 70 69 72 65 73 20 3d 20  ).    expires = 
fba0: 48 65 61 64 65 72 50 72 6f 70 65 72 74 79 28 27  HeaderProperty('
fbb0: 45 78 70 69 72 65 73 27 2c 0a 20 20 20 20 20 20  Expires',.      
fbc0: 20 20 72 65 61 64 65 72 3d 6c 61 6d 62 64 61 20    reader=lambda 
fbd0: 78 3a 20 64 61 74 65 74 69 6d 65 2e 75 74 63 66  x: datetime.utcf
fbe0: 72 6f 6d 74 69 6d 65 73 74 61 6d 70 28 70 61 72  romtimestamp(par
fbf0: 73 65 5f 64 61 74 65 28 78 29 29 2c 0a 20 20 20  se_date(x)),.   
fc00: 20 20 20 20 20 77 72 69 74 65 72 3d 6c 61 6d 62       writer=lamb
fc10: 64 61 20 78 3a 20 68 74 74 70 5f 64 61 74 65 28  da x: http_date(
fc20: 78 29 29 0a 0a 20 20 20 20 40 70 72 6f 70 65 72  x))..    @proper
fc30: 74 79 0a 20 20 20 20 64 65 66 20 63 68 61 72 73  ty.    def chars
fc40: 65 74 28 73 65 6c 66 2c 20 64 65 66 61 75 6c 74  et(self, default
fc50: 3d 27 55 54 46 2d 38 27 29 3a 0a 20 20 20 20 20  ='UTF-8'):.     
fc60: 20 20 20 22 22 22 20 52 65 74 75 72 6e 20 74 68     """ Return th
fc70: 65 20 63 68 61 72 73 65 74 20 73 70 65 63 69 66  e charset specif
fc80: 69 65 64 20 69 6e 20 74 68 65 20 63 6f 6e 74 65  ied in the conte
fc90: 6e 74 2d 74 79 70 65 20 68 65 61 64 65 72 20 28  nt-type header (
fca0: 64 65 66 61 75 6c 74 3a 20 75 74 66 38 29 2e 20  default: utf8). 
fcb0: 22 22 22 0a 20 20 20 20 20 20 20 20 69 66 20 27  """.        if '
fcc0: 63 68 61 72 73 65 74 3d 27 20 69 6e 20 73 65 6c  charset=' in sel
fcd0: 66 2e 63 6f 6e 74 65 6e 74 5f 74 79 70 65 3a 0a  f.content_type:.
fce0: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
fcf0: 72 6e 20 73 65 6c 66 2e 63 6f 6e 74 65 6e 74 5f  rn self.content_
fd00: 74 79 70 65 2e 73 70 6c 69 74 28 27 63 68 61 72  type.split('char
fd10: 73 65 74 3d 27 29 5b 2d 31 5d 2e 73 70 6c 69 74  set=')[-1].split
fd20: 28 27 3b 27 29 5b 30 5d 2e 73 74 72 69 70 28 29  (';')[0].strip()
fd30: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
fd40: 64 65 66 61 75 6c 74 0a 0a 20 20 20 20 64 65 66  default..    def
fd50: 20 73 65 74 5f 63 6f 6f 6b 69 65 28 73 65 6c 66   set_cookie(self
fd60: 2c 20 6e 61 6d 65 2c 20 76 61 6c 75 65 2c 20 73  , name, value, s
fd70: 65 63 72 65 74 3d 4e 6f 6e 65 2c 20 2a 2a 6f 70  ecret=None, **op
fd80: 74 69 6f 6e 73 29 3a 0a 20 20 20 20 20 20 20 20  tions):.        
fd90: 27 27 27 20 43 72 65 61 74 65 20 61 20 6e 65 77  ''' Create a new
fda0: 20 63 6f 6f 6b 69 65 20 6f 72 20 72 65 70 6c 61   cookie or repla
fdb0: 63 65 20 61 6e 20 6f 6c 64 20 6f 6e 65 2e 20 49  ce an old one. I
fdc0: 66 20 74 68 65 20 60 73 65 63 72 65 74 60 20 70  f the `secret` p
fdd0: 61 72 61 6d 65 74 65 72 20 69 73 0a 20 20 20 20  arameter is.    
fde0: 20 20 20 20 20 20 20 20 73 65 74 2c 20 63 72 65          set, cre
fdf0: 61 74 65 20 61 20 60 53 69 67 6e 65 64 20 43 6f  ate a `Signed Co
fe00: 6f 6b 69 65 60 20 28 64 65 73 63 72 69 62 65 64  okie` (described
fe10: 20 62 65 6c 6f 77 29 2e 0a 0a 20 20 20 20 20 20   below)...      
fe20: 20 20 20 20 20 20 3a 70 61 72 61 6d 20 6e 61 6d        :param nam
fe30: 65 3a 20 74 68 65 20 6e 61 6d 65 20 6f 66 20 74  e: the name of t
fe40: 68 65 20 63 6f 6f 6b 69 65 2e 0a 20 20 20 20 20  he cookie..     
fe50: 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 76 61         :param va
fe60: 6c 75 65 3a 20 74 68 65 20 76 61 6c 75 65 20 6f  lue: the value o
fe70: 66 20 74 68 65 20 63 6f 6f 6b 69 65 2e 0a 20 20  f the cookie..  
fe80: 20 20 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d            :param
fe90: 20 73 65 63 72 65 74 3a 20 61 20 73 69 67 6e 61   secret: a signa
fea0: 74 75 72 65 20 6b 65 79 20 72 65 71 75 69 72 65  ture key require
feb0: 64 20 66 6f 72 20 73 69 67 6e 65 64 20 63 6f 6f  d for signed coo
fec0: 6b 69 65 73 2e 0a 0a 20 20 20 20 20 20 20 20 20  kies...         
fed0: 20 20 20 41 64 64 69 74 69 6f 6e 61 6c 6c 79 2c     Additionally,
fee0: 20 74 68 69 73 20 6d 65 74 68 6f 64 20 61 63 63   this method acc
fef0: 65 70 74 73 20 61 6c 6c 20 52 46 43 20 32 31 30  epts all RFC 210
ff00: 39 20 61 74 74 72 69 62 75 74 65 73 20 74 68 61  9 attributes tha
ff10: 74 20 61 72 65 0a 20 20 20 20 20 20 20 20 20 20  t are.          
ff20: 20 20 73 75 70 70 6f 72 74 65 64 20 62 79 20 3a    supported by :
ff30: 63 6c 61 73 73 3a 60 63 6f 6f 6b 69 65 2e 4d 6f  class:`cookie.Mo
ff40: 72 73 65 6c 60 2c 20 69 6e 63 6c 75 64 69 6e 67  rsel`, including
ff50: 3a 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a  :..            :
ff60: 70 61 72 61 6d 20 6d 61 78 5f 61 67 65 3a 20 6d  param max_age: m
ff70: 61 78 69 6d 75 6d 20 61 67 65 20 69 6e 20 73 65  aximum age in se
ff80: 63 6f 6e 64 73 2e 20 28 64 65 66 61 75 6c 74 3a  conds. (default:
ff90: 20 4e 6f 6e 65 29 0a 20 20 20 20 20 20 20 20 20   None).         
ffa0: 20 20 20 3a 70 61 72 61 6d 20 65 78 70 69 72 65     :param expire
ffb0: 73 3a 20 61 20 64 61 74 65 74 69 6d 65 20 6f 62  s: a datetime ob
ffc0: 6a 65 63 74 20 6f 72 20 55 4e 49 58 20 74 69 6d  ject or UNIX tim
ffd0: 65 73 74 61 6d 70 2e 20 28 64 65 66 61 75 6c 74  estamp. (default
ffe0: 3a 20 4e 6f 6e 65 29 0a 20 20 20 20 20 20 20 20  : None).        
fff0: 20 20 20 20 3a 70 61 72 61 6d 20 64 6f 6d 61 69      :param domai
10000 6e 3a 20 74 68 65 20 64 6f 6d 61 69 6e 20 74 68  n: the domain th
10010 61 74 20 69 73 20 61 6c 6c 6f 77 65 64 20 74 6f  at is allowed to
10020 20 72 65 61 64 20 74 68 65 20 63 6f 6f 6b 69 65   read the cookie
10030 2e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ..              
10040 28 64 65 66 61 75 6c 74 3a 20 63 75 72 72 65 6e  (default: curren
10050 74 20 64 6f 6d 61 69 6e 29 0a 20 20 20 20 20 20  t domain).      
10060 20 20 20 20 20 20 3a 70 61 72 61 6d 20 70 61 74        :param pat
10070 68 3a 20 6c 69 6d 69 74 73 20 74 68 65 20 63 6f  h: limits the co
10080 6f 6b 69 65 20 74 6f 20 61 20 67 69 76 65 6e 20  okie to a given 
10090 70 61 74 68 20 28 64 65 66 61 75 6c 74 3a 20 63  path (default: c
100a0 75 72 72 65 6e 74 20 70 61 74 68 29 0a 20 20 20  urrent path).   
100b0 20 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20           :param 
100c0 73 65 63 75 72 65 3a 20 6c 69 6d 69 74 20 74 68  secure: limit th
100d0 65 20 63 6f 6f 6b 69 65 20 74 6f 20 48 54 54 50  e cookie to HTTP
100e0 53 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 28 64  S connections (d
100f0 65 66 61 75 6c 74 3a 20 6f 66 66 29 2e 0a 20 20  efault: off)..  
10100 20 20 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d            :param
10110 20 68 74 74 70 6f 6e 6c 79 3a 20 70 72 65 76 65   httponly: preve
10120 6e 74 73 20 63 6c 69 65 6e 74 2d 73 69 64 65 20  nts client-side 
10130 6a 61 76 61 73 63 72 69 70 74 20 74 6f 20 72 65  javascript to re
10140 61 64 20 74 68 69 73 20 63 6f 6f 6b 69 65 0a 20  ad this cookie. 
10150 20 20 20 20 20 20 20 20 20 20 20 20 20 28 64 65               (de
10160 66 61 75 6c 74 3a 20 6f 66 66 2c 20 72 65 71 75  fault: off, requ
10170 69 72 65 73 20 50 79 74 68 6f 6e 20 32 2e 36 20  ires Python 2.6 
10180 6f 72 20 6e 65 77 65 72 29 2e 0a 0a 20 20 20 20  or newer)...    
10190 20 20 20 20 20 20 20 20 49 66 20 6e 65 69 74 68          If neith
101a0 65 72 20 60 65 78 70 69 72 65 73 60 20 6e 6f 72  er `expires` nor
101b0 20 60 6d 61 78 5f 61 67 65 60 20 69 73 20 73 65   `max_age` is se
101c0 74 20 28 64 65 66 61 75 6c 74 29 2c 20 74 68 65  t (default), the
101d0 20 63 6f 6f 6b 69 65 20 77 69 6c 6c 0a 20 20 20   cookie will.   
101e0 20 20 20 20 20 20 20 20 20 65 78 70 69 72 65 20           expire 
101f0 61 74 20 74 68 65 20 65 6e 64 20 6f 66 20 74 68  at the end of th
10200 65 20 62 72 6f 77 73 65 72 20 73 65 73 73 69 6f  e browser sessio
10210 6e 20 28 61 73 20 73 6f 6f 6e 20 61 73 20 74 68  n (as soon as th
10220 65 20 62 72 6f 77 73 65 72 0a 20 20 20 20 20 20  e browser.      
10230 20 20 20 20 20 20 77 69 6e 64 6f 77 20 69 73 20        window is 
10240 63 6c 6f 73 65 64 29 2e 0a 0a 20 20 20 20 20 20  closed)...      
10250 20 20 20 20 20 20 53 69 67 6e 65 64 20 63 6f 6f        Signed coo
10260 6b 69 65 73 20 6d 61 79 20 73 74 6f 72 65 20 61  kies may store a
10270 6e 79 20 70 69 63 6b 6c 65 2d 61 62 6c 65 20 6f  ny pickle-able o
10280 62 6a 65 63 74 20 61 6e 64 20 61 72 65 0a 20 20  bject and are.  
10290 20 20 20 20 20 20 20 20 20 20 63 72 79 70 74 6f            crypto
102a0 67 72 61 70 68 69 63 61 6c 6c 79 20 73 69 67 6e  graphically sign
102b0 65 64 20 74 6f 20 70 72 65 76 65 6e 74 20 6d 61  ed to prevent ma
102c0 6e 69 70 75 6c 61 74 69 6f 6e 2e 20 4b 65 65 70  nipulation. Keep
102d0 20 69 6e 20 6d 69 6e 64 20 74 68 61 74 0a 20 20   in mind that.  
102e0 20 20 20 20 20 20 20 20 20 20 63 6f 6f 6b 69 65            cookie
102f0 73 20 61 72 65 20 6c 69 6d 69 74 65 64 20 74 6f  s are limited to
10300 20 34 6b 62 20 69 6e 20 6d 6f 73 74 20 62 72 6f   4kb in most bro
10310 77 73 65 72 73 2e 0a 0a 20 20 20 20 20 20 20 20  wsers...        
10320 20 20 20 20 57 61 72 6e 69 6e 67 3a 20 53 69 67      Warning: Sig
10330 6e 65 64 20 63 6f 6f 6b 69 65 73 20 61 72 65 20  ned cookies are 
10340 6e 6f 74 20 65 6e 63 72 79 70 74 65 64 20 28 74  not encrypted (t
10350 68 65 20 63 6c 69 65 6e 74 20 63 61 6e 20 73 74  he client can st
10360 69 6c 6c 20 73 65 65 0a 20 20 20 20 20 20 20 20  ill see.        
10370 20 20 20 20 74 68 65 20 63 6f 6e 74 65 6e 74 29      the content)
10380 20 61 6e 64 20 6e 6f 74 20 63 6f 70 79 2d 70 72   and not copy-pr
10390 6f 74 65 63 74 65 64 20 28 74 68 65 20 63 6c 69  otected (the cli
103a0 65 6e 74 20 63 61 6e 20 72 65 73 74 6f 72 65 20  ent can restore 
103b0 61 6e 20 6f 6c 64 0a 20 20 20 20 20 20 20 20 20  an old.         
103c0 20 20 20 63 6f 6f 6b 69 65 29 2e 20 54 68 65 20     cookie). The 
103d0 6d 61 69 6e 20 69 6e 74 65 6e 74 69 6f 6e 20 69  main intention i
103e0 73 20 74 6f 20 6d 61 6b 65 20 70 69 63 6b 6c 69  s to make pickli
103f0 6e 67 20 61 6e 64 20 75 6e 70 69 63 6b 6c 69 6e  ng and unpicklin
10400 67 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 61  g.            sa
10410 76 65 2c 20 6e 6f 74 20 74 6f 20 73 74 6f 72 65  ve, not to store
10420 20 73 65 63 72 65 74 20 69 6e 66 6f 72 6d 61 74   secret informat
10430 69 6f 6e 20 61 74 20 63 6c 69 65 6e 74 20 73 69  ion at client si
10440 64 65 2e 0a 20 20 20 20 20 20 20 20 27 27 27 0a  de..        '''.
10450 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73          if not s
10460 65 6c 66 2e 5f 63 6f 6f 6b 69 65 73 3a 0a 20 20  elf._cookies:.  
10470 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
10480 63 6f 6f 6b 69 65 73 20 3d 20 53 69 6d 70 6c 65  cookies = Simple
10490 43 6f 6f 6b 69 65 28 29 0a 0a 20 20 20 20 20 20  Cookie()..      
104a0 20 20 69 66 20 73 65 63 72 65 74 3a 0a 20 20 20    if secret:.   
104b0 20 20 20 20 20 20 20 20 20 76 61 6c 75 65 20 3d           value =
104c0 20 74 6f 75 6e 69 28 63 6f 6f 6b 69 65 5f 65 6e   touni(cookie_en
104d0 63 6f 64 65 28 28 6e 61 6d 65 2c 20 76 61 6c 75  code((name, valu
104e0 65 29 2c 20 73 65 63 72 65 74 29 29 0a 20 20 20  e), secret)).   
104f0 20 20 20 20 20 65 6c 69 66 20 6e 6f 74 20 69 73       elif not is
10500 69 6e 73 74 61 6e 63 65 28 76 61 6c 75 65 2c 20  instance(value, 
10510 62 61 73 65 73 74 72 69 6e 67 29 3a 0a 20 20 20  basestring):.   
10520 20 20 20 20 20 20 20 20 20 72 61 69 73 65 20 54           raise T
10530 79 70 65 45 72 72 6f 72 28 27 53 65 63 72 65 74  ypeError('Secret
10540 20 6b 65 79 20 6d 69 73 73 69 6e 67 20 66 6f 72   key missing for
10550 20 6e 6f 6e 2d 73 74 72 69 6e 67 20 43 6f 6f 6b   non-string Cook
10560 69 65 2e 27 29 0a 0a 20 20 20 20 20 20 20 20 69  ie.')..        i
10570 66 20 6c 65 6e 28 76 61 6c 75 65 29 20 3e 20 34  f len(value) > 4
10580 30 39 36 3a 20 72 61 69 73 65 20 56 61 6c 75 65  096: raise Value
10590 45 72 72 6f 72 28 27 43 6f 6f 6b 69 65 20 76 61  Error('Cookie va
105a0 6c 75 65 20 74 6f 20 6c 6f 6e 67 2e 27 29 0a 20  lue to long.'). 
105b0 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 63 6f 6f         self._coo
105c0 6b 69 65 73 5b 6e 61 6d 65 5d 20 3d 20 76 61 6c  kies[name] = val
105d0 75 65 0a 0a 20 20 20 20 20 20 20 20 66 6f 72 20  ue..        for 
105e0 6b 65 79 2c 20 76 61 6c 75 65 20 69 6e 20 6f 70  key, value in op
105f0 74 69 6f 6e 73 2e 69 74 65 6d 73 28 29 3a 0a 20  tions.items():. 
10600 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6b 65             if ke
10610 79 20 3d 3d 20 27 6d 61 78 5f 61 67 65 27 3a 0a  y == 'max_age':.
10620 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10630 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 76 61  if isinstance(va
10640 6c 75 65 2c 20 74 69 6d 65 64 65 6c 74 61 29 3a  lue, timedelta):
10650 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
10660 20 20 20 20 20 76 61 6c 75 65 20 3d 20 76 61 6c       value = val
10670 75 65 2e 73 65 63 6f 6e 64 73 20 2b 20 76 61 6c  ue.seconds + val
10680 75 65 2e 64 61 79 73 20 2a 20 32 34 20 2a 20 33  ue.days * 24 * 3
10690 36 30 30 0a 20 20 20 20 20 20 20 20 20 20 20 20  600.            
106a0 69 66 20 6b 65 79 20 3d 3d 20 27 65 78 70 69 72  if key == 'expir
106b0 65 73 27 3a 0a 20 20 20 20 20 20 20 20 20 20 20  es':.           
106c0 20 20 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e       if isinstan
106d0 63 65 28 76 61 6c 75 65 2c 20 28 64 61 74 65 64  ce(value, (dated
106e0 61 74 65 2c 20 64 61 74 65 74 69 6d 65 29 29 3a  ate, datetime)):
106f0 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
10700 20 20 20 20 20 76 61 6c 75 65 20 3d 20 76 61 6c       value = val
10710 75 65 2e 74 69 6d 65 74 75 70 6c 65 28 29 0a 20  ue.timetuple(). 
10720 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
10730 6c 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 76  lif isinstance(v
10740 61 6c 75 65 2c 20 28 69 6e 74 2c 20 66 6c 6f 61  alue, (int, floa
10750 74 29 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  t)):.           
10760 20 20 20 20 20 20 20 20 20 76 61 6c 75 65 20 3d           value =
10770 20 74 69 6d 65 2e 67 6d 74 69 6d 65 28 76 61 6c   time.gmtime(val
10780 75 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ue).            
10790 20 20 20 20 76 61 6c 75 65 20 3d 20 74 69 6d 65      value = time
107a0 2e 73 74 72 66 74 69 6d 65 28 22 25 61 2c 20 25  .strftime("%a, %
107b0 64 20 25 62 20 25 59 20 25 48 3a 25 4d 3a 25 53  d %b %Y %H:%M:%S
107c0 20 47 4d 54 22 2c 20 76 61 6c 75 65 29 0a 20 20   GMT", value).  
107d0 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
107e0 63 6f 6f 6b 69 65 73 5b 6e 61 6d 65 5d 5b 6b 65  cookies[name][ke
107f0 79 2e 72 65 70 6c 61 63 65 28 27 5f 27 2c 20 27  y.replace('_', '
10800 2d 27 29 5d 20 3d 20 76 61 6c 75 65 0a 0a 20 20  -')] = value..  
10810 20 20 64 65 66 20 64 65 6c 65 74 65 5f 63 6f 6f    def delete_coo
10820 6b 69 65 28 73 65 6c 66 2c 20 6b 65 79 2c 20 2a  kie(self, key, *
10830 2a 6b 77 61 72 67 73 29 3a 0a 20 20 20 20 20 20  *kwargs):.      
10840 20 20 27 27 27 20 44 65 6c 65 74 65 20 61 20 63    ''' Delete a c
10850 6f 6f 6b 69 65 2e 20 42 65 20 73 75 72 65 20 74  ookie. Be sure t
10860 6f 20 75 73 65 20 74 68 65 20 73 61 6d 65 20 60  o use the same `
10870 64 6f 6d 61 69 6e 60 20 61 6e 64 20 60 70 61 74  domain` and `pat
10880 68 60 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  h`.            s
10890 65 74 74 69 6e 67 73 20 61 73 20 75 73 65 64 20  ettings as used 
108a0 74 6f 20 63 72 65 61 74 65 20 74 68 65 20 63 6f  to create the co
108b0 6f 6b 69 65 2e 20 27 27 27 0a 20 20 20 20 20 20  okie. '''.      
108c0 20 20 6b 77 61 72 67 73 5b 27 6d 61 78 5f 61 67    kwargs['max_ag
108d0 65 27 5d 20 3d 20 2d 31 0a 20 20 20 20 20 20 20  e'] = -1.       
108e0 20 6b 77 61 72 67 73 5b 27 65 78 70 69 72 65 73   kwargs['expires
108f0 27 5d 20 3d 20 30 0a 20 20 20 20 20 20 20 20 73  '] = 0.        s
10900 65 6c 66 2e 73 65 74 5f 63 6f 6f 6b 69 65 28 6b  elf.set_cookie(k
10910 65 79 2c 20 27 27 2c 20 2a 2a 6b 77 61 72 67 73  ey, '', **kwargs
10920 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 72 65 70  )..    def __rep
10930 72 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  r__(self):.     
10940 20 20 20 6f 75 74 20 3d 20 27 27 0a 20 20 20 20     out = ''.    
10950 20 20 20 20 66 6f 72 20 6e 61 6d 65 2c 20 76 61      for name, va
10960 6c 75 65 20 69 6e 20 73 65 6c 66 2e 68 65 61 64  lue in self.head
10970 65 72 6c 69 73 74 3a 0a 20 20 20 20 20 20 20 20  erlist:.        
10980 20 20 20 20 6f 75 74 20 2b 3d 20 27 25 73 3a 20      out += '%s: 
10990 25 73 5c 6e 27 20 25 20 28 6e 61 6d 65 2e 74 69  %s\n' % (name.ti
109a0 74 6c 65 28 29 2c 20 76 61 6c 75 65 2e 73 74 72  tle(), value.str
109b0 69 70 28 29 29 0a 20 20 20 20 20 20 20 20 72 65  ip()).        re
109c0 74 75 72 6e 20 6f 75 74 0a 0a 0a 64 65 66 20 6c  turn out...def l
109d0 6f 63 61 6c 5f 70 72 6f 70 65 72 74 79 28 6e 61  ocal_property(na
109e0 6d 65 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 69 66  me=None):.    if
109f0 20 6e 61 6d 65 3a 20 64 65 70 72 28 27 6c 6f 63   name: depr('loc
10a00 61 6c 5f 70 72 6f 70 65 72 74 79 28 29 20 69 73  al_property() is
10a10 20 64 65 70 72 65 63 61 74 65 64 20 61 6e 64 20   deprecated and 
10a20 77 69 6c 6c 20 62 65 20 72 65 6d 6f 76 65 64 2e  will be removed.
10a30 27 29 20 23 30 2e 31 32 0a 20 20 20 20 6c 73 20  ') #0.12.    ls 
10a40 3d 20 74 68 72 65 61 64 69 6e 67 2e 6c 6f 63 61  = threading.loca
10a50 6c 28 29 0a 20 20 20 20 64 65 66 20 66 67 65 74  l().    def fget
10a60 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20  (self):.        
10a70 74 72 79 3a 20 72 65 74 75 72 6e 20 6c 73 2e 76  try: return ls.v
10a80 61 72 0a 20 20 20 20 20 20 20 20 65 78 63 65 70  ar.        excep
10a90 74 20 41 74 74 72 69 62 75 74 65 45 72 72 6f 72  t AttributeError
10aa0 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 61  :.            ra
10ab0 69 73 65 20 52 75 6e 74 69 6d 65 45 72 72 6f 72  ise RuntimeError
10ac0 28 22 52 65 71 75 65 73 74 20 63 6f 6e 74 65 78  ("Request contex
10ad0 74 20 6e 6f 74 20 69 6e 69 74 69 61 6c 69 7a 65  t not initialize
10ae0 64 2e 22 29 0a 20 20 20 20 64 65 66 20 66 73 65  d.").    def fse
10af0 74 28 73 65 6c 66 2c 20 76 61 6c 75 65 29 3a 20  t(self, value): 
10b00 6c 73 2e 76 61 72 20 3d 20 76 61 6c 75 65 0a 20  ls.var = value. 
10b10 20 20 20 64 65 66 20 66 64 65 6c 28 73 65 6c 66     def fdel(self
10b20 29 3a 20 64 65 6c 20 6c 73 2e 76 61 72 0a 20 20  ): del ls.var.  
10b30 20 20 72 65 74 75 72 6e 20 70 72 6f 70 65 72 74    return propert
10b40 79 28 66 67 65 74 2c 20 66 73 65 74 2c 20 66 64  y(fget, fset, fd
10b50 65 6c 2c 20 27 54 68 72 65 61 64 2d 6c 6f 63 61  el, 'Thread-loca
10b60 6c 20 70 72 6f 70 65 72 74 79 27 29 0a 0a 0a 63  l property')...c
10b70 6c 61 73 73 20 4c 6f 63 61 6c 52 65 71 75 65 73  lass LocalReques
10b80 74 28 42 61 73 65 52 65 71 75 65 73 74 29 3a 0a  t(BaseRequest):.
10b90 20 20 20 20 27 27 27 20 41 20 74 68 72 65 61 64      ''' A thread
10ba0 2d 6c 6f 63 61 6c 20 73 75 62 63 6c 61 73 73 20  -local subclass 
10bb0 6f 66 20 3a 63 6c 61 73 73 3a 60 42 61 73 65 52  of :class:`BaseR
10bc0 65 71 75 65 73 74 60 20 77 69 74 68 20 61 20 64  equest` with a d
10bd0 69 66 66 65 72 65 6e 74 0a 20 20 20 20 20 20 20  ifferent.       
10be0 20 73 65 74 20 6f 66 20 61 74 74 72 69 62 75 74   set of attribut
10bf0 65 73 20 66 6f 72 20 65 61 63 68 20 74 68 72 65  es for each thre
10c00 61 64 2e 20 54 68 65 72 65 20 69 73 20 75 73 75  ad. There is usu
10c10 61 6c 6c 79 20 6f 6e 6c 79 20 6f 6e 65 20 67 6c  ally only one gl
10c20 6f 62 61 6c 0a 20 20 20 20 20 20 20 20 69 6e 73  obal.        ins
10c30 74 61 6e 63 65 20 6f 66 20 74 68 69 73 20 63 6c  tance of this cl
10c40 61 73 73 20 28 3a 64 61 74 61 3a 60 72 65 71 75  ass (:data:`requ
10c50 65 73 74 60 29 2e 20 49 66 20 61 63 63 65 73 73  est`). If access
10c60 65 64 20 64 75 72 69 6e 67 20 61 0a 20 20 20 20  ed during a.    
10c70 20 20 20 20 72 65 71 75 65 73 74 2f 72 65 73 70      request/resp
10c80 6f 6e 73 65 20 63 79 63 6c 65 2c 20 74 68 69 73  onse cycle, this
10c90 20 69 6e 73 74 61 6e 63 65 20 61 6c 77 61 79 73   instance always
10ca0 20 72 65 66 65 72 73 20 74 6f 20 74 68 65 20 2a   refers to the *
10cb0 63 75 72 72 65 6e 74 2a 0a 20 20 20 20 20 20 20  current*.       
10cc0 20 72 65 71 75 65 73 74 20 28 65 76 65 6e 20 6f   request (even o
10cd0 6e 20 61 20 6d 75 6c 74 69 74 68 72 65 61 64 65  n a multithreade
10ce0 64 20 73 65 72 76 65 72 29 2e 20 27 27 27 0a 20  d server). '''. 
10cf0 20 20 20 62 69 6e 64 20 3d 20 42 61 73 65 52 65     bind = BaseRe
10d00 71 75 65 73 74 2e 5f 5f 69 6e 69 74 5f 5f 0a 20  quest.__init__. 
10d10 20 20 20 65 6e 76 69 72 6f 6e 20 3d 20 6c 6f 63     environ = loc
10d20 61 6c 5f 70 72 6f 70 65 72 74 79 28 29 0a 0a 0a  al_property()...
10d30 63 6c 61 73 73 20 4c 6f 63 61 6c 52 65 73 70 6f  class LocalRespo
10d40 6e 73 65 28 42 61 73 65 52 65 73 70 6f 6e 73 65  nse(BaseResponse
10d50 29 3a 0a 20 20 20 20 27 27 27 20 41 20 74 68 72  ):.    ''' A thr
10d60 65 61 64 2d 6c 6f 63 61 6c 20 73 75 62 63 6c 61  ead-local subcla
10d70 73 73 20 6f 66 20 3a 63 6c 61 73 73 3a 60 42 61  ss of :class:`Ba
10d80 73 65 52 65 73 70 6f 6e 73 65 60 20 77 69 74 68  seResponse` with
10d90 20 61 20 64 69 66 66 65 72 65 6e 74 0a 20 20 20   a different.   
10da0 20 20 20 20 20 73 65 74 20 6f 66 20 61 74 74 72       set of attr
10db0 69 62 75 74 65 73 20 66 6f 72 20 65 61 63 68 20  ibutes for each 
10dc0 74 68 72 65 61 64 2e 20 54 68 65 72 65 20 69 73  thread. There is
10dd0 20 75 73 75 61 6c 6c 79 20 6f 6e 6c 79 20 6f 6e   usually only on
10de0 65 20 67 6c 6f 62 61 6c 0a 20 20 20 20 20 20 20  e global.       
10df0 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 69   instance of thi
10e00 73 20 63 6c 61 73 73 20 28 3a 64 61 74 61 3a 60  s class (:data:`
10e10 72 65 73 70 6f 6e 73 65 60 29 2e 20 49 74 73 20  response`). Its 
10e20 61 74 74 72 69 62 75 74 65 73 20 61 72 65 20 75  attributes are u
10e30 73 65 64 0a 20 20 20 20 20 20 20 20 74 6f 20 62  sed.        to b
10e40 75 69 6c 64 20 74 68 65 20 48 54 54 50 20 72 65  uild the HTTP re
10e50 73 70 6f 6e 73 65 20 61 74 20 74 68 65 20 65 6e  sponse at the en
10e60 64 20 6f 66 20 74 68 65 20 72 65 71 75 65 73 74  d of the request
10e70 2f 72 65 73 70 6f 6e 73 65 20 63 79 63 6c 65 2e  /response cycle.
10e80 0a 20 20 20 20 27 27 27 0a 20 20 20 20 62 69 6e  .    '''.    bin
10e90 64 20 3d 20 42 61 73 65 52 65 73 70 6f 6e 73 65  d = BaseResponse
10ea0 2e 5f 5f 69 6e 69 74 5f 5f 0a 20 20 20 20 5f 73  .__init__.    _s
10eb0 74 61 74 75 73 5f 6c 69 6e 65 20 3d 20 6c 6f 63  tatus_line = loc
10ec0 61 6c 5f 70 72 6f 70 65 72 74 79 28 29 0a 20 20  al_property().  
10ed0 20 20 5f 73 74 61 74 75 73 5f 63 6f 64 65 20 3d    _status_code =
10ee0 20 6c 6f 63 61 6c 5f 70 72 6f 70 65 72 74 79 28   local_property(
10ef0 29 0a 20 20 20 20 5f 63 6f 6f 6b 69 65 73 20 20  ).    _cookies  
10f00 20 20 20 3d 20 6c 6f 63 61 6c 5f 70 72 6f 70 65     = local_prope
10f10 72 74 79 28 29 0a 20 20 20 20 5f 68 65 61 64 65  rty().    _heade
10f20 72 73 20 20 20 20 20 3d 20 6c 6f 63 61 6c 5f 70  rs     = local_p
10f30 72 6f 70 65 72 74 79 28 29 0a 20 20 20 20 62 6f  roperty().    bo
10f40 64 79 20 20 20 20 20 20 20 20 20 3d 20 6c 6f 63  dy         = loc
10f50 61 6c 5f 70 72 6f 70 65 72 74 79 28 29 0a 0a 0a  al_property()...
10f60 52 65 71 75 65 73 74 20 3d 20 42 61 73 65 52 65  Request = BaseRe
10f70 71 75 65 73 74 0a 52 65 73 70 6f 6e 73 65 20 3d  quest.Response =
10f80 20 42 61 73 65 52 65 73 70 6f 6e 73 65 0a 0a 0a   BaseResponse...
10f90 63 6c 61 73 73 20 48 54 54 50 52 65 73 70 6f 6e  class HTTPRespon
10fa0 73 65 28 52 65 73 70 6f 6e 73 65 2c 20 42 6f 74  se(Response, Bot
10fb0 74 6c 65 45 78 63 65 70 74 69 6f 6e 29 3a 0a 20  tleException):. 
10fc0 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 28     def __init__(
10fd0 73 65 6c 66 2c 20 62 6f 64 79 3d 27 27 2c 20 73  self, body='', s
10fe0 74 61 74 75 73 3d 4e 6f 6e 65 2c 20 68 65 61 64  tatus=None, head
10ff0 65 72 73 3d 4e 6f 6e 65 2c 20 2a 2a 6d 6f 72 65  ers=None, **more
11000 5f 68 65 61 64 65 72 73 29 3a 0a 20 20 20 20 20  _headers):.     
11010 20 20 20 73 75 70 65 72 28 48 54 54 50 52 65 73     super(HTTPRes
11020 70 6f 6e 73 65 2c 20 73 65 6c 66 29 2e 5f 5f 69  ponse, self).__i
11030 6e 69 74 5f 5f 28 62 6f 64 79 2c 20 73 74 61 74  nit__(body, stat
11040 75 73 2c 20 68 65 61 64 65 72 73 2c 20 2a 2a 6d  us, headers, **m
11050 6f 72 65 5f 68 65 61 64 65 72 73 29 0a 0a 20 20  ore_headers)..  
11060 20 20 64 65 66 20 61 70 70 6c 79 28 73 65 6c 66    def apply(self
11070 2c 20 72 65 73 70 6f 6e 73 65 29 3a 0a 20 20 20  , response):.   
11080 20 20 20 20 20 72 65 73 70 6f 6e 73 65 2e 5f 73       response._s
11090 74 61 74 75 73 5f 63 6f 64 65 20 3d 20 73 65 6c  tatus_code = sel
110a0 66 2e 5f 73 74 61 74 75 73 5f 63 6f 64 65 0a 20  f._status_code. 
110b0 20 20 20 20 20 20 20 72 65 73 70 6f 6e 73 65 2e         response.
110c0 5f 73 74 61 74 75 73 5f 6c 69 6e 65 20 3d 20 73  _status_line = s
110d0 65 6c 66 2e 5f 73 74 61 74 75 73 5f 6c 69 6e 65  elf._status_line
110e0 0a 20 20 20 20 20 20 20 20 72 65 73 70 6f 6e 73  .        respons
110f0 65 2e 5f 68 65 61 64 65 72 73 20 3d 20 73 65 6c  e._headers = sel
11100 66 2e 5f 68 65 61 64 65 72 73 0a 20 20 20 20 20  f._headers.     
11110 20 20 20 72 65 73 70 6f 6e 73 65 2e 5f 63 6f 6f     response._coo
11120 6b 69 65 73 20 3d 20 73 65 6c 66 2e 5f 63 6f 6f  kies = self._coo
11130 6b 69 65 73 0a 20 20 20 20 20 20 20 20 72 65 73  kies.        res
11140 70 6f 6e 73 65 2e 62 6f 64 79 20 3d 20 73 65 6c  ponse.body = sel
11150 66 2e 62 6f 64 79 0a 0a 0a 63 6c 61 73 73 20 48  f.body...class H
11160 54 54 50 45 72 72 6f 72 28 48 54 54 50 52 65 73  TTPError(HTTPRes
11170 70 6f 6e 73 65 29 3a 0a 20 20 20 20 64 65 66 61  ponse):.    defa
11180 75 6c 74 5f 73 74 61 74 75 73 20 3d 20 35 30 30  ult_status = 500
11190 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f  .    def __init_
111a0 5f 28 73 65 6c 66 2c 20 73 74 61 74 75 73 3d 4e  _(self, status=N
111b0 6f 6e 65 2c 20 62 6f 64 79 3d 4e 6f 6e 65 2c 20  one, body=None, 
111c0 65 78 63 65 70 74 69 6f 6e 3d 4e 6f 6e 65 2c 20  exception=None, 
111d0 74 72 61 63 65 62 61 63 6b 3d 4e 6f 6e 65 2c 0a  traceback=None,.
111e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
111f0 20 2a 2a 6f 70 74 69 6f 6e 73 29 3a 0a 20 20 20   **options):.   
11200 20 20 20 20 20 73 65 6c 66 2e 65 78 63 65 70 74       self.except
11210 69 6f 6e 20 3d 20 65 78 63 65 70 74 69 6f 6e 0a  ion = exception.
11220 20 20 20 20 20 20 20 20 73 65 6c 66 2e 74 72 61          self.tra
11230 63 65 62 61 63 6b 20 3d 20 74 72 61 63 65 62 61  ceback = traceba
11240 63 6b 0a 20 20 20 20 20 20 20 20 73 75 70 65 72  ck.        super
11250 28 48 54 54 50 45 72 72 6f 72 2c 20 73 65 6c 66  (HTTPError, self
11260 29 2e 5f 5f 69 6e 69 74 5f 5f 28 62 6f 64 79 2c  ).__init__(body,
11270 20 73 74 61 74 75 73 2c 20 2a 2a 6f 70 74 69 6f   status, **optio
11280 6e 73 29 0a 0a 0a 0a 0a 0a 23 23 23 23 23 23 23  ns)......#######
11290 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
112a0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
112b0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
112c0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
112d0 23 23 23 23 23 23 23 23 0a 23 20 50 6c 75 67 69  ########.# Plugi
112e0 6e 73 20 23 23 23 23 23 23 23 23 23 23 23 23 23  ns #############
112f0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11300 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11310 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11320 23 23 23 23 23 23 23 23 23 0a 23 23 23 23 23 23  #########.######
11330 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11340 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11350 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11360 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11370 23 23 23 23 23 23 23 23 23 0a 0a 63 6c 61 73 73  #########..class
11380 20 50 6c 75 67 69 6e 45 72 72 6f 72 28 42 6f 74   PluginError(Bot
11390 74 6c 65 45 78 63 65 70 74 69 6f 6e 29 3a 20 70  tleException): p
113a0 61 73 73 0a 0a 0a 63 6c 61 73 73 20 4a 53 4f 4e  ass...class JSON
113b0 50 6c 75 67 69 6e 28 6f 62 6a 65 63 74 29 3a 0a  Plugin(object):.
113c0 20 20 20 20 6e 61 6d 65 20 3d 20 27 6a 73 6f 6e      name = 'json
113d0 27 0a 20 20 20 20 61 70 69 20 20 3d 20 32 0a 0a  '.    api  = 2..
113e0 20 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f      def __init__
113f0 28 73 65 6c 66 2c 20 6a 73 6f 6e 5f 64 75 6d 70  (self, json_dump
11400 73 3d 6a 73 6f 6e 5f 64 75 6d 70 73 29 3a 0a 20  s=json_dumps):. 
11410 20 20 20 20 20 20 20 73 65 6c 66 2e 6a 73 6f 6e         self.json
11420 5f 64 75 6d 70 73 20 3d 20 6a 73 6f 6e 5f 64 75  _dumps = json_du
11430 6d 70 73 0a 0a 20 20 20 20 64 65 66 20 61 70 70  mps..    def app
11440 6c 79 28 73 65 6c 66 2c 20 63 61 6c 6c 62 61 63  ly(self, callbac
11450 6b 2c 20 72 6f 75 74 65 29 3a 0a 20 20 20 20 20  k, route):.     
11460 20 20 20 64 75 6d 70 73 20 3d 20 73 65 6c 66 2e     dumps = self.
11470 6a 73 6f 6e 5f 64 75 6d 70 73 0a 20 20 20 20 20  json_dumps.     
11480 20 20 20 69 66 20 6e 6f 74 20 64 75 6d 70 73 3a     if not dumps:
11490 20 72 65 74 75 72 6e 20 63 61 6c 6c 62 61 63 6b   return callback
114a0 0a 20 20 20 20 20 20 20 20 64 65 66 20 77 72 61  .        def wra
114b0 70 70 65 72 28 2a 61 2c 20 2a 2a 6b 61 29 3a 0a  pper(*a, **ka):.
114c0 20 20 20 20 20 20 20 20 20 20 20 20 74 72 79 3a              try:
114d0 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
114e0 20 72 76 20 3d 20 63 61 6c 6c 62 61 63 6b 28 2a   rv = callback(*
114f0 61 2c 20 2a 2a 6b 61 29 0a 20 20 20 20 20 20 20  a, **ka).       
11500 20 20 20 20 20 65 78 63 65 70 74 20 48 54 54 50       except HTTP
11510 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20  Error:.         
11520 20 20 20 20 20 20 20 72 76 20 3d 20 5f 65 28 29         rv = _e()
11530 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ..            if
11540 20 69 73 69 6e 73 74 61 6e 63 65 28 72 76 2c 20   isinstance(rv, 
11550 64 69 63 74 29 3a 0a 20 20 20 20 20 20 20 20 20  dict):.         
11560 20 20 20 20 20 20 20 23 41 74 74 65 6d 70 74 20         #Attempt 
11570 74 6f 20 73 65 72 69 61 6c 69 7a 65 2c 20 72 61  to serialize, ra
11580 69 73 65 73 20 65 78 63 65 70 74 69 6f 6e 20 6f  ises exception o
11590 6e 20 66 61 69 6c 75 72 65 0a 20 20 20 20 20 20  n failure.      
115a0 20 20 20 20 20 20 20 20 20 20 6a 73 6f 6e 5f 72            json_r
115b0 65 73 70 6f 6e 73 65 20 3d 20 64 75 6d 70 73 28  esponse = dumps(
115c0 72 76 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  rv).            
115d0 20 20 20 20 23 53 65 74 20 63 6f 6e 74 65 6e 74      #Set content
115e0 20 74 79 70 65 20 6f 6e 6c 79 20 69 66 20 73 65   type only if se
115f0 72 69 61 6c 69 7a 61 74 69 6f 6e 20 73 75 63 63  rialization succ
11600 65 73 66 75 6c 0a 20 20 20 20 20 20 20 20 20 20  esful.          
11610 20 20 20 20 20 20 72 65 73 70 6f 6e 73 65 2e 63        response.c
11620 6f 6e 74 65 6e 74 5f 74 79 70 65 20 3d 20 27 61  ontent_type = 'a
11630 70 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 27  pplication/json'
11640 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
11650 20 72 65 74 75 72 6e 20 6a 73 6f 6e 5f 72 65 73   return json_res
11660 70 6f 6e 73 65 0a 20 20 20 20 20 20 20 20 20 20  ponse.          
11670 20 20 65 6c 69 66 20 69 73 69 6e 73 74 61 6e 63    elif isinstanc
11680 65 28 72 76 2c 20 48 54 54 50 52 65 73 70 6f 6e  e(rv, HTTPRespon
11690 73 65 29 20 61 6e 64 20 69 73 69 6e 73 74 61 6e  se) and isinstan
116a0 63 65 28 72 76 2e 62 6f 64 79 2c 20 64 69 63 74  ce(rv.body, dict
116b0 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
116c0 20 20 20 72 76 2e 62 6f 64 79 20 3d 20 64 75 6d     rv.body = dum
116d0 70 73 28 72 76 2e 62 6f 64 79 29 0a 20 20 20 20  ps(rv.body).    
116e0 20 20 20 20 20 20 20 20 20 20 20 20 72 76 2e 63              rv.c
116f0 6f 6e 74 65 6e 74 5f 74 79 70 65 20 3d 20 27 61  ontent_type = 'a
11700 70 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 27  pplication/json'
11710 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
11720 75 72 6e 20 72 76 0a 0a 20 20 20 20 20 20 20 20  urn rv..        
11730 72 65 74 75 72 6e 20 77 72 61 70 70 65 72 0a 0a  return wrapper..
11740 0a 63 6c 61 73 73 20 54 65 6d 70 6c 61 74 65 50  .class TemplateP
11750 6c 75 67 69 6e 28 6f 62 6a 65 63 74 29 3a 0a 20  lugin(object):. 
11760 20 20 20 27 27 27 20 54 68 69 73 20 70 6c 75 67     ''' This plug
11770 69 6e 20 61 70 70 6c 69 65 73 20 74 68 65 20 3a  in applies the :
11780 66 75 6e 63 3a 60 76 69 65 77 60 20 64 65 63 6f  func:`view` deco
11790 72 61 74 6f 72 20 74 6f 20 61 6c 6c 20 72 6f 75  rator to all rou
117a0 74 65 73 20 77 69 74 68 20 61 0a 20 20 20 20 20  tes with a.     
117b0 20 20 20 60 74 65 6d 70 6c 61 74 65 60 20 63 6f     `template` co
117c0 6e 66 69 67 20 70 61 72 61 6d 65 74 65 72 2e 20  nfig parameter. 
117d0 49 66 20 74 68 65 20 70 61 72 61 6d 65 74 65 72  If the parameter
117e0 20 69 73 20 61 20 74 75 70 6c 65 2c 20 74 68 65   is a tuple, the
117f0 20 73 65 63 6f 6e 64 0a 20 20 20 20 20 20 20 20   second.        
11800 65 6c 65 6d 65 6e 74 20 6d 75 73 74 20 62 65 20  element must be 
11810 61 20 64 69 63 74 20 77 69 74 68 20 61 64 64 69  a dict with addi
11820 74 69 6f 6e 61 6c 20 6f 70 74 69 6f 6e 73 20 28  tional options (
11830 65 2e 67 2e 20 60 74 65 6d 70 6c 61 74 65 5f 65  e.g. `template_e
11840 6e 67 69 6e 65 60 29 0a 20 20 20 20 20 20 20 20  ngine`).        
11850 6f 72 20 64 65 66 61 75 6c 74 20 76 61 72 69 61  or default varia
11860 62 6c 65 73 20 66 6f 72 20 74 68 65 20 74 65 6d  bles for the tem
11870 70 6c 61 74 65 2e 20 27 27 27 0a 20 20 20 20 6e  plate. '''.    n
11880 61 6d 65 20 3d 20 27 74 65 6d 70 6c 61 74 65 27  ame = 'template'
11890 0a 20 20 20 20 61 70 69 20 20 3d 20 32 0a 0a 20  .    api  = 2.. 
118a0 20 20 20 64 65 66 20 61 70 70 6c 79 28 73 65 6c     def apply(sel
118b0 66 2c 20 63 61 6c 6c 62 61 63 6b 2c 20 72 6f 75  f, callback, rou
118c0 74 65 29 3a 0a 20 20 20 20 20 20 20 20 63 6f 6e  te):.        con
118d0 66 20 3d 20 72 6f 75 74 65 2e 63 6f 6e 66 69 67  f = route.config
118e0 2e 67 65 74 28 27 74 65 6d 70 6c 61 74 65 27 29  .get('template')
118f0 0a 20 20 20 20 20 20 20 20 69 66 20 69 73 69 6e  .        if isin
11900 73 74 61 6e 63 65 28 63 6f 6e 66 2c 20 28 74 75  stance(conf, (tu
11910 70 6c 65 2c 20 6c 69 73 74 29 29 20 61 6e 64 20  ple, list)) and 
11920 6c 65 6e 28 63 6f 6e 66 29 20 3d 3d 20 32 3a 0a  len(conf) == 2:.
11930 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
11940 72 6e 20 76 69 65 77 28 63 6f 6e 66 5b 30 5d 2c  rn view(conf[0],
11950 20 2a 2a 63 6f 6e 66 5b 31 5d 29 28 63 61 6c 6c   **conf[1])(call
11960 62 61 63 6b 29 0a 20 20 20 20 20 20 20 20 65 6c  back).        el
11970 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 63 6f  if isinstance(co
11980 6e 66 2c 20 73 74 72 29 3a 0a 20 20 20 20 20 20  nf, str):.      
11990 20 20 20 20 20 20 72 65 74 75 72 6e 20 76 69 65        return vie
119a0 77 28 63 6f 6e 66 29 28 63 61 6c 6c 62 61 63 6b  w(conf)(callback
119b0 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  ).        else:.
119c0 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
119d0 72 6e 20 63 61 6c 6c 62 61 63 6b 0a 0a 0a 23 3a  rn callback...#:
119e0 20 4e 6f 74 20 61 20 70 6c 75 67 69 6e 2c 20 62   Not a plugin, b
119f0 75 74 20 70 61 72 74 20 6f 66 20 74 68 65 20 70  ut part of the p
11a00 6c 75 67 69 6e 20 41 50 49 2e 20 54 4f 44 4f 3a  lugin API. TODO:
11a10 20 46 69 6e 64 20 61 20 62 65 74 74 65 72 20 70   Find a better p
11a20 6c 61 63 65 2e 0a 63 6c 61 73 73 20 5f 49 6d 70  lace..class _Imp
11a30 6f 72 74 52 65 64 69 72 65 63 74 28 6f 62 6a 65  ortRedirect(obje
11a40 63 74 29 3a 0a 20 20 20 20 64 65 66 20 5f 5f 69  ct):.    def __i
11a50 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 6e 61 6d 65  nit__(self, name
11a60 2c 20 69 6d 70 6d 61 73 6b 29 3a 0a 20 20 20 20  , impmask):.    
11a70 20 20 20 20 27 27 27 20 43 72 65 61 74 65 20 61      ''' Create a
11a80 20 76 69 72 74 75 61 6c 20 70 61 63 6b 61 67 65   virtual package
11a90 20 74 68 61 74 20 72 65 64 69 72 65 63 74 73 20   that redirects 
11aa0 69 6d 70 6f 72 74 73 20 28 73 65 65 20 50 45 50  imports (see PEP
11ab0 20 33 30 32 29 2e 20 27 27 27 0a 20 20 20 20 20   302). '''.     
11ac0 20 20 20 73 65 6c 66 2e 6e 61 6d 65 20 3d 20 6e     self.name = n
11ad0 61 6d 65 0a 20 20 20 20 20 20 20 20 73 65 6c 66  ame.        self
11ae0 2e 69 6d 70 6d 61 73 6b 20 3d 20 69 6d 70 6d 61  .impmask = impma
11af0 73 6b 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  sk.        self.
11b00 6d 6f 64 75 6c 65 20 3d 20 73 79 73 2e 6d 6f 64  module = sys.mod
11b10 75 6c 65 73 2e 73 65 74 64 65 66 61 75 6c 74 28  ules.setdefault(
11b20 6e 61 6d 65 2c 20 69 6d 70 2e 6e 65 77 5f 6d 6f  name, imp.new_mo
11b30 64 75 6c 65 28 6e 61 6d 65 29 29 0a 20 20 20 20  dule(name)).    
11b40 20 20 20 20 73 65 6c 66 2e 6d 6f 64 75 6c 65 2e      self.module.
11b50 5f 5f 64 69 63 74 5f 5f 2e 75 70 64 61 74 65 28  __dict__.update(
11b60 7b 27 5f 5f 66 69 6c 65 5f 5f 27 3a 20 5f 5f 66  {'__file__': __f
11b70 69 6c 65 5f 5f 2c 20 27 5f 5f 70 61 74 68 5f 5f  ile__, '__path__
11b80 27 3a 20 5b 5d 2c 0a 20 20 20 20 20 20 20 20 20  ': [],.         
11b90 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11ba0 20 20 20 20 20 20 20 20 20 20 20 27 5f 5f 61 6c             '__al
11bb0 6c 5f 5f 27 3a 20 5b 5d 2c 20 27 5f 5f 6c 6f 61  l__': [], '__loa
11bc0 64 65 72 5f 5f 27 3a 20 73 65 6c 66 7d 29 0a 20  der__': self}). 
11bd0 20 20 20 20 20 20 20 73 79 73 2e 6d 65 74 61 5f         sys.meta_
11be0 70 61 74 68 2e 61 70 70 65 6e 64 28 73 65 6c 66  path.append(self
11bf0 29 0a 0a 20 20 20 20 64 65 66 20 66 69 6e 64 5f  )..    def find_
11c00 6d 6f 64 75 6c 65 28 73 65 6c 66 2c 20 66 75 6c  module(self, ful
11c10 6c 6e 61 6d 65 2c 20 70 61 74 68 3d 4e 6f 6e 65  lname, path=None
11c20 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 27 2e  ):.        if '.
11c30 27 20 6e 6f 74 20 69 6e 20 66 75 6c 6c 6e 61 6d  ' not in fullnam
11c40 65 3a 20 72 65 74 75 72 6e 0a 20 20 20 20 20 20  e: return.      
11c50 20 20 70 61 63 6b 6e 61 6d 65 20 3d 20 66 75 6c    packname = ful
11c60 6c 6e 61 6d 65 2e 72 73 70 6c 69 74 28 27 2e 27  lname.rsplit('.'
11c70 2c 20 31 29 5b 30 5d 0a 20 20 20 20 20 20 20 20  , 1)[0].        
11c80 69 66 20 70 61 63 6b 6e 61 6d 65 20 21 3d 20 73  if packname != s
11c90 65 6c 66 2e 6e 61 6d 65 3a 20 72 65 74 75 72 6e  elf.name: return
11ca0 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
11cb0 73 65 6c 66 0a 0a 20 20 20 20 64 65 66 20 6c 6f  self..    def lo
11cc0 61 64 5f 6d 6f 64 75 6c 65 28 73 65 6c 66 2c 20  ad_module(self, 
11cd0 66 75 6c 6c 6e 61 6d 65 29 3a 0a 20 20 20 20 20  fullname):.     
11ce0 20 20 20 69 66 20 66 75 6c 6c 6e 61 6d 65 20 69     if fullname i
11cf0 6e 20 73 79 73 2e 6d 6f 64 75 6c 65 73 3a 20 72  n sys.modules: r
11d00 65 74 75 72 6e 20 73 79 73 2e 6d 6f 64 75 6c 65  eturn sys.module
11d10 73 5b 66 75 6c 6c 6e 61 6d 65 5d 0a 20 20 20 20  s[fullname].    
11d20 20 20 20 20 6d 6f 64 6e 61 6d 65 20 3d 20 66 75      modname = fu
11d30 6c 6c 6e 61 6d 65 2e 72 73 70 6c 69 74 28 27 2e  llname.rsplit('.
11d40 27 2c 20 31 29 5b 31 5d 0a 20 20 20 20 20 20 20  ', 1)[1].       
11d50 20 72 65 61 6c 6e 61 6d 65 20 3d 20 73 65 6c 66   realname = self
11d60 2e 69 6d 70 6d 61 73 6b 20 25 20 6d 6f 64 6e 61  .impmask % modna
11d70 6d 65 0a 20 20 20 20 20 20 20 20 5f 5f 69 6d 70  me.        __imp
11d80 6f 72 74 5f 5f 28 72 65 61 6c 6e 61 6d 65 29 0a  ort__(realname).
11d90 20 20 20 20 20 20 20 20 6d 6f 64 75 6c 65 20 3d          module =
11da0 20 73 79 73 2e 6d 6f 64 75 6c 65 73 5b 66 75 6c   sys.modules[ful
11db0 6c 6e 61 6d 65 5d 20 3d 20 73 79 73 2e 6d 6f 64  lname] = sys.mod
11dc0 75 6c 65 73 5b 72 65 61 6c 6e 61 6d 65 5d 0a 20  ules[realname]. 
11dd0 20 20 20 20 20 20 20 73 65 74 61 74 74 72 28 73         setattr(s
11de0 65 6c 66 2e 6d 6f 64 75 6c 65 2c 20 6d 6f 64 6e  elf.module, modn
11df0 61 6d 65 2c 20 6d 6f 64 75 6c 65 29 0a 20 20 20  ame, module).   
11e00 20 20 20 20 20 6d 6f 64 75 6c 65 2e 5f 5f 6c 6f       module.__lo
11e10 61 64 65 72 5f 5f 20 3d 20 73 65 6c 66 0a 20 20  ader__ = self.  
11e20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6d 6f 64        return mod
11e30 75 6c 65 0a 0a 0a 0a 0a 0a 0a 23 23 23 23 23 23  ule.......######
11e40 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11e50 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11e60 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11e70 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11e80 23 23 23 23 23 23 23 23 23 0a 23 20 43 6f 6d 6d  #########.# Comm
11e90 6f 6e 20 55 74 69 6c 69 74 69 65 73 20 23 23 23  on Utilities ###
11ea0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11eb0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11ec0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11ed0 23 23 23 23 23 23 23 23 23 23 0a 23 23 23 23 23  ##########.#####
11ee0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11ef0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11f00 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11f10 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
11f20 23 23 23 23 23 23 23 23 23 23 0a 0a 0a 63 6c 61  ##########...cla
11f30 73 73 20 4d 75 6c 74 69 44 69 63 74 28 44 69 63  ss MultiDict(Dic
11f40 74 4d 69 78 69 6e 29 3a 0a 20 20 20 20 22 22 22  tMixin):.    """
11f50 20 54 68 69 73 20 64 69 63 74 20 73 74 6f 72 65   This dict store
11f60 73 20 6d 75 6c 74 69 70 6c 65 20 76 61 6c 75 65  s multiple value
11f70 73 20 70 65 72 20 6b 65 79 2c 20 62 75 74 20 62  s per key, but b
11f80 65 68 61 76 65 73 20 65 78 61 63 74 6c 79 20 6c  ehaves exactly l
11f90 69 6b 65 20 61 0a 20 20 20 20 20 20 20 20 6e 6f  ike a.        no
11fa0 72 6d 61 6c 20 64 69 63 74 20 69 6e 20 74 68 61  rmal dict in tha
11fb0 74 20 69 74 20 72 65 74 75 72 6e 73 20 6f 6e 6c  t it returns onl
11fc0 79 20 74 68 65 20 6e 65 77 65 73 74 20 76 61 6c  y the newest val
11fd0 75 65 20 66 6f 72 20 61 6e 79 20 67 69 76 65 6e  ue for any given
11fe0 20 6b 65 79 2e 0a 20 20 20 20 20 20 20 20 54 68   key..        Th
11ff0 65 72 65 20 61 72 65 20 73 70 65 63 69 61 6c 20  ere are special 
12000 6d 65 74 68 6f 64 73 20 61 76 61 69 6c 61 62 6c  methods availabl
12010 65 20 74 6f 20 61 63 63 65 73 73 20 74 68 65 20  e to access the 
12020 66 75 6c 6c 20 6c 69 73 74 20 6f 66 20 76 61 6c  full list of val
12030 75 65 73 2e 0a 20 20 20 20 22 22 22 0a 0a 20 20  ues..    """..  
12040 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 28 73    def __init__(s
12050 65 6c 66 2c 20 2a 61 2c 20 2a 2a 6b 29 3a 0a 20  elf, *a, **k):. 
12060 20 20 20 20 20 20 20 73 65 6c 66 2e 64 69 63 74         self.dict
12070 20 3d 20 64 69 63 74 28 28 6b 2c 20 5b 76 5d 29   = dict((k, [v])
12080 20 66 6f 72 20 28 6b 2c 20 76 29 20 69 6e 20 64   for (k, v) in d
12090 69 63 74 28 2a 61 2c 20 2a 2a 6b 29 2e 69 74 65  ict(*a, **k).ite
120a0 6d 73 28 29 29 0a 0a 20 20 20 20 64 65 66 20 5f  ms())..    def _
120b0 5f 6c 65 6e 5f 5f 28 73 65 6c 66 29 3a 20 72 65  _len__(self): re
120c0 74 75 72 6e 20 6c 65 6e 28 73 65 6c 66 2e 64 69  turn len(self.di
120d0 63 74 29 0a 20 20 20 20 64 65 66 20 5f 5f 69 74  ct).    def __it
120e0 65 72 5f 5f 28 73 65 6c 66 29 3a 20 72 65 74 75  er__(self): retu
120f0 72 6e 20 69 74 65 72 28 73 65 6c 66 2e 64 69 63  rn iter(self.dic
12100 74 29 0a 20 20 20 20 64 65 66 20 5f 5f 63 6f 6e  t).    def __con
12110 74 61 69 6e 73 5f 5f 28 73 65 6c 66 2c 20 6b 65  tains__(self, ke
12120 79 29 3a 20 72 65 74 75 72 6e 20 6b 65 79 20 69  y): return key i
12130 6e 20 73 65 6c 66 2e 64 69 63 74 0a 20 20 20 20  n self.dict.    
12140 64 65 66 20 5f 5f 64 65 6c 69 74 65 6d 5f 5f 28  def __delitem__(
12150 73 65 6c 66 2c 20 6b 65 79 29 3a 20 64 65 6c 20  self, key): del 
12160 73 65 6c 66 2e 64 69 63 74 5b 6b 65 79 5d 0a 20  self.dict[key]. 
12170 20 20 20 64 65 66 20 5f 5f 67 65 74 69 74 65 6d     def __getitem
12180 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 29 3a 20 72  __(self, key): r
12190 65 74 75 72 6e 20 73 65 6c 66 2e 64 69 63 74 5b  eturn self.dict[
121a0 6b 65 79 5d 5b 2d 31 5d 0a 20 20 20 20 64 65 66  key][-1].    def
121b0 20 5f 5f 73 65 74 69 74 65 6d 5f 5f 28 73 65 6c   __setitem__(sel
121c0 66 2c 20 6b 65 79 2c 20 76 61 6c 75 65 29 3a 20  f, key, value): 
121d0 73 65 6c 66 2e 61 70 70 65 6e 64 28 6b 65 79 2c  self.append(key,
121e0 20 76 61 6c 75 65 29 0a 20 20 20 20 64 65 66 20   value).    def 
121f0 6b 65 79 73 28 73 65 6c 66 29 3a 20 72 65 74 75  keys(self): retu
12200 72 6e 20 73 65 6c 66 2e 64 69 63 74 2e 6b 65 79  rn self.dict.key
12210 73 28 29 0a 0a 20 20 20 20 69 66 20 70 79 33 6b  s()..    if py3k
12220 3a 0a 20 20 20 20 20 20 20 20 64 65 66 20 76 61  :.        def va
12230 6c 75 65 73 28 73 65 6c 66 29 3a 20 72 65 74 75  lues(self): retu
12240 72 6e 20 28 76 5b 2d 31 5d 20 66 6f 72 20 76 20  rn (v[-1] for v 
12250 69 6e 20 73 65 6c 66 2e 64 69 63 74 2e 76 61 6c  in self.dict.val
12260 75 65 73 28 29 29 0a 20 20 20 20 20 20 20 20 64  ues()).        d
12270 65 66 20 69 74 65 6d 73 28 73 65 6c 66 29 3a 20  ef items(self): 
12280 72 65 74 75 72 6e 20 28 28 6b 2c 20 76 5b 2d 31  return ((k, v[-1
12290 5d 29 20 66 6f 72 20 6b 2c 20 76 20 69 6e 20 73  ]) for k, v in s
122a0 65 6c 66 2e 64 69 63 74 2e 69 74 65 6d 73 28 29  elf.dict.items()
122b0 29 0a 20 20 20 20 20 20 20 20 64 65 66 20 61 6c  ).        def al
122c0 6c 69 74 65 6d 73 28 73 65 6c 66 29 3a 0a 20 20  litems(self):.  
122d0 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
122e0 20 28 28 6b 2c 20 76 29 20 66 6f 72 20 6b 2c 20   ((k, v) for k, 
122f0 76 6c 20 69 6e 20 73 65 6c 66 2e 64 69 63 74 2e  vl in self.dict.
12300 69 74 65 6d 73 28 29 20 66 6f 72 20 76 20 69 6e  items() for v in
12310 20 76 6c 29 0a 20 20 20 20 20 20 20 20 69 74 65   vl).        ite
12320 72 6b 65 79 73 20 3d 20 6b 65 79 73 0a 20 20 20  rkeys = keys.   
12330 20 20 20 20 20 69 74 65 72 76 61 6c 75 65 73 20       itervalues 
12340 3d 20 76 61 6c 75 65 73 0a 20 20 20 20 20 20 20  = values.       
12350 20 69 74 65 72 69 74 65 6d 73 20 3d 20 69 74 65   iteritems = ite
12360 6d 73 0a 20 20 20 20 20 20 20 20 69 74 65 72 61  ms.        itera
12370 6c 6c 69 74 65 6d 73 20 3d 20 61 6c 6c 69 74 65  llitems = allite
12380 6d 73 0a 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20  ms..    else:.  
12390 20 20 20 20 20 20 64 65 66 20 76 61 6c 75 65 73        def values
123a0 28 73 65 6c 66 29 3a 20 72 65 74 75 72 6e 20 5b  (self): return [
123b0 76 5b 2d 31 5d 20 66 6f 72 20 76 20 69 6e 20 73  v[-1] for v in s
123c0 65 6c 66 2e 64 69 63 74 2e 76 61 6c 75 65 73 28  elf.dict.values(
123d0 29 5d 0a 20 20 20 20 20 20 20 20 64 65 66 20 69  )].        def i
123e0 74 65 6d 73 28 73 65 6c 66 29 3a 20 72 65 74 75  tems(self): retu
123f0 72 6e 20 5b 28 6b 2c 20 76 5b 2d 31 5d 29 20 66  rn [(k, v[-1]) f
12400 6f 72 20 6b 2c 20 76 20 69 6e 20 73 65 6c 66 2e  or k, v in self.
12410 64 69 63 74 2e 69 74 65 6d 73 28 29 5d 0a 20 20  dict.items()].  
12420 20 20 20 20 20 20 64 65 66 20 69 74 65 72 6b 65        def iterke
12430 79 73 28 73 65 6c 66 29 3a 20 72 65 74 75 72 6e  ys(self): return
12440 20 73 65 6c 66 2e 64 69 63 74 2e 69 74 65 72 6b   self.dict.iterk
12450 65 79 73 28 29 0a 20 20 20 20 20 20 20 20 64 65  eys().        de
12460 66 20 69 74 65 72 76 61 6c 75 65 73 28 73 65 6c  f itervalues(sel
12470 66 29 3a 20 72 65 74 75 72 6e 20 28 76 5b 2d 31  f): return (v[-1
12480 5d 20 66 6f 72 20 76 20 69 6e 20 73 65 6c 66 2e  ] for v in self.
12490 64 69 63 74 2e 69 74 65 72 76 61 6c 75 65 73 28  dict.itervalues(
124a0 29 29 0a 20 20 20 20 20 20 20 20 64 65 66 20 69  )).        def i
124b0 74 65 72 69 74 65 6d 73 28 73 65 6c 66 29 3a 0a  teritems(self):.
124c0 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
124d0 72 6e 20 28 28 6b 2c 20 76 5b 2d 31 5d 29 20 66  rn ((k, v[-1]) f
124e0 6f 72 20 6b 2c 20 76 20 69 6e 20 73 65 6c 66 2e  or k, v in self.
124f0 64 69 63 74 2e 69 74 65 72 69 74 65 6d 73 28 29  dict.iteritems()
12500 29 0a 20 20 20 20 20 20 20 20 64 65 66 20 69 74  ).        def it
12510 65 72 61 6c 6c 69 74 65 6d 73 28 73 65 6c 66 29  erallitems(self)
12520 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
12530 74 75 72 6e 20 28 28 6b 2c 20 76 29 20 66 6f 72  turn ((k, v) for
12540 20 6b 2c 20 76 6c 20 69 6e 20 73 65 6c 66 2e 64   k, vl in self.d
12550 69 63 74 2e 69 74 65 72 69 74 65 6d 73 28 29 20  ict.iteritems() 
12560 66 6f 72 20 76 20 69 6e 20 76 6c 29 0a 20 20 20  for v in vl).   
12570 20 20 20 20 20 64 65 66 20 61 6c 6c 69 74 65 6d       def allitem
12580 73 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20  s(self):.       
12590 20 20 20 20 20 72 65 74 75 72 6e 20 5b 28 6b 2c       return [(k,
125a0 20 76 29 20 66 6f 72 20 6b 2c 20 76 6c 20 69 6e   v) for k, vl in
125b0 20 73 65 6c 66 2e 64 69 63 74 2e 69 74 65 72 69   self.dict.iteri
125c0 74 65 6d 73 28 29 20 66 6f 72 20 76 20 69 6e 20  tems() for v in 
125d0 76 6c 5d 0a 0a 20 20 20 20 64 65 66 20 67 65 74  vl]..    def get
125e0 28 73 65 6c 66 2c 20 6b 65 79 2c 20 64 65 66 61  (self, key, defa
125f0 75 6c 74 3d 4e 6f 6e 65 2c 20 69 6e 64 65 78 3d  ult=None, index=
12600 2d 31 2c 20 74 79 70 65 3d 4e 6f 6e 65 29 3a 0a  -1, type=None):.
12610 20 20 20 20 20 20 20 20 27 27 27 20 52 65 74 75          ''' Retu
12620 72 6e 20 74 68 65 20 6d 6f 73 74 20 72 65 63 65  rn the most rece
12630 6e 74 20 76 61 6c 75 65 20 66 6f 72 20 61 20 6b  nt value for a k
12640 65 79 2e 0a 0a 20 20 20 20 20 20 20 20 20 20 20  ey...           
12650 20 3a 70 61 72 61 6d 20 64 65 66 61 75 6c 74 3a   :param default:
12660 20 54 68 65 20 64 65 66 61 75 6c 74 20 76 61 6c   The default val
12670 75 65 20 74 6f 20 62 65 20 72 65 74 75 72 6e 65  ue to be returne
12680 64 20 69 66 20 74 68 65 20 6b 65 79 20 69 73 20  d if the key is 
12690 6e 6f 74 0a 20 20 20 20 20 20 20 20 20 20 20 20  not.            
126a0 20 20 20 20 20 20 20 70 72 65 73 65 6e 74 20 6f         present o
126b0 72 20 74 68 65 20 74 79 70 65 20 63 6f 6e 76 65  r the type conve
126c0 72 73 69 6f 6e 20 66 61 69 6c 73 2e 0a 20 20 20  rsion fails..   
126d0 20 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20           :param 
126e0 69 6e 64 65 78 3a 20 41 6e 20 69 6e 64 65 78 20  index: An index 
126f0 66 6f 72 20 74 68 65 20 6c 69 73 74 20 6f 66 20  for the list of 
12700 61 76 61 69 6c 61 62 6c 65 20 76 61 6c 75 65 73  available values
12710 2e 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a 70  ..            :p
12720 61 72 61 6d 20 74 79 70 65 3a 20 49 66 20 64 65  aram type: If de
12730 66 69 6e 65 64 2c 20 74 68 69 73 20 63 61 6c 6c  fined, this call
12740 61 62 6c 65 20 69 73 20 75 73 65 64 20 74 6f 20  able is used to 
12750 63 61 73 74 20 74 68 65 20 76 61 6c 75 65 0a 20  cast the value. 
12760 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12770 20 20 20 69 6e 74 6f 20 61 20 73 70 65 63 69 66     into a specif
12780 69 63 20 74 79 70 65 2e 20 45 78 63 65 70 74 69  ic type. Excepti
12790 6f 6e 20 61 72 65 20 73 75 70 70 72 65 73 73 65  on are suppresse
127a0 64 20 61 6e 64 20 72 65 73 75 6c 74 20 69 6e 0a  d and result in.
127b0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
127c0 20 20 20 20 74 68 65 20 64 65 66 61 75 6c 74 20      the default 
127d0 76 61 6c 75 65 20 74 6f 20 62 65 20 72 65 74 75  value to be retu
127e0 72 6e 65 64 2e 0a 20 20 20 20 20 20 20 20 27 27  rned..        ''
127f0 27 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20  '.        try:. 
12800 20 20 20 20 20 20 20 20 20 20 20 76 61 6c 20 3d             val =
12810 20 73 65 6c 66 2e 64 69 63 74 5b 6b 65 79 5d 5b   self.dict[key][
12820 69 6e 64 65 78 5d 0a 20 20 20 20 20 20 20 20 20  index].         
12830 20 20 20 72 65 74 75 72 6e 20 74 79 70 65 28 76     return type(v
12840 61 6c 29 20 69 66 20 74 79 70 65 20 65 6c 73 65  al) if type else
12850 20 76 61 6c 0a 20 20 20 20 20 20 20 20 65 78 63   val.        exc
12860 65 70 74 20 45 78 63 65 70 74 69 6f 6e 3a 0a 20  ept Exception:. 
12870 20 20 20 20 20 20 20 20 20 20 20 70 61 73 73 0a             pass.
12880 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 64          return d
12890 65 66 61 75 6c 74 0a 0a 20 20 20 20 64 65 66 20  efault..    def 
128a0 61 70 70 65 6e 64 28 73 65 6c 66 2c 20 6b 65 79  append(self, key
128b0 2c 20 76 61 6c 75 65 29 3a 0a 20 20 20 20 20 20  , value):.      
128c0 20 20 27 27 27 20 41 64 64 20 61 20 6e 65 77 20    ''' Add a new 
128d0 76 61 6c 75 65 20 74 6f 20 74 68 65 20 6c 69 73  value to the lis
128e0 74 20 6f 66 20 76 61 6c 75 65 73 20 66 6f 72 20  t of values for 
128f0 74 68 69 73 20 6b 65 79 2e 20 27 27 27 0a 20 20  this key. '''.  
12900 20 20 20 20 20 20 73 65 6c 66 2e 64 69 63 74 2e        self.dict.
12910 73 65 74 64 65 66 61 75 6c 74 28 6b 65 79 2c 20  setdefault(key, 
12920 5b 5d 29 2e 61 70 70 65 6e 64 28 76 61 6c 75 65  []).append(value
12930 29 0a 0a 20 20 20 20 64 65 66 20 72 65 70 6c 61  )..    def repla
12940 63 65 28 73 65 6c 66 2c 20 6b 65 79 2c 20 76 61  ce(self, key, va
12950 6c 75 65 29 3a 0a 20 20 20 20 20 20 20 20 27 27  lue):.        ''
12960 27 20 52 65 70 6c 61 63 65 20 74 68 65 20 6c 69  ' Replace the li
12970 73 74 20 6f 66 20 76 61 6c 75 65 73 20 77 69 74  st of values wit
12980 68 20 61 20 73 69 6e 67 6c 65 20 76 61 6c 75 65  h a single value
12990 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20 73 65  . '''.        se
129a0 6c 66 2e 64 69 63 74 5b 6b 65 79 5d 20 3d 20 5b  lf.dict[key] = [
129b0 76 61 6c 75 65 5d 0a 0a 20 20 20 20 64 65 66 20  value]..    def 
129c0 67 65 74 61 6c 6c 28 73 65 6c 66 2c 20 6b 65 79  getall(self, key
129d0 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 52  ):.        ''' R
129e0 65 74 75 72 6e 20 61 20 28 70 6f 73 73 69 62 6c  eturn a (possibl
129f0 79 20 65 6d 70 74 79 29 20 6c 69 73 74 20 6f 66  y empty) list of
12a00 20 76 61 6c 75 65 73 20 66 6f 72 20 61 20 6b 65   values for a ke
12a10 79 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20 72  y. '''.        r
12a20 65 74 75 72 6e 20 73 65 6c 66 2e 64 69 63 74 2e  eturn self.dict.
12a30 67 65 74 28 6b 65 79 29 20 6f 72 20 5b 5d 0a 0a  get(key) or []..
12a40 20 20 20 20 23 3a 20 41 6c 69 61 73 65 73 20 66      #: Aliases f
12a50 6f 72 20 57 54 46 6f 72 6d 73 20 74 6f 20 6d 69  or WTForms to mi
12a60 6d 69 63 20 6f 74 68 65 72 20 6d 75 6c 74 69 2d  mic other multi-
12a70 64 69 63 74 20 41 50 49 73 20 28 44 6a 61 6e 67  dict APIs (Djang
12a80 6f 29 0a 20 20 20 20 67 65 74 6f 6e 65 20 3d 20  o).    getone = 
12a90 67 65 74 0a 20 20 20 20 67 65 74 6c 69 73 74 20  get.    getlist 
12aa0 3d 20 67 65 74 61 6c 6c 0a 0a 0a 63 6c 61 73 73  = getall...class
12ab0 20 46 6f 72 6d 73 44 69 63 74 28 4d 75 6c 74 69   FormsDict(Multi
12ac0 44 69 63 74 29 3a 0a 20 20 20 20 27 27 27 20 54  Dict):.    ''' T
12ad0 68 69 73 20 3a 63 6c 61 73 73 3a 60 4d 75 6c 74  his :class:`Mult
12ae0 69 44 69 63 74 60 20 73 75 62 63 6c 61 73 73 20  iDict` subclass 
12af0 69 73 20 75 73 65 64 20 74 6f 20 73 74 6f 72 65  is used to store
12b00 20 72 65 71 75 65 73 74 20 66 6f 72 6d 20 64 61   request form da
12b10 74 61 2e 0a 20 20 20 20 20 20 20 20 41 64 64 69  ta..        Addi
12b20 74 69 6f 6e 61 6c 6c 79 20 74 6f 20 74 68 65 20  tionally to the 
12b30 6e 6f 72 6d 61 6c 20 64 69 63 74 2d 6c 69 6b 65  normal dict-like
12b40 20 69 74 65 6d 20 61 63 63 65 73 73 20 6d 65 74   item access met
12b50 68 6f 64 73 20 28 77 68 69 63 68 20 72 65 74 75  hods (which retu
12b60 72 6e 0a 20 20 20 20 20 20 20 20 75 6e 6d 6f 64  rn.        unmod
12b70 69 66 69 65 64 20 64 61 74 61 20 61 73 20 6e 61  ified data as na
12b80 74 69 76 65 20 73 74 72 69 6e 67 73 29 2c 20 74  tive strings), t
12b90 68 69 73 20 63 6f 6e 74 61 69 6e 65 72 20 61 6c  his container al
12ba0 73 6f 20 73 75 70 70 6f 72 74 73 0a 20 20 20 20  so supports.    
12bb0 20 20 20 20 61 74 74 72 69 62 75 74 65 2d 6c 69      attribute-li
12bc0 6b 65 20 61 63 63 65 73 73 20 74 6f 20 69 74 73  ke access to its
12bd0 20 76 61 6c 75 65 73 2e 20 41 74 74 72 69 62 75   values. Attribu
12be0 74 65 73 20 61 72 65 20 61 75 74 6f 6d 61 74 69  tes are automati
12bf0 63 61 6c 6c 79 20 64 65 2d 0a 20 20 20 20 20 20  cally de-.      
12c00 20 20 6f 72 20 72 65 63 6f 64 65 64 20 74 6f 20    or recoded to 
12c10 6d 61 74 63 68 20 3a 61 74 74 72 3a 60 69 6e 70  match :attr:`inp
12c20 75 74 5f 65 6e 63 6f 64 69 6e 67 60 20 28 64 65  ut_encoding` (de
12c30 66 61 75 6c 74 3a 20 27 75 74 66 38 27 29 2e 20  fault: 'utf8'). 
12c40 4d 69 73 73 69 6e 67 0a 20 20 20 20 20 20 20 20  Missing.        
12c50 61 74 74 72 69 62 75 74 65 73 20 64 65 66 61 75  attributes defau
12c60 6c 74 20 74 6f 20 61 6e 20 65 6d 70 74 79 20 73  lt to an empty s
12c70 74 72 69 6e 67 2e 20 27 27 27 0a 0a 20 20 20 20  tring. '''..    
12c80 23 3a 20 45 6e 63 6f 64 69 6e 67 20 75 73 65 64  #: Encoding used
12c90 20 66 6f 72 20 61 74 74 72 69 62 75 74 65 20 76   for attribute v
12ca0 61 6c 75 65 73 2e 0a 20 20 20 20 69 6e 70 75 74  alues..    input
12cb0 5f 65 6e 63 6f 64 69 6e 67 20 3d 20 27 75 74 66  _encoding = 'utf
12cc0 38 27 0a 20 20 20 20 23 3a 20 49 66 20 74 72 75  8'.    #: If tru
12cd0 65 20 28 64 65 66 61 75 6c 74 29 2c 20 75 6e 69  e (default), uni
12ce0 63 6f 64 65 20 73 74 72 69 6e 67 73 20 61 72 65  code strings are
12cf0 20 66 69 72 73 74 20 65 6e 63 6f 64 65 64 20 77   first encoded w
12d00 69 74 68 20 60 6c 61 74 69 6e 31 60 0a 20 20 20  ith `latin1`.   
12d10 20 23 3a 20 61 6e 64 20 74 68 65 6e 20 64 65 63   #: and then dec
12d20 6f 64 65 64 20 74 6f 20 6d 61 74 63 68 20 3a 61  oded to match :a
12d30 74 74 72 3a 60 69 6e 70 75 74 5f 65 6e 63 6f 64  ttr:`input_encod
12d40 69 6e 67 60 2e 0a 20 20 20 20 72 65 63 6f 64 65  ing`..    recode
12d50 5f 75 6e 69 63 6f 64 65 20 3d 20 54 72 75 65 0a  _unicode = True.
12d60 0a 20 20 20 20 64 65 66 20 5f 66 69 78 28 73 65  .    def _fix(se
12d70 6c 66 2c 20 73 2c 20 65 6e 63 6f 64 69 6e 67 3d  lf, s, encoding=
12d80 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20 20 69  None):.        i
12d90 66 20 69 73 69 6e 73 74 61 6e 63 65 28 73 2c 20  f isinstance(s, 
12da0 75 6e 69 63 6f 64 65 29 20 61 6e 64 20 73 65 6c  unicode) and sel
12db0 66 2e 72 65 63 6f 64 65 5f 75 6e 69 63 6f 64 65  f.recode_unicode
12dc0 3a 20 23 20 50 79 74 68 6f 6e 20 33 20 57 53 47  : # Python 3 WSG
12dd0 49 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  I.            re
12de0 74 75 72 6e 20 73 2e 65 6e 63 6f 64 65 28 27 6c  turn s.encode('l
12df0 61 74 69 6e 31 27 29 2e 64 65 63 6f 64 65 28 65  atin1').decode(e
12e00 6e 63 6f 64 69 6e 67 20 6f 72 20 73 65 6c 66 2e  ncoding or self.
12e10 69 6e 70 75 74 5f 65 6e 63 6f 64 69 6e 67 29 0a  input_encoding).
12e20 20 20 20 20 20 20 20 20 65 6c 69 66 20 69 73 69          elif isi
12e30 6e 73 74 61 6e 63 65 28 73 2c 20 62 79 74 65 73  nstance(s, bytes
12e40 29 3a 20 23 20 50 79 74 68 6f 6e 20 32 20 57 53  ): # Python 2 WS
12e50 47 49 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  GI.            r
12e60 65 74 75 72 6e 20 73 2e 64 65 63 6f 64 65 28 65  eturn s.decode(e
12e70 6e 63 6f 64 69 6e 67 20 6f 72 20 73 65 6c 66 2e  ncoding or self.
12e80 69 6e 70 75 74 5f 65 6e 63 6f 64 69 6e 67 29 0a  input_encoding).
12e90 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
12ea0 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
12eb0 20 73 0a 0a 20 20 20 20 64 65 66 20 64 65 63 6f   s..    def deco
12ec0 64 65 28 73 65 6c 66 2c 20 65 6e 63 6f 64 69 6e  de(self, encodin
12ed0 67 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20  g=None):.       
12ee0 20 27 27 27 20 52 65 74 75 72 6e 73 20 61 20 63   ''' Returns a c
12ef0 6f 70 79 20 77 69 74 68 20 61 6c 6c 20 6b 65 79  opy with all key
12f00 73 20 61 6e 64 20 76 61 6c 75 65 73 20 64 65 2d  s and values de-
12f10 20 6f 72 20 72 65 63 6f 64 65 64 20 74 6f 20 6d   or recoded to m
12f20 61 74 63 68 0a 20 20 20 20 20 20 20 20 20 20 20  atch.           
12f30 20 3a 61 74 74 72 3a 60 69 6e 70 75 74 5f 65 6e   :attr:`input_en
12f40 63 6f 64 69 6e 67 60 2e 20 53 6f 6d 65 20 6c 69  coding`. Some li
12f50 62 72 61 72 69 65 73 20 28 65 2e 67 2e 20 57 54  braries (e.g. WT
12f60 46 6f 72 6d 73 29 20 77 61 6e 74 20 61 0a 20 20  Forms) want a.  
12f70 20 20 20 20 20 20 20 20 20 20 75 6e 69 63 6f 64            unicod
12f80 65 20 64 69 63 74 69 6f 6e 61 72 79 2e 20 27 27  e dictionary. ''
12f90 27 0a 20 20 20 20 20 20 20 20 63 6f 70 79 20 3d  '.        copy =
12fa0 20 46 6f 72 6d 73 44 69 63 74 28 29 0a 20 20 20   FormsDict().   
12fb0 20 20 20 20 20 65 6e 63 20 3d 20 63 6f 70 79 2e       enc = copy.
12fc0 69 6e 70 75 74 5f 65 6e 63 6f 64 69 6e 67 20 3d  input_encoding =
12fd0 20 65 6e 63 6f 64 69 6e 67 20 6f 72 20 73 65 6c   encoding or sel
12fe0 66 2e 69 6e 70 75 74 5f 65 6e 63 6f 64 69 6e 67  f.input_encoding
12ff0 0a 20 20 20 20 20 20 20 20 63 6f 70 79 2e 72 65  .        copy.re
13000 63 6f 64 65 5f 75 6e 69 63 6f 64 65 20 3d 20 46  code_unicode = F
13010 61 6c 73 65 0a 20 20 20 20 20 20 20 20 66 6f 72  alse.        for
13020 20 6b 65 79 2c 20 76 61 6c 75 65 20 69 6e 20 73   key, value in s
13030 65 6c 66 2e 61 6c 6c 69 74 65 6d 73 28 29 3a 0a  elf.allitems():.
13040 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 70 79              copy
13050 2e 61 70 70 65 6e 64 28 73 65 6c 66 2e 5f 66 69  .append(self._fi
13060 78 28 6b 65 79 2c 20 65 6e 63 29 2c 20 73 65 6c  x(key, enc), sel
13070 66 2e 5f 66 69 78 28 76 61 6c 75 65 2c 20 65 6e  f._fix(value, en
13080 63 29 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  c)).        retu
13090 72 6e 20 63 6f 70 79 0a 0a 20 20 20 20 64 65 66  rn copy..    def
130a0 20 67 65 74 75 6e 69 63 6f 64 65 28 73 65 6c 66   getunicode(self
130b0 2c 20 6e 61 6d 65 2c 20 64 65 66 61 75 6c 74 3d  , name, default=
130c0 4e 6f 6e 65 2c 20 65 6e 63 6f 64 69 6e 67 3d 4e  None, encoding=N
130d0 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20 20 27 27  one):.        ''
130e0 27 20 52 65 74 75 72 6e 20 74 68 65 20 76 61 6c  ' Return the val
130f0 75 65 20 61 73 20 61 20 75 6e 69 63 6f 64 65 20  ue as a unicode 
13100 73 74 72 69 6e 67 2c 20 6f 72 20 74 68 65 20 64  string, or the d
13110 65 66 61 75 6c 74 2e 20 27 27 27 0a 20 20 20 20  efault. '''.    
13120 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
13130 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66       return self
13140 2e 5f 66 69 78 28 73 65 6c 66 5b 6e 61 6d 65 5d  ._fix(self[name]
13150 2c 20 65 6e 63 6f 64 69 6e 67 29 0a 20 20 20 20  , encoding).    
13160 20 20 20 20 65 78 63 65 70 74 20 28 55 6e 69 63      except (Unic
13170 6f 64 65 45 72 72 6f 72 2c 20 4b 65 79 45 72 72  odeError, KeyErr
13180 6f 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  or):.           
13190 20 72 65 74 75 72 6e 20 64 65 66 61 75 6c 74 0a   return default.
131a0 0a 20 20 20 20 64 65 66 20 5f 5f 67 65 74 61 74  .    def __getat
131b0 74 72 5f 5f 28 73 65 6c 66 2c 20 6e 61 6d 65 2c  tr__(self, name,
131c0 20 64 65 66 61 75 6c 74 3d 75 6e 69 63 6f 64 65   default=unicode
131d0 28 29 29 3a 0a 20 20 20 20 20 20 20 20 23 20 57  ()):.        # W
131e0 69 74 68 6f 75 74 20 74 68 69 73 20 67 75 61 72  ithout this guar
131f0 64 2c 20 70 69 63 6b 6c 65 20 67 65 6e 65 72 61  d, pickle genera
13200 74 65 73 20 61 20 63 72 79 70 74 69 63 20 54 79  tes a cryptic Ty
13210 70 65 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20  peError:.       
13220 20 69 66 20 6e 61 6d 65 2e 73 74 61 72 74 73 77   if name.startsw
13230 69 74 68 28 27 5f 5f 27 29 20 61 6e 64 20 6e 61  ith('__') and na
13240 6d 65 2e 65 6e 64 73 77 69 74 68 28 27 5f 5f 27  me.endswith('__'
13250 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  ):.            r
13260 65 74 75 72 6e 20 73 75 70 65 72 28 46 6f 72 6d  eturn super(Form
13270 73 44 69 63 74 2c 20 73 65 6c 66 29 2e 5f 5f 67  sDict, self).__g
13280 65 74 61 74 74 72 5f 5f 28 6e 61 6d 65 29 0a 20  etattr__(name). 
13290 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65         return se
132a0 6c 66 2e 67 65 74 75 6e 69 63 6f 64 65 28 6e 61  lf.getunicode(na
132b0 6d 65 2c 20 64 65 66 61 75 6c 74 3d 64 65 66 61  me, default=defa
132c0 75 6c 74 29 0a 0a 63 6c 61 73 73 20 48 65 61 64  ult)..class Head
132d0 65 72 44 69 63 74 28 4d 75 6c 74 69 44 69 63 74  erDict(MultiDict
132e0 29 3a 0a 20 20 20 20 22 22 22 20 41 20 63 61 73  ):.    """ A cas
132f0 65 2d 69 6e 73 65 6e 73 69 74 69 76 65 20 76 65  e-insensitive ve
13300 72 73 69 6f 6e 20 6f 66 20 3a 63 6c 61 73 73 3a  rsion of :class:
13310 60 4d 75 6c 74 69 44 69 63 74 60 20 74 68 61 74  `MultiDict` that
13320 20 64 65 66 61 75 6c 74 73 20 74 6f 0a 20 20 20   defaults to.   
13330 20 20 20 20 20 72 65 70 6c 61 63 65 20 74 68 65       replace the
13340 20 6f 6c 64 20 76 61 6c 75 65 20 69 6e 73 74 65   old value inste
13350 61 64 20 6f 66 20 61 70 70 65 6e 64 69 6e 67 20  ad of appending 
13360 69 74 2e 20 22 22 22 0a 0a 20 20 20 20 64 65 66  it. """..    def
13370 20 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20   __init__(self, 
13380 2a 61 2c 20 2a 2a 6b 61 29 3a 0a 20 20 20 20 20  *a, **ka):.     
13390 20 20 20 73 65 6c 66 2e 64 69 63 74 20 3d 20 7b     self.dict = {
133a0 7d 0a 20 20 20 20 20 20 20 20 69 66 20 61 20 6f  }.        if a o
133b0 72 20 6b 61 3a 20 73 65 6c 66 2e 75 70 64 61 74  r ka: self.updat
133c0 65 28 2a 61 2c 20 2a 2a 6b 61 29 0a 0a 20 20 20  e(*a, **ka)..   
133d0 20 64 65 66 20 5f 5f 63 6f 6e 74 61 69 6e 73 5f   def __contains_
133e0 5f 28 73 65 6c 66 2c 20 6b 65 79 29 3a 20 72 65  _(self, key): re
133f0 74 75 72 6e 20 5f 68 6b 65 79 28 6b 65 79 29 20  turn _hkey(key) 
13400 69 6e 20 73 65 6c 66 2e 64 69 63 74 0a 20 20 20  in self.dict.   
13410 20 64 65 66 20 5f 5f 64 65 6c 69 74 65 6d 5f 5f   def __delitem__
13420 28 73 65 6c 66 2c 20 6b 65 79 29 3a 20 64 65 6c  (self, key): del
13430 20 73 65 6c 66 2e 64 69 63 74 5b 5f 68 6b 65 79   self.dict[_hkey
13440 28 6b 65 79 29 5d 0a 20 20 20 20 64 65 66 20 5f  (key)].    def _
13450 5f 67 65 74 69 74 65 6d 5f 5f 28 73 65 6c 66 2c  _getitem__(self,
13460 20 6b 65 79 29 3a 20 72 65 74 75 72 6e 20 73 65   key): return se
13470 6c 66 2e 64 69 63 74 5b 5f 68 6b 65 79 28 6b 65  lf.dict[_hkey(ke
13480 79 29 5d 5b 2d 31 5d 0a 20 20 20 20 64 65 66 20  y)][-1].    def 
13490 5f 5f 73 65 74 69 74 65 6d 5f 5f 28 73 65 6c 66  __setitem__(self
134a0 2c 20 6b 65 79 2c 20 76 61 6c 75 65 29 3a 20 73  , key, value): s
134b0 65 6c 66 2e 64 69 63 74 5b 5f 68 6b 65 79 28 6b  elf.dict[_hkey(k
134c0 65 79 29 5d 20 3d 20 5b 5f 68 76 61 6c 28 76 61  ey)] = [_hval(va
134d0 6c 75 65 29 5d 0a 20 20 20 20 64 65 66 20 61 70  lue)].    def ap
134e0 70 65 6e 64 28 73 65 6c 66 2c 20 6b 65 79 2c 20  pend(self, key, 
134f0 76 61 6c 75 65 29 3a 20 73 65 6c 66 2e 64 69 63  value): self.dic
13500 74 2e 73 65 74 64 65 66 61 75 6c 74 28 5f 68 6b  t.setdefault(_hk
13510 65 79 28 6b 65 79 29 2c 20 5b 5d 29 2e 61 70 70  ey(key), []).app
13520 65 6e 64 28 5f 68 76 61 6c 28 76 61 6c 75 65 29  end(_hval(value)
13530 29 0a 20 20 20 20 64 65 66 20 72 65 70 6c 61 63  ).    def replac
13540 65 28 73 65 6c 66 2c 20 6b 65 79 2c 20 76 61 6c  e(self, key, val
13550 75 65 29 3a 20 73 65 6c 66 2e 64 69 63 74 5b 5f  ue): self.dict[_
13560 68 6b 65 79 28 6b 65 79 29 5d 20 3d 20 5b 5f 68  hkey(key)] = [_h
13570 76 61 6c 28 76 61 6c 75 65 29 5d 0a 20 20 20 20  val(value)].    
13580 64 65 66 20 67 65 74 61 6c 6c 28 73 65 6c 66 2c  def getall(self,
13590 20 6b 65 79 29 3a 20 72 65 74 75 72 6e 20 73 65   key): return se
135a0 6c 66 2e 64 69 63 74 2e 67 65 74 28 5f 68 6b 65  lf.dict.get(_hke
135b0 79 28 6b 65 79 29 29 20 6f 72 20 5b 5d 0a 20 20  y(key)) or [].  
135c0 20 20 64 65 66 20 67 65 74 28 73 65 6c 66 2c 20    def get(self, 
135d0 6b 65 79 2c 20 64 65 66 61 75 6c 74 3d 4e 6f 6e  key, default=Non
135e0 65 2c 20 69 6e 64 65 78 3d 2d 31 29 3a 0a 20 20  e, index=-1):.  
135f0 20 20 20 20 20 20 72 65 74 75 72 6e 20 4d 75 6c        return Mul
13600 74 69 44 69 63 74 2e 67 65 74 28 73 65 6c 66 2c  tiDict.get(self,
13610 20 5f 68 6b 65 79 28 6b 65 79 29 2c 20 64 65 66   _hkey(key), def
13620 61 75 6c 74 2c 20 69 6e 64 65 78 29 0a 20 20 20  ault, index).   
13630 20 64 65 66 20 66 69 6c 74 65 72 28 73 65 6c 66   def filter(self
13640 2c 20 6e 61 6d 65 73 29 3a 0a 20 20 20 20 20 20  , names):.      
13650 20 20 66 6f 72 20 6e 61 6d 65 20 69 6e 20 28 5f    for name in (_
13660 68 6b 65 79 28 6e 29 20 66 6f 72 20 6e 20 69 6e  hkey(n) for n in
13670 20 6e 61 6d 65 73 29 3a 0a 20 20 20 20 20 20 20   names):.       
13680 20 20 20 20 20 69 66 20 6e 61 6d 65 20 69 6e 20       if name in 
13690 73 65 6c 66 2e 64 69 63 74 3a 0a 20 20 20 20 20  self.dict:.     
136a0 20 20 20 20 20 20 20 20 20 20 20 64 65 6c 20 73             del s
136b0 65 6c 66 2e 64 69 63 74 5b 6e 61 6d 65 5d 0a 0a  elf.dict[name]..
136c0 0a 63 6c 61 73 73 20 57 53 47 49 48 65 61 64 65  .class WSGIHeade
136d0 72 44 69 63 74 28 44 69 63 74 4d 69 78 69 6e 29  rDict(DictMixin)
136e0 3a 0a 20 20 20 20 27 27 27 20 54 68 69 73 20 64  :.    ''' This d
136f0 69 63 74 2d 6c 69 6b 65 20 63 6c 61 73 73 20 77  ict-like class w
13700 72 61 70 73 20 61 20 57 53 47 49 20 65 6e 76 69  raps a WSGI envi
13710 72 6f 6e 20 64 69 63 74 20 61 6e 64 20 70 72 6f  ron dict and pro
13720 76 69 64 65 73 20 63 6f 6e 76 65 6e 69 65 6e 74  vides convenient
13730 0a 20 20 20 20 20 20 20 20 61 63 63 65 73 73 20  .        access 
13740 74 6f 20 48 54 54 50 5f 2a 20 66 69 65 6c 64 73  to HTTP_* fields
13750 2e 20 4b 65 79 73 20 61 6e 64 20 76 61 6c 75 65  . Keys and value
13760 73 20 61 72 65 20 6e 61 74 69 76 65 20 73 74 72  s are native str
13770 69 6e 67 73 0a 20 20 20 20 20 20 20 20 28 32 2e  ings.        (2.
13780 78 20 62 79 74 65 73 20 6f 72 20 33 2e 78 20 75  x bytes or 3.x u
13790 6e 69 63 6f 64 65 29 20 61 6e 64 20 6b 65 79 73  nicode) and keys
137a0 20 61 72 65 20 63 61 73 65 2d 69 6e 73 65 6e 73   are case-insens
137b0 69 74 69 76 65 2e 20 49 66 20 74 68 65 20 57 53  itive. If the WS
137c0 47 49 0a 20 20 20 20 20 20 20 20 65 6e 76 69 72  GI.        envir
137d0 6f 6e 6d 65 6e 74 20 63 6f 6e 74 61 69 6e 73 20  onment contains 
137e0 6e 6f 6e 2d 6e 61 74 69 76 65 20 73 74 72 69 6e  non-native strin
137f0 67 20 76 61 6c 75 65 73 2c 20 74 68 65 73 65 20  g values, these 
13800 61 72 65 20 64 65 2d 20 6f 72 20 65 6e 63 6f 64  are de- or encod
13810 65 64 0a 20 20 20 20 20 20 20 20 75 73 69 6e 67  ed.        using
13820 20 61 20 6c 6f 73 73 6c 65 73 73 20 27 6c 61 74   a lossless 'lat
13830 69 6e 31 27 20 63 68 61 72 61 63 74 65 72 20 73  in1' character s
13840 65 74 2e 0a 0a 20 20 20 20 20 20 20 20 54 68 65  et...        The
13850 20 41 50 49 20 77 69 6c 6c 20 72 65 6d 61 69 6e   API will remain
13860 20 73 74 61 62 6c 65 20 65 76 65 6e 20 6f 6e 20   stable even on 
13870 63 68 61 6e 67 65 73 20 74 6f 20 74 68 65 20 72  changes to the r
13880 65 6c 65 76 61 6e 74 20 50 45 50 73 2e 0a 20 20  elevant PEPs..  
13890 20 20 20 20 20 20 43 75 72 72 65 6e 74 6c 79 20        Currently 
138a0 50 45 50 20 33 33 33 2c 20 34 34 34 20 61 6e 64  PEP 333, 444 and
138b0 20 33 33 33 33 20 61 72 65 20 73 75 70 70 6f 72   3333 are suppor
138c0 74 65 64 2e 20 28 50 45 50 20 34 34 34 20 69 73  ted. (PEP 444 is
138d0 20 74 68 65 20 6f 6e 6c 79 20 6f 6e 65 0a 20 20   the only one.  
138e0 20 20 20 20 20 20 74 68 61 74 20 75 73 65 73 20        that uses 
138f0 6e 6f 6e 2d 6e 61 74 69 76 65 20 73 74 72 69 6e  non-native strin
13900 67 73 2e 29 0a 20 20 20 20 27 27 27 0a 20 20 20  gs.).    '''.   
13910 20 23 3a 20 4c 69 73 74 20 6f 66 20 6b 65 79 73   #: List of keys
13920 20 74 68 61 74 20 64 6f 20 6e 6f 74 20 68 61 76   that do not hav
13930 65 20 61 20 60 60 48 54 54 50 5f 60 60 20 70 72  e a ``HTTP_`` pr
13940 65 66 69 78 2e 0a 20 20 20 20 63 67 69 6b 65 79  efix..    cgikey
13950 73 20 3d 20 28 27 43 4f 4e 54 45 4e 54 5f 54 59  s = ('CONTENT_TY
13960 50 45 27 2c 20 27 43 4f 4e 54 45 4e 54 5f 4c 45  PE', 'CONTENT_LE
13970 4e 47 54 48 27 29 0a 0a 20 20 20 20 64 65 66 20  NGTH')..    def 
13980 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 65  __init__(self, e
13990 6e 76 69 72 6f 6e 29 3a 0a 20 20 20 20 20 20 20  nviron):.       
139a0 20 73 65 6c 66 2e 65 6e 76 69 72 6f 6e 20 3d 20   self.environ = 
139b0 65 6e 76 69 72 6f 6e 0a 0a 20 20 20 20 64 65 66  environ..    def
139c0 20 5f 65 6b 65 79 28 73 65 6c 66 2c 20 6b 65 79   _ekey(self, key
139d0 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20 54  ):.        ''' T
139e0 72 61 6e 73 6c 61 74 65 20 68 65 61 64 65 72 20  ranslate header 
139f0 66 69 65 6c 64 20 6e 61 6d 65 20 74 6f 20 43 47  field name to CG
13a00 49 2f 57 53 47 49 20 65 6e 76 69 72 6f 6e 20 6b  I/WSGI environ k
13a10 65 79 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20  ey. '''.        
13a20 6b 65 79 20 3d 20 6b 65 79 2e 72 65 70 6c 61 63  key = key.replac
13a30 65 28 27 2d 27 2c 27 5f 27 29 2e 75 70 70 65 72  e('-','_').upper
13a40 28 29 0a 20 20 20 20 20 20 20 20 69 66 20 6b 65  ().        if ke
13a50 79 20 69 6e 20 73 65 6c 66 2e 63 67 69 6b 65 79  y in self.cgikey
13a60 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  s:.            r
13a70 65 74 75 72 6e 20 6b 65 79 0a 20 20 20 20 20 20  eturn key.      
13a80 20 20 72 65 74 75 72 6e 20 27 48 54 54 50 5f 27    return 'HTTP_'
13a90 20 2b 20 6b 65 79 0a 0a 20 20 20 20 64 65 66 20   + key..    def 
13aa0 72 61 77 28 73 65 6c 66 2c 20 6b 65 79 2c 20 64  raw(self, key, d
13ab0 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20  efault=None):.  
13ac0 20 20 20 20 20 20 27 27 27 20 52 65 74 75 72 6e        ''' Return
13ad0 20 74 68 65 20 68 65 61 64 65 72 20 76 61 6c 75   the header valu
13ae0 65 20 61 73 20 69 73 20 28 6d 61 79 20 62 65 20  e as is (may be 
13af0 62 79 74 65 73 20 6f 72 20 75 6e 69 63 6f 64 65  bytes or unicode
13b00 29 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20 72  ). '''.        r
13b10 65 74 75 72 6e 20 73 65 6c 66 2e 65 6e 76 69 72  eturn self.envir
13b20 6f 6e 2e 67 65 74 28 73 65 6c 66 2e 5f 65 6b 65  on.get(self._eke
13b30 79 28 6b 65 79 29 2c 20 64 65 66 61 75 6c 74 29  y(key), default)
13b40 0a 0a 20 20 20 20 64 65 66 20 5f 5f 67 65 74 69  ..    def __geti
13b50 74 65 6d 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 29  tem__(self, key)
13b60 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
13b70 20 74 6f 6e 61 74 28 73 65 6c 66 2e 65 6e 76 69   tonat(self.envi
13b80 72 6f 6e 5b 73 65 6c 66 2e 5f 65 6b 65 79 28 6b  ron[self._ekey(k
13b90 65 79 29 5d 2c 20 27 6c 61 74 69 6e 31 27 29 0a  ey)], 'latin1').
13ba0 0a 20 20 20 20 64 65 66 20 5f 5f 73 65 74 69 74  .    def __setit
13bb0 65 6d 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 2c 20  em__(self, key, 
13bc0 76 61 6c 75 65 29 3a 0a 20 20 20 20 20 20 20 20  value):.        
13bd0 72 61 69 73 65 20 54 79 70 65 45 72 72 6f 72 28  raise TypeError(
13be0 22 25 73 20 69 73 20 72 65 61 64 2d 6f 6e 6c 79  "%s is read-only
13bf0 2e 22 20 25 20 73 65 6c 66 2e 5f 5f 63 6c 61 73  ." % self.__clas
13c00 73 5f 5f 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f  s__)..    def __
13c10 64 65 6c 69 74 65 6d 5f 5f 28 73 65 6c 66 2c 20  delitem__(self, 
13c20 6b 65 79 29 3a 0a 20 20 20 20 20 20 20 20 72 61  key):.        ra
13c30 69 73 65 20 54 79 70 65 45 72 72 6f 72 28 22 25  ise TypeError("%
13c40 73 20 69 73 20 72 65 61 64 2d 6f 6e 6c 79 2e 22  s is read-only."
13c50 20 25 20 73 65 6c 66 2e 5f 5f 63 6c 61 73 73 5f   % self.__class_
13c60 5f 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 74  _)..    def __it
13c70 65 72 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20 20  er__(self):.    
13c80 20 20 20 20 66 6f 72 20 6b 65 79 20 69 6e 20 73      for key in s
13c90 65 6c 66 2e 65 6e 76 69 72 6f 6e 3a 0a 20 20 20  elf.environ:.   
13ca0 20 20 20 20 20 20 20 20 20 69 66 20 6b 65 79 5b           if key[
13cb0 3a 35 5d 20 3d 3d 20 27 48 54 54 50 5f 27 3a 0a  :5] == 'HTTP_':.
13cc0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13cd0 79 69 65 6c 64 20 6b 65 79 5b 35 3a 5d 2e 72 65  yield key[5:].re
13ce0 70 6c 61 63 65 28 27 5f 27 2c 20 27 2d 27 29 2e  place('_', '-').
13cf0 74 69 74 6c 65 28 29 0a 20 20 20 20 20 20 20 20  title().        
13d00 20 20 20 20 65 6c 69 66 20 6b 65 79 20 69 6e 20      elif key in 
13d10 73 65 6c 66 2e 63 67 69 6b 65 79 73 3a 0a 20 20  self.cgikeys:.  
13d20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69                yi
13d30 65 6c 64 20 6b 65 79 2e 72 65 70 6c 61 63 65 28  eld key.replace(
13d40 27 5f 27 2c 20 27 2d 27 29 2e 74 69 74 6c 65 28  '_', '-').title(
13d50 29 0a 0a 20 20 20 20 64 65 66 20 6b 65 79 73 28  )..    def keys(
13d60 73 65 6c 66 29 3a 20 72 65 74 75 72 6e 20 5b 78  self): return [x
13d70 20 66 6f 72 20 78 20 69 6e 20 73 65 6c 66 5d 0a   for x in self].
13d80 20 20 20 20 64 65 66 20 5f 5f 6c 65 6e 5f 5f 28      def __len__(
13d90 73 65 6c 66 29 3a 20 72 65 74 75 72 6e 20 6c 65  self): return le
13da0 6e 28 73 65 6c 66 2e 6b 65 79 73 28 29 29 0a 20  n(self.keys()). 
13db0 20 20 20 64 65 66 20 5f 5f 63 6f 6e 74 61 69 6e     def __contain
13dc0 73 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 29 3a 20  s__(self, key): 
13dd0 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f 65 6b 65  return self._eke
13de0 79 28 6b 65 79 29 20 69 6e 20 73 65 6c 66 2e 65  y(key) in self.e
13df0 6e 76 69 72 6f 6e 0a 0a 0a 0a 63 6c 61 73 73 20  nviron....class 
13e00 43 6f 6e 66 69 67 44 69 63 74 28 64 69 63 74 29  ConfigDict(dict)
13e10 3a 0a 20 20 20 20 27 27 27 20 41 20 64 69 63 74  :.    ''' A dict
13e20 2d 6c 69 6b 65 20 63 6f 6e 66 69 67 75 72 61 74  -like configurat
13e30 69 6f 6e 20 73 74 6f 72 61 67 65 20 77 69 74 68  ion storage with
13e40 20 61 64 64 69 74 69 6f 6e 61 6c 20 73 75 70 70   additional supp
13e50 6f 72 74 20 66 6f 72 0a 20 20 20 20 20 20 20 20  ort for.        
13e60 6e 61 6d 65 73 70 61 63 65 73 2c 20 76 61 6c 69  namespaces, vali
13e70 64 61 74 6f 72 73 2c 20 6d 65 74 61 2d 64 61 74  dators, meta-dat
13e80 61 2c 20 6f 6e 5f 63 68 61 6e 67 65 20 6c 69 73  a, on_change lis
13e90 74 65 6e 65 72 73 20 61 6e 64 20 6d 6f 72 65 2e  teners and more.
13ea0 0a 0a 20 20 20 20 20 20 20 20 54 68 69 73 20 73  ..        This s
13eb0 74 6f 72 61 67 65 20 69 73 20 6f 70 74 69 6d 69  torage is optimi
13ec0 7a 65 64 20 66 6f 72 20 66 61 73 74 20 72 65 61  zed for fast rea
13ed0 64 20 61 63 63 65 73 73 2e 20 52 65 74 72 69 65  d access. Retrie
13ee0 76 69 6e 67 20 61 20 6b 65 79 0a 20 20 20 20 20  ving a key.     
13ef0 20 20 20 6f 72 20 75 73 69 6e 67 20 6e 6f 6e 2d     or using non-
13f00 61 6c 74 65 72 69 6e 67 20 64 69 63 74 20 6d 65  altering dict me
13f10 74 68 6f 64 73 20 28 65 2e 67 2e 20 60 64 69 63  thods (e.g. `dic
13f20 74 2e 67 65 74 28 29 60 29 20 68 61 73 20 6e 6f  t.get()`) has no
13f30 20 6f 76 65 72 68 65 61 64 0a 20 20 20 20 20 20   overhead.      
13f40 20 20 63 6f 6d 70 61 72 65 64 20 74 6f 20 61 20    compared to a 
13f50 6e 61 74 69 76 65 20 64 69 63 74 2e 0a 20 20 20  native dict..   
13f60 20 27 27 27 0a 20 20 20 20 5f 5f 73 6c 6f 74 73   '''.    __slots
13f70 5f 5f 20 3d 20 28 27 5f 6d 65 74 61 27 2c 20 27  __ = ('_meta', '
13f80 5f 6f 6e 5f 63 68 61 6e 67 65 27 29 0a 0a 20 20  _on_change')..  
13f90 20 20 63 6c 61 73 73 20 4e 61 6d 65 73 70 61 63    class Namespac
13fa0 65 28 44 69 63 74 4d 69 78 69 6e 29 3a 0a 0a 20  e(DictMixin):.. 
13fb0 20 20 20 20 20 20 20 64 65 66 20 5f 5f 69 6e 69         def __ini
13fc0 74 5f 5f 28 73 65 6c 66 2c 20 63 6f 6e 66 69 67  t__(self, config
13fd0 2c 20 6e 61 6d 65 73 70 61 63 65 29 3a 0a 20 20  , namespace):.  
13fe0 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
13ff0 63 6f 6e 66 69 67 20 3d 20 63 6f 6e 66 69 67 0a  config = config.
14000 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
14010 2e 5f 70 72 65 66 69 78 20 3d 20 6e 61 6d 65 73  ._prefix = names
14020 70 61 63 65 0a 0a 20 20 20 20 20 20 20 20 64 65  pace..        de
14030 66 20 5f 5f 67 65 74 69 74 65 6d 5f 5f 28 73 65  f __getitem__(se
14040 6c 66 2c 20 6b 65 79 29 3a 0a 20 20 20 20 20 20  lf, key):.      
14050 20 20 20 20 20 20 64 65 70 72 28 27 41 63 63 65        depr('Acce
14060 73 73 69 6e 67 20 6e 61 6d 65 73 70 61 63 65 73  ssing namespaces
14070 20 61 73 20 64 69 63 74 73 20 69 73 20 64 69 73   as dicts is dis
14080 63 6f 75 72 61 67 65 64 2e 20 27 0a 20 20 20 20  couraged. '.    
14090 20 20 20 20 20 20 20 20 20 20 20 20 20 27 4f 6e               'On
140a0 6c 79 20 75 73 65 20 66 6c 61 74 20 69 74 65 6d  ly use flat item
140b0 20 61 63 63 65 73 73 3a 20 27 0a 20 20 20 20 20   access: '.     
140c0 20 20 20 20 20 20 20 20 20 20 20 20 27 63 66 67              'cfg
140d0 5b 22 6e 61 6d 65 73 22 5d 5b 22 70 61 63 65 22  ["names"]["pace"
140e0 5d 5b 22 6b 65 79 22 5d 20 2d 3e 20 63 66 67 5b  ]["key"] -> cfg[
140f0 22 6e 61 6d 65 2e 73 70 61 63 65 2e 6b 65 79 22  "name.space.key"
14100 5d 27 29 20 23 30 2e 31 32 0a 20 20 20 20 20 20  ]') #0.12.      
14110 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
14120 66 2e 5f 63 6f 6e 66 69 67 5b 73 65 6c 66 2e 5f  f._config[self._
14130 70 72 65 66 69 78 20 2b 20 27 2e 27 20 2b 20 6b  prefix + '.' + k
14140 65 79 5d 0a 0a 20 20 20 20 20 20 20 20 64 65 66  ey]..        def
14150 20 5f 5f 73 65 74 69 74 65 6d 5f 5f 28 73 65 6c   __setitem__(sel
14160 66 2c 20 6b 65 79 2c 20 76 61 6c 75 65 29 3a 0a  f, key, value):.
14170 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
14180 2e 5f 63 6f 6e 66 69 67 5b 73 65 6c 66 2e 5f 70  ._config[self._p
14190 72 65 66 69 78 20 2b 20 27 2e 27 20 2b 20 6b 65  refix + '.' + ke
141a0 79 5d 20 3d 20 76 61 6c 75 65 0a 0a 20 20 20 20  y] = value..    
141b0 20 20 20 20 64 65 66 20 5f 5f 64 65 6c 69 74 65      def __delite
141c0 6d 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 29 3a 0a  m__(self, key):.
141d0 20 20 20 20 20 20 20 20 20 20 20 20 64 65 6c 20              del 
141e0 73 65 6c 66 2e 5f 63 6f 6e 66 69 67 5b 73 65 6c  self._config[sel
141f0 66 2e 5f 70 72 65 66 69 78 20 2b 20 27 2e 27 20  f._prefix + '.' 
14200 2b 20 6b 65 79 5d 0a 0a 20 20 20 20 20 20 20 20  + key]..        
14210 64 65 66 20 5f 5f 69 74 65 72 5f 5f 28 73 65 6c  def __iter__(sel
14220 66 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  f):.            
14230 6e 73 5f 70 72 65 66 69 78 20 3d 20 73 65 6c 66  ns_prefix = self
14240 2e 5f 70 72 65 66 69 78 20 2b 20 27 2e 27 0a 20  ._prefix + '.'. 
14250 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 6b             for k
14260 65 79 20 69 6e 20 73 65 6c 66 2e 5f 63 6f 6e 66  ey in self._conf
14270 69 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ig:.            
14280 20 20 20 20 6e 73 2c 20 64 6f 74 2c 20 6e 61 6d      ns, dot, nam
14290 65 20 3d 20 6b 65 79 2e 72 70 61 72 74 69 74 69  e = key.rpartiti
142a0 6f 6e 28 27 2e 27 29 0a 20 20 20 20 20 20 20 20  on('.').        
142b0 20 20 20 20 20 20 20 20 69 66 20 6e 73 20 3d 3d          if ns ==
142c0 20 73 65 6c 66 2e 5f 70 72 65 66 69 78 20 61 6e   self._prefix an
142d0 64 20 6e 61 6d 65 3a 0a 20 20 20 20 20 20 20 20  d name:.        
142e0 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c              yiel
142f0 64 20 6e 61 6d 65 0a 0a 20 20 20 20 20 20 20 20  d name..        
14300 64 65 66 20 6b 65 79 73 28 73 65 6c 66 29 3a 20  def keys(self): 
14310 72 65 74 75 72 6e 20 5b 78 20 66 6f 72 20 78 20  return [x for x 
14320 69 6e 20 73 65 6c 66 5d 0a 20 20 20 20 20 20 20  in self].       
14330 20 64 65 66 20 5f 5f 6c 65 6e 5f 5f 28 73 65 6c   def __len__(sel
14340 66 29 3a 20 72 65 74 75 72 6e 20 6c 65 6e 28 73  f): return len(s
14350 65 6c 66 2e 6b 65 79 73 28 29 29 0a 20 20 20 20  elf.keys()).    
14360 20 20 20 20 64 65 66 20 5f 5f 63 6f 6e 74 61 69      def __contai
14370 6e 73 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 29 3a  ns__(self, key):
14380 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f 70 72   return self._pr
14390 65 66 69 78 20 2b 20 27 2e 27 20 2b 20 6b 65 79  efix + '.' + key
143a0 20 69 6e 20 73 65 6c 66 2e 5f 63 6f 6e 66 69 67   in self._config
143b0 0a 20 20 20 20 20 20 20 20 64 65 66 20 5f 5f 72  .        def __r
143c0 65 70 72 5f 5f 28 73 65 6c 66 29 3a 20 72 65 74  epr__(self): ret
143d0 75 72 6e 20 27 3c 43 6f 6e 66 69 67 2e 4e 61 6d  urn '<Config.Nam
143e0 65 73 70 61 63 65 20 25 73 2e 2a 3e 27 20 25 20  espace %s.*>' % 
143f0 73 65 6c 66 2e 5f 70 72 65 66 69 78 0a 20 20 20  self._prefix.   
14400 20 20 20 20 20 64 65 66 20 5f 5f 73 74 72 5f 5f       def __str__
14410 28 73 65 6c 66 29 3a 20 72 65 74 75 72 6e 20 27  (self): return '
14420 3c 43 6f 6e 66 69 67 2e 4e 61 6d 65 73 70 61 63  <Config.Namespac
14430 65 20 25 73 2e 2a 3e 27 20 25 20 73 65 6c 66 2e  e %s.*>' % self.
14440 5f 70 72 65 66 69 78 0a 0a 20 20 20 20 20 20 20  _prefix..       
14450 20 23 20 44 65 70 72 65 63 61 74 65 64 20 43 6f   # Deprecated Co
14460 6e 66 69 67 44 69 63 74 20 66 65 61 74 75 72 65  nfigDict feature
14470 73 0a 20 20 20 20 20 20 20 20 64 65 66 20 5f 5f  s.        def __
14480 67 65 74 61 74 74 72 5f 5f 28 73 65 6c 66 2c 20  getattr__(self, 
14490 6b 65 79 29 3a 0a 20 20 20 20 20 20 20 20 20 20  key):.          
144a0 20 20 64 65 70 72 28 27 41 74 74 72 69 62 75 74    depr('Attribut
144b0 65 20 61 63 63 65 73 73 20 69 73 20 64 65 70 72  e access is depr
144c0 65 63 61 74 65 64 2e 27 29 20 23 30 2e 31 32 0a  ecated.') #0.12.
144d0 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6b              if k
144e0 65 79 20 6e 6f 74 20 69 6e 20 73 65 6c 66 20 61  ey not in self a
144f0 6e 64 20 6b 65 79 5b 30 5d 2e 69 73 75 70 70 65  nd key[0].isuppe
14500 72 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  r():.           
14510 20 20 20 20 20 73 65 6c 66 5b 6b 65 79 5d 20 3d       self[key] =
14520 20 43 6f 6e 66 69 67 44 69 63 74 2e 4e 61 6d 65   ConfigDict.Name
14530 73 70 61 63 65 28 73 65 6c 66 2e 5f 63 6f 6e 66  space(self._conf
14540 69 67 2c 20 73 65 6c 66 2e 5f 70 72 65 66 69 78  ig, self._prefix
14550 20 2b 20 27 2e 27 20 2b 20 6b 65 79 29 0a 20 20   + '.' + key).  
14560 20 20 20 20 20 20 20 20 20 20 69 66 20 6b 65 79            if key
14570 20 6e 6f 74 20 69 6e 20 73 65 6c 66 20 61 6e 64   not in self and
14580 20 6b 65 79 2e 73 74 61 72 74 73 77 69 74 68 28   key.startswith(
14590 27 5f 5f 27 29 3a 0a 20 20 20 20 20 20 20 20 20  '__'):.         
145a0 20 20 20 20 20 20 20 72 61 69 73 65 20 41 74 74         raise Att
145b0 72 69 62 75 74 65 45 72 72 6f 72 28 6b 65 79 29  ributeError(key)
145c0 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
145d0 75 72 6e 20 73 65 6c 66 2e 67 65 74 28 6b 65 79  urn self.get(key
145e0 29 0a 0a 20 20 20 20 20 20 20 20 64 65 66 20 5f  )..        def _
145f0 5f 73 65 74 61 74 74 72 5f 5f 28 73 65 6c 66 2c  _setattr__(self,
14600 20 6b 65 79 2c 20 76 61 6c 75 65 29 3a 0a 20 20   key, value):.  
14610 20 20 20 20 20 20 20 20 20 20 69 66 20 6b 65 79            if key
14620 20 69 6e 20 28 27 5f 63 6f 6e 66 69 67 27 2c 20   in ('_config', 
14630 27 5f 70 72 65 66 69 78 27 29 3a 0a 20 20 20 20  '_prefix'):.    
14640 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
14650 2e 5f 5f 64 69 63 74 5f 5f 5b 6b 65 79 5d 20 3d  .__dict__[key] =
14660 20 76 61 6c 75 65 0a 20 20 20 20 20 20 20 20 20   value.         
14670 20 20 20 20 20 20 20 72 65 74 75 72 6e 0a 20 20         return.  
14680 20 20 20 20 20 20 20 20 20 20 64 65 70 72 28 27            depr('
14690 41 74 74 72 69 62 75 74 65 20 61 73 73 69 67 6e  Attribute assign
146a0 6d 65 6e 74 20 69 73 20 64 65 70 72 65 63 61 74  ment is deprecat
146b0 65 64 2e 27 29 20 23 30 2e 31 32 0a 20 20 20 20  ed.') #0.12.    
146c0 20 20 20 20 20 20 20 20 69 66 20 68 61 73 61 74          if hasat
146d0 74 72 28 44 69 63 74 4d 69 78 69 6e 2c 20 6b 65  tr(DictMixin, ke
146e0 79 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  y):.            
146f0 20 20 20 20 72 61 69 73 65 20 41 74 74 72 69 62      raise Attrib
14700 75 74 65 45 72 72 6f 72 28 27 52 65 61 64 2d 6f  uteError('Read-o
14710 6e 6c 79 20 61 74 74 72 69 62 75 74 65 2e 27 29  nly attribute.')
14720 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
14730 6b 65 79 20 69 6e 20 73 65 6c 66 20 61 6e 64 20  key in self and 
14740 73 65 6c 66 5b 6b 65 79 5d 20 61 6e 64 20 69 73  self[key] and is
14750 69 6e 73 74 61 6e 63 65 28 73 65 6c 66 5b 6b 65  instance(self[ke
14760 79 5d 2c 20 73 65 6c 66 2e 5f 5f 63 6c 61 73 73  y], self.__class
14770 5f 5f 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  __):.           
14780 20 20 20 20 20 72 61 69 73 65 20 41 74 74 72 69       raise Attri
14790 62 75 74 65 45 72 72 6f 72 28 27 4e 6f 6e 2d 65  buteError('Non-e
147a0 6d 70 74 79 20 6e 61 6d 65 73 70 61 63 65 20 61  mpty namespace a
147b0 74 74 72 69 62 75 74 65 2e 27 29 0a 20 20 20 20  ttribute.').    
147c0 20 20 20 20 20 20 20 20 73 65 6c 66 5b 6b 65 79          self[key
147d0 5d 20 3d 20 76 61 6c 75 65 0a 0a 20 20 20 20 20  ] = value..     
147e0 20 20 20 64 65 66 20 5f 5f 64 65 6c 61 74 74 72     def __delattr
147f0 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 29 3a 0a 20  __(self, key):. 
14800 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6b 65             if ke
14810 79 20 69 6e 20 73 65 6c 66 3a 0a 20 20 20 20 20  y in self:.     
14820 20 20 20 20 20 20 20 20 20 20 20 76 61 6c 20 3d             val =
14830 20 73 65 6c 66 2e 70 6f 70 28 6b 65 79 29 0a 20   self.pop(key). 
14840 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
14850 66 20 69 73 69 6e 73 74 61 6e 63 65 28 76 61 6c  f isinstance(val
14860 2c 20 73 65 6c 66 2e 5f 5f 63 6c 61 73 73 5f 5f  , self.__class__
14870 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
14880 20 20 20 20 20 20 20 70 72 65 66 69 78 20 3d 20         prefix = 
14890 6b 65 79 20 2b 20 27 2e 27 0a 20 20 20 20 20 20  key + '.'.      
148a0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
148b0 72 20 6b 65 79 20 69 6e 20 73 65 6c 66 3a 0a 20  r key in self:. 
148c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
148d0 20 20 20 20 20 20 20 69 66 20 6b 65 79 2e 73 74         if key.st
148e0 61 72 74 73 77 69 74 68 28 70 72 65 66 69 78 29  artswith(prefix)
148f0 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
14900 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 65                de
14910 6c 20 73 65 6c 66 5b 70 72 65 66 69 78 2b 6b 65  l self[prefix+ke
14920 79 5d 0a 0a 20 20 20 20 20 20 20 20 64 65 66 20  y]..        def 
14930 5f 5f 63 61 6c 6c 5f 5f 28 73 65 6c 66 2c 20 2a  __call__(self, *
14940 61 2c 20 2a 2a 6b 61 29 3a 0a 20 20 20 20 20 20  a, **ka):.      
14950 20 20 20 20 20 20 64 65 70 72 28 27 43 61 6c 6c        depr('Call
14960 69 6e 67 20 43 6f 6e 66 44 69 63 74 20 69 73 20  ing ConfDict is 
14970 64 65 70 72 65 63 61 74 65 64 2e 20 55 73 65 20  deprecated. Use 
14980 74 68 65 20 75 70 64 61 74 65 28 29 20 6d 65 74  the update() met
14990 68 6f 64 2e 27 29 20 23 30 2e 31 32 0a 20 20 20  hod.') #0.12.   
149a0 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 75 70           self.up
149b0 64 61 74 65 28 2a 61 2c 20 2a 2a 6b 61 29 0a 20  date(*a, **ka). 
149c0 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
149d0 6e 20 73 65 6c 66 0a 0a 20 20 20 20 64 65 66 20  n self..    def 
149e0 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 2a  __init__(self, *
149f0 61 2c 20 2a 2a 6b 61 29 3a 0a 20 20 20 20 20 20  a, **ka):.      
14a00 20 20 73 65 6c 66 2e 5f 6d 65 74 61 20 3d 20 7b    self._meta = {
14a10 7d 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f  }.        self._
14a20 6f 6e 5f 63 68 61 6e 67 65 20 3d 20 6c 61 6d 62  on_change = lamb
14a30 64 61 20 6e 61 6d 65 2c 20 76 61 6c 75 65 3a 20  da name, value: 
14a40 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 69 66 20  None.        if 
14a50 61 20 6f 72 20 6b 61 3a 0a 20 20 20 20 20 20 20  a or ka:.       
14a60 20 20 20 20 20 64 65 70 72 28 27 43 6f 6e 73 74       depr('Const
14a70 72 75 63 74 6f 72 20 64 6f 65 73 20 6e 6f 20 6c  ructor does no l
14a80 6f 6e 67 65 72 20 61 63 63 65 70 74 20 70 61 72  onger accept par
14a90 61 6d 65 74 65 72 73 2e 27 29 20 23 30 2e 31 32  ameters.') #0.12
14aa0 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
14ab0 66 2e 75 70 64 61 74 65 28 2a 61 2c 20 2a 2a 6b  f.update(*a, **k
14ac0 61 29 0a 0a 20 20 20 20 64 65 66 20 6c 6f 61 64  a)..    def load
14ad0 5f 63 6f 6e 66 69 67 28 73 65 6c 66 2c 20 66 69  _config(self, fi
14ae0 6c 65 6e 61 6d 65 29 3a 0a 20 20 20 20 20 20 20  lename):.       
14af0 20 27 27 27 20 4c 6f 61 64 20 76 61 6c 75 65 73   ''' Load values
14b00 20 66 72 6f 6d 20 61 6e 20 2a 2e 69 6e 69 20 73   from an *.ini s
14b10 74 79 6c 65 20 63 6f 6e 66 69 67 20 66 69 6c 65  tyle config file
14b20 2e 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 49  ...            I
14b30 66 20 74 68 65 20 63 6f 6e 66 69 67 20 66 69 6c  f the config fil
14b40 65 20 63 6f 6e 74 61 69 6e 73 20 73 65 63 74 69  e contains secti
14b50 6f 6e 73 2c 20 74 68 65 69 72 20 6e 61 6d 65 73  ons, their names
14b60 20 61 72 65 20 75 73 65 64 20 61 73 0a 20 20 20   are used as.   
14b70 20 20 20 20 20 20 20 20 20 6e 61 6d 65 73 70 61           namespa
14b80 63 65 73 20 66 6f 72 20 74 68 65 20 76 61 6c 75  ces for the valu
14b90 65 73 20 77 69 74 68 69 6e 2e 20 54 68 65 20 74  es within. The t
14ba0 77 6f 20 73 70 65 63 69 61 6c 20 73 65 63 74 69  wo special secti
14bb0 6f 6e 73 0a 20 20 20 20 20 20 20 20 20 20 20 20  ons.            
14bc0 60 60 44 45 46 41 55 4c 54 60 60 20 61 6e 64 20  ``DEFAULT`` and 
14bd0 60 60 62 6f 74 74 6c 65 60 60 20 72 65 66 65 72  ``bottle`` refer
14be0 20 74 6f 20 74 68 65 20 72 6f 6f 74 20 6e 61 6d   to the root nam
14bf0 65 73 70 61 63 65 20 28 6e 6f 20 70 72 65 66 69  espace (no prefi
14c00 78 29 2e 0a 20 20 20 20 20 20 20 20 27 27 27 0a  x)..        '''.
14c10 20 20 20 20 20 20 20 20 63 6f 6e 66 20 3d 20 43          conf = C
14c20 6f 6e 66 69 67 50 61 72 73 65 72 28 29 0a 20 20  onfigParser().  
14c30 20 20 20 20 20 20 63 6f 6e 66 2e 72 65 61 64 28        conf.read(
14c40 66 69 6c 65 6e 61 6d 65 29 0a 20 20 20 20 20 20  filename).      
14c50 20 20 66 6f 72 20 73 65 63 74 69 6f 6e 20 69 6e    for section in
14c60 20 63 6f 6e 66 2e 73 65 63 74 69 6f 6e 73 28 29   conf.sections()
14c70 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f  :.            fo
14c80 72 20 6b 65 79 2c 20 76 61 6c 75 65 20 69 6e 20  r key, value in 
14c90 63 6f 6e 66 2e 69 74 65 6d 73 28 73 65 63 74 69  conf.items(secti
14ca0 6f 6e 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  on):.           
14cb0 20 20 20 20 20 69 66 20 73 65 63 74 69 6f 6e 20       if section 
14cc0 6e 6f 74 20 69 6e 20 28 27 44 45 46 41 55 4c 54  not in ('DEFAULT
14cd0 27 2c 20 27 62 6f 74 74 6c 65 27 29 3a 0a 20 20  ', 'bottle'):.  
14ce0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
14cf0 20 20 6b 65 79 20 3d 20 73 65 63 74 69 6f 6e 20    key = section 
14d00 2b 20 27 2e 27 20 2b 20 6b 65 79 0a 20 20 20 20  + '.' + key.    
14d10 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
14d20 5b 6b 65 79 5d 20 3d 20 76 61 6c 75 65 0a 20 20  [key] = value.  
14d30 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
14d40 66 0a 0a 20 20 20 20 64 65 66 20 6c 6f 61 64 5f  f..    def load_
14d50 64 69 63 74 28 73 65 6c 66 2c 20 73 6f 75 72 63  dict(self, sourc
14d60 65 2c 20 6e 61 6d 65 73 70 61 63 65 3d 27 27 2c  e, namespace='',
14d70 20 6d 61 6b 65 5f 6e 61 6d 65 73 70 61 63 65 73   make_namespaces
14d80 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20  =False):.       
14d90 20 27 27 27 20 49 6d 70 6f 72 74 20 76 61 6c 75   ''' Import valu
14da0 65 73 20 66 72 6f 6d 20 61 20 64 69 63 74 69 6f  es from a dictio
14db0 6e 61 72 79 20 73 74 72 75 63 74 75 72 65 2e 20  nary structure. 
14dc0 4e 65 73 74 69 6e 67 20 63 61 6e 20 62 65 20 75  Nesting can be u
14dd0 73 65 64 20 74 6f 0a 20 20 20 20 20 20 20 20 20  sed to.         
14de0 20 20 20 72 65 70 72 65 73 65 6e 74 20 6e 61 6d     represent nam
14df0 65 73 70 61 63 65 73 2e 0a 0a 20 20 20 20 20 20  espaces...      
14e00 20 20 20 20 20 20 3e 3e 3e 20 43 6f 6e 66 69 67        >>> Config
14e10 44 69 63 74 28 29 2e 6c 6f 61 64 5f 64 69 63 74  Dict().load_dict
14e20 28 7b 27 6e 61 6d 65 27 3a 20 7b 27 73 70 61 63  ({'name': {'spac
14e30 65 27 3a 20 7b 27 6b 65 79 27 3a 20 27 76 61 6c  e': {'key': 'val
14e40 75 65 27 7d 7d 7d 29 0a 20 20 20 20 20 20 20 20  ue'}}}).        
14e50 20 20 20 20 7b 27 6e 61 6d 65 2e 73 70 61 63 65      {'name.space
14e60 2e 6b 65 79 27 3a 20 27 76 61 6c 75 65 27 7d 0a  .key': 'value'}.
14e70 20 20 20 20 20 20 20 20 27 27 27 0a 20 20 20 20          '''.    
14e80 20 20 20 20 73 74 61 63 6b 20 3d 20 5b 28 6e 61      stack = [(na
14e90 6d 65 73 70 61 63 65 2c 20 73 6f 75 72 63 65 29  mespace, source)
14ea0 5d 0a 20 20 20 20 20 20 20 20 77 68 69 6c 65 20  ].        while 
14eb0 73 74 61 63 6b 3a 0a 20 20 20 20 20 20 20 20 20  stack:.         
14ec0 20 20 20 70 72 65 66 69 78 2c 20 73 6f 75 72 63     prefix, sourc
14ed0 65 20 3d 20 73 74 61 63 6b 2e 70 6f 70 28 29 0a  e = stack.pop().
14ee0 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
14ef0 6f 74 20 69 73 69 6e 73 74 61 6e 63 65 28 73 6f  ot isinstance(so
14f00 75 72 63 65 2c 20 64 69 63 74 29 3a 0a 20 20 20  urce, dict):.   
14f10 20 20 20 20 20 20 20 20 20 20 20 20 20 72 61 69               rai
14f20 73 65 20 54 79 70 65 45 72 72 6f 72 28 27 53 6f  se TypeError('So
14f30 75 72 63 65 20 69 73 20 6e 6f 74 20 61 20 64 69  urce is not a di
14f40 63 74 20 28 72 29 27 20 25 20 74 79 70 65 28 6b  ct (r)' % type(k
14f50 65 79 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  ey)).           
14f60 20 66 6f 72 20 6b 65 79 2c 20 76 61 6c 75 65 20   for key, value 
14f70 69 6e 20 73 6f 75 72 63 65 2e 69 74 65 6d 73 28  in source.items(
14f80 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
14f90 20 20 20 69 66 20 6e 6f 74 20 69 73 69 6e 73 74     if not isinst
14fa0 61 6e 63 65 28 6b 65 79 2c 20 62 61 73 65 73 74  ance(key, basest
14fb0 72 69 6e 67 29 3a 0a 20 20 20 20 20 20 20 20 20  ring):.         
14fc0 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65             raise
14fd0 20 54 79 70 65 45 72 72 6f 72 28 27 4b 65 79 20   TypeError('Key 
14fe0 69 73 20 6e 6f 74 20 61 20 73 74 72 69 6e 67 20  is not a string 
14ff0 28 25 72 29 27 20 25 20 74 79 70 65 28 6b 65 79  (%r)' % type(key
15000 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
15010 20 20 20 66 75 6c 6c 5f 6b 65 79 20 3d 20 70 72     full_key = pr
15020 65 66 69 78 20 2b 20 27 2e 27 20 2b 20 6b 65 79  efix + '.' + key
15030 20 69 66 20 70 72 65 66 69 78 20 65 6c 73 65 20   if prefix else 
15040 6b 65 79 0a 20 20 20 20 20 20 20 20 20 20 20 20  key.            
15050 20 20 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63      if isinstanc
15060 65 28 76 61 6c 75 65 2c 20 64 69 63 74 29 3a 0a  e(value, dict):.
15070 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15080 20 20 20 20 73 74 61 63 6b 2e 61 70 70 65 6e 64      stack.append
15090 28 28 66 75 6c 6c 5f 6b 65 79 2c 20 76 61 6c 75  ((full_key, valu
150a0 65 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  e)).            
150b0 20 20 20 20 20 20 20 20 69 66 20 6d 61 6b 65 5f          if make_
150c0 6e 61 6d 65 73 70 61 63 65 73 3a 0a 20 20 20 20  namespaces:.    
150d0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
150e0 20 20 20 20 73 65 6c 66 5b 66 75 6c 6c 5f 6b 65      self[full_ke
150f0 79 5d 20 3d 20 73 65 6c 66 2e 4e 61 6d 65 73 70  y] = self.Namesp
15100 61 63 65 28 73 65 6c 66 2c 20 66 75 6c 6c 5f 6b  ace(self, full_k
15110 65 79 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ey).            
15120 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
15130 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
15140 6c 66 5b 66 75 6c 6c 5f 6b 65 79 5d 20 3d 20 76  lf[full_key] = v
15150 61 6c 75 65 0a 20 20 20 20 20 20 20 20 72 65 74  alue.        ret
15160 75 72 6e 20 73 65 6c 66 0a 0a 20 20 20 20 64 65  urn self..    de
15170 66 20 75 70 64 61 74 65 28 73 65 6c 66 2c 20 2a  f update(self, *
15180 61 2c 20 2a 2a 6b 61 29 3a 0a 20 20 20 20 20 20  a, **ka):.      
15190 20 20 27 27 27 20 49 66 20 74 68 65 20 66 69 72    ''' If the fir
151a0 73 74 20 70 61 72 61 6d 65 74 65 72 20 69 73 20  st parameter is 
151b0 61 20 73 74 72 69 6e 67 2c 20 61 6c 6c 20 6b 65  a string, all ke
151c0 79 73 20 61 72 65 20 70 72 65 66 69 78 65 64 20  ys are prefixed 
151d0 77 69 74 68 20 74 68 69 73 0a 20 20 20 20 20 20  with this.      
151e0 20 20 20 20 20 20 6e 61 6d 65 73 70 61 63 65 2e        namespace.
151f0 20 41 70 61 72 74 20 66 72 6f 6d 20 74 68 61 74   Apart from that
15200 20 69 74 20 77 6f 72 6b 73 20 6a 75 73 74 20 61   it works just a
15210 73 20 74 68 65 20 75 73 75 61 6c 20 64 69 63 74  s the usual dict
15220 2e 75 70 64 61 74 65 28 29 2e 0a 20 20 20 20 20  .update()..     
15230 20 20 20 20 20 20 20 45 78 61 6d 70 6c 65 3a 20         Example: 
15240 60 60 75 70 64 61 74 65 28 27 73 6f 6d 65 2e 6e  ``update('some.n
15250 61 6d 65 73 70 61 63 65 27 2c 20 6b 65 79 3d 27  amespace', key='
15260 76 61 6c 75 65 27 29 60 60 20 27 27 27 0a 20 20  value')`` '''.  
15270 20 20 20 20 20 20 70 72 65 66 69 78 20 3d 20 27        prefix = '
15280 27 0a 20 20 20 20 20 20 20 20 69 66 20 61 20 61  '.        if a a
15290 6e 64 20 69 73 69 6e 73 74 61 6e 63 65 28 61 5b  nd isinstance(a[
152a0 30 5d 2c 20 62 61 73 65 73 74 72 69 6e 67 29 3a  0], basestring):
152b0 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72 65  .            pre
152c0 66 69 78 20 3d 20 61 5b 30 5d 2e 73 74 72 69 70  fix = a[0].strip
152d0 28 27 2e 27 29 20 2b 20 27 2e 27 0a 20 20 20 20  ('.') + '.'.    
152e0 20 20 20 20 20 20 20 20 61 20 3d 20 61 5b 31 3a          a = a[1:
152f0 5d 0a 20 20 20 20 20 20 20 20 66 6f 72 20 6b 65  ].        for ke
15300 79 2c 20 76 61 6c 75 65 20 69 6e 20 64 69 63 74  y, value in dict
15310 28 2a 61 2c 20 2a 2a 6b 61 29 2e 69 74 65 6d 73  (*a, **ka).items
15320 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ():.            
15330 73 65 6c 66 5b 70 72 65 66 69 78 2b 6b 65 79 5d  self[prefix+key]
15340 20 3d 20 76 61 6c 75 65 0a 0a 20 20 20 20 64 65   = value..    de
15350 66 20 73 65 74 64 65 66 61 75 6c 74 28 73 65 6c  f setdefault(sel
15360 66 2c 20 6b 65 79 2c 20 76 61 6c 75 65 29 3a 0a  f, key, value):.
15370 20 20 20 20 20 20 20 20 69 66 20 6b 65 79 20 6e          if key n
15380 6f 74 20 69 6e 20 73 65 6c 66 3a 0a 20 20 20 20  ot in self:.    
15390 20 20 20 20 20 20 20 20 73 65 6c 66 5b 6b 65 79          self[key
153a0 5d 20 3d 20 76 61 6c 75 65 0a 20 20 20 20 20 20  ] = value.      
153b0 20 20 72 65 74 75 72 6e 20 73 65 6c 66 5b 6b 65    return self[ke
153c0 79 5d 0a 0a 20 20 20 20 64 65 66 20 5f 5f 73 65  y]..    def __se
153d0 74 69 74 65 6d 5f 5f 28 73 65 6c 66 2c 20 6b 65  titem__(self, ke
153e0 79 2c 20 76 61 6c 75 65 29 3a 0a 20 20 20 20 20  y, value):.     
153f0 20 20 20 69 66 20 6e 6f 74 20 69 73 69 6e 73 74     if not isinst
15400 61 6e 63 65 28 6b 65 79 2c 20 62 61 73 65 73 74  ance(key, basest
15410 72 69 6e 67 29 3a 0a 20 20 20 20 20 20 20 20 20  ring):.         
15420 20 20 20 72 61 69 73 65 20 54 79 70 65 45 72 72     raise TypeErr
15430 6f 72 28 27 4b 65 79 20 68 61 73 20 74 79 70 65  or('Key has type
15440 20 25 72 20 28 6e 6f 74 20 61 20 73 74 72 69 6e   %r (not a strin
15450 67 29 27 20 25 20 74 79 70 65 28 6b 65 79 29 29  g)' % type(key))
15460 0a 0a 20 20 20 20 20 20 20 20 76 61 6c 75 65 20  ..        value 
15470 3d 20 73 65 6c 66 2e 6d 65 74 61 5f 67 65 74 28  = self.meta_get(
15480 6b 65 79 2c 20 27 66 69 6c 74 65 72 27 2c 20 6c  key, 'filter', l
15490 61 6d 62 64 61 20 78 3a 20 78 29 28 76 61 6c 75  ambda x: x)(valu
154a0 65 29 0a 20 20 20 20 20 20 20 20 69 66 20 6b 65  e).        if ke
154b0 79 20 69 6e 20 73 65 6c 66 20 61 6e 64 20 73 65  y in self and se
154c0 6c 66 5b 6b 65 79 5d 20 69 73 20 76 61 6c 75 65  lf[key] is value
154d0 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
154e0 74 75 72 6e 0a 20 20 20 20 20 20 20 20 73 65 6c  turn.        sel
154f0 66 2e 5f 6f 6e 5f 63 68 61 6e 67 65 28 6b 65 79  f._on_change(key
15500 2c 20 76 61 6c 75 65 29 0a 20 20 20 20 20 20 20  , value).       
15510 20 64 69 63 74 2e 5f 5f 73 65 74 69 74 65 6d 5f   dict.__setitem_
15520 5f 28 73 65 6c 66 2c 20 6b 65 79 2c 20 76 61 6c  _(self, key, val
15530 75 65 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 64  ue)..    def __d
15540 65 6c 69 74 65 6d 5f 5f 28 73 65 6c 66 2c 20 6b  elitem__(self, k
15550 65 79 29 3a 0a 20 20 20 20 20 20 20 20 64 69 63  ey):.        dic
15560 74 2e 5f 5f 64 65 6c 69 74 65 6d 5f 5f 28 73 65  t.__delitem__(se
15570 6c 66 2c 20 6b 65 79 29 0a 0a 20 20 20 20 64 65  lf, key)..    de
15580 66 20 63 6c 65 61 72 28 73 65 6c 66 29 3a 0a 20  f clear(self):. 
15590 20 20 20 20 20 20 20 66 6f 72 20 6b 65 79 20 69         for key i
155a0 6e 20 73 65 6c 66 3a 0a 20 20 20 20 20 20 20 20  n self:.        
155b0 20 20 20 20 64 65 6c 20 73 65 6c 66 5b 6b 65 79      del self[key
155c0 5d 0a 0a 20 20 20 20 64 65 66 20 6d 65 74 61 5f  ]..    def meta_
155d0 67 65 74 28 73 65 6c 66 2c 20 6b 65 79 2c 20 6d  get(self, key, m
155e0 65 74 61 66 69 65 6c 64 2c 20 64 65 66 61 75 6c  etafield, defaul
155f0 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20  t=None):.       
15600 20 27 27 27 20 52 65 74 75 72 6e 20 74 68 65 20   ''' Return the 
15610 76 61 6c 75 65 20 6f 66 20 61 20 6d 65 74 61 20  value of a meta 
15620 66 69 65 6c 64 20 66 6f 72 20 61 20 6b 65 79 2e  field for a key.
15630 20 27 27 27 0a 20 20 20 20 20 20 20 20 72 65 74   '''.        ret
15640 75 72 6e 20 73 65 6c 66 2e 5f 6d 65 74 61 2e 67  urn self._meta.g
15650 65 74 28 6b 65 79 2c 20 7b 7d 29 2e 67 65 74 28  et(key, {}).get(
15660 6d 65 74 61 66 69 65 6c 64 2c 20 64 65 66 61 75  metafield, defau
15670 6c 74 29 0a 0a 20 20 20 20 64 65 66 20 6d 65 74  lt)..    def met
15680 61 5f 73 65 74 28 73 65 6c 66 2c 20 6b 65 79 2c  a_set(self, key,
15690 20 6d 65 74 61 66 69 65 6c 64 2c 20 76 61 6c 75   metafield, valu
156a0 65 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20  e):.        ''' 
156b0 53 65 74 20 74 68 65 20 6d 65 74 61 20 66 69 65  Set the meta fie
156c0 6c 64 20 66 6f 72 20 61 20 6b 65 79 20 74 6f 20  ld for a key to 
156d0 61 20 6e 65 77 20 76 61 6c 75 65 2e 20 54 68 69  a new value. Thi
156e0 73 20 74 72 69 67 67 65 72 73 20 74 68 65 0a 20  s triggers the. 
156f0 20 20 20 20 20 20 20 20 20 20 20 6f 6e 2d 63 68             on-ch
15700 61 6e 67 65 20 68 61 6e 64 6c 65 72 20 66 6f 72  ange handler for
15710 20 65 78 69 73 74 69 6e 67 20 6b 65 79 73 2e 20   existing keys. 
15720 27 27 27 0a 20 20 20 20 20 20 20 20 73 65 6c 66  '''.        self
15730 2e 5f 6d 65 74 61 2e 73 65 74 64 65 66 61 75 6c  ._meta.setdefaul
15740 74 28 6b 65 79 2c 20 7b 7d 29 5b 6d 65 74 61 66  t(key, {})[metaf
15750 69 65 6c 64 5d 20 3d 20 76 61 6c 75 65 0a 20 20  ield] = value.  
15760 20 20 20 20 20 20 69 66 20 6b 65 79 20 69 6e 20        if key in 
15770 73 65 6c 66 3a 0a 20 20 20 20 20 20 20 20 20 20  self:.          
15780 20 20 73 65 6c 66 5b 6b 65 79 5d 20 3d 20 73 65    self[key] = se
15790 6c 66 5b 6b 65 79 5d 0a 0a 20 20 20 20 64 65 66  lf[key]..    def
157a0 20 6d 65 74 61 5f 6c 69 73 74 28 73 65 6c 66 2c   meta_list(self,
157b0 20 6b 65 79 29 3a 0a 20 20 20 20 20 20 20 20 27   key):.        '
157c0 27 27 20 52 65 74 75 72 6e 20 61 6e 20 69 74 65  '' Return an ite
157d0 72 61 62 6c 65 20 6f 66 20 6d 65 74 61 20 66 69  rable of meta fi
157e0 65 6c 64 20 6e 61 6d 65 73 20 64 65 66 69 6e 65  eld names define
157f0 64 20 66 6f 72 20 61 20 6b 65 79 2e 20 27 27 27  d for a key. '''
15800 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
15810 73 65 6c 66 2e 5f 6d 65 74 61 2e 67 65 74 28 6b  self._meta.get(k
15820 65 79 2c 20 7b 7d 29 2e 6b 65 79 73 28 29 0a 0a  ey, {}).keys()..
15830 20 20 20 20 23 20 44 65 70 72 65 63 61 74 65 64      # Deprecated
15840 20 43 6f 6e 66 69 67 44 69 63 74 20 66 65 61 74   ConfigDict feat
15850 75 72 65 73 0a 20 20 20 20 64 65 66 20 5f 5f 67  ures.    def __g
15860 65 74 61 74 74 72 5f 5f 28 73 65 6c 66 2c 20 6b  etattr__(self, k
15870 65 79 29 3a 0a 20 20 20 20 20 20 20 20 64 65 70  ey):.        dep
15880 72 28 27 41 74 74 72 69 62 75 74 65 20 61 63 63  r('Attribute acc
15890 65 73 73 20 69 73 20 64 65 70 72 65 63 61 74 65  ess is deprecate
158a0 64 2e 27 29 20 23 30 2e 31 32 0a 20 20 20 20 20  d.') #0.12.     
158b0 20 20 20 69 66 20 6b 65 79 20 6e 6f 74 20 69 6e     if key not in
158c0 20 73 65 6c 66 20 61 6e 64 20 6b 65 79 5b 30 5d   self and key[0]
158d0 2e 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20  .isupper():.    
158e0 20 20 20 20 20 20 20 20 73 65 6c 66 5b 6b 65 79          self[key
158f0 5d 20 3d 20 73 65 6c 66 2e 4e 61 6d 65 73 70 61  ] = self.Namespa
15900 63 65 28 73 65 6c 66 2c 20 6b 65 79 29 0a 20 20  ce(self, key).  
15910 20 20 20 20 20 20 69 66 20 6b 65 79 20 6e 6f 74        if key not
15920 20 69 6e 20 73 65 6c 66 20 61 6e 64 20 6b 65 79   in self and key
15930 2e 73 74 61 72 74 73 77 69 74 68 28 27 5f 5f 27  .startswith('__'
15940 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  ):.            r
15950 61 69 73 65 20 41 74 74 72 69 62 75 74 65 45 72  aise AttributeEr
15960 72 6f 72 28 6b 65 79 29 0a 20 20 20 20 20 20 20  ror(key).       
15970 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 67 65 74   return self.get
15980 28 6b 65 79 29 0a 0a 20 20 20 20 64 65 66 20 5f  (key)..    def _
15990 5f 73 65 74 61 74 74 72 5f 5f 28 73 65 6c 66 2c  _setattr__(self,
159a0 20 6b 65 79 2c 20 76 61 6c 75 65 29 3a 0a 20 20   key, value):.  
159b0 20 20 20 20 20 20 69 66 20 6b 65 79 20 69 6e 20        if key in 
159c0 73 65 6c 66 2e 5f 5f 73 6c 6f 74 73 5f 5f 3a 0a  self.__slots__:.
159d0 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
159e0 72 6e 20 64 69 63 74 2e 5f 5f 73 65 74 61 74 74  rn dict.__setatt
159f0 72 5f 5f 28 73 65 6c 66 2c 20 6b 65 79 2c 20 76  r__(self, key, v
15a00 61 6c 75 65 29 0a 20 20 20 20 20 20 20 20 64 65  alue).        de
15a10 70 72 28 27 41 74 74 72 69 62 75 74 65 20 61 73  pr('Attribute as
15a20 73 69 67 6e 6d 65 6e 74 20 69 73 20 64 65 70 72  signment is depr
15a30 65 63 61 74 65 64 2e 27 29 20 23 30 2e 31 32 0a  ecated.') #0.12.
15a40 20 20 20 20 20 20 20 20 69 66 20 68 61 73 61 74          if hasat
15a50 74 72 28 64 69 63 74 2c 20 6b 65 79 29 3a 0a 20  tr(dict, key):. 
15a60 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65             raise
15a70 20 41 74 74 72 69 62 75 74 65 45 72 72 6f 72 28   AttributeError(
15a80 27 52 65 61 64 2d 6f 6e 6c 79 20 61 74 74 72 69  'Read-only attri
15a90 62 75 74 65 2e 27 29 0a 20 20 20 20 20 20 20 20  bute.').        
15aa0 69 66 20 6b 65 79 20 69 6e 20 73 65 6c 66 20 61  if key in self a
15ab0 6e 64 20 73 65 6c 66 5b 6b 65 79 5d 20 61 6e 64  nd self[key] and
15ac0 20 69 73 69 6e 73 74 61 6e 63 65 28 73 65 6c 66   isinstance(self
15ad0 5b 6b 65 79 5d 2c 20 73 65 6c 66 2e 4e 61 6d 65  [key], self.Name
15ae0 73 70 61 63 65 29 3a 0a 20 20 20 20 20 20 20 20  space):.        
15af0 20 20 20 20 72 61 69 73 65 20 41 74 74 72 69 62      raise Attrib
15b00 75 74 65 45 72 72 6f 72 28 27 4e 6f 6e 2d 65 6d  uteError('Non-em
15b10 70 74 79 20 6e 61 6d 65 73 70 61 63 65 20 61 74  pty namespace at
15b20 74 72 69 62 75 74 65 2e 27 29 0a 20 20 20 20 20  tribute.').     
15b30 20 20 20 73 65 6c 66 5b 6b 65 79 5d 20 3d 20 76     self[key] = v
15b40 61 6c 75 65 0a 0a 20 20 20 20 64 65 66 20 5f 5f  alue..    def __
15b50 64 65 6c 61 74 74 72 5f 5f 28 73 65 6c 66 2c 20  delattr__(self, 
15b60 6b 65 79 29 3a 0a 20 20 20 20 20 20 20 20 69 66  key):.        if
15b70 20 6b 65 79 20 69 6e 20 73 65 6c 66 3a 0a 20 20   key in self:.  
15b80 20 20 20 20 20 20 20 20 20 20 76 61 6c 20 3d 20            val = 
15b90 73 65 6c 66 2e 70 6f 70 28 6b 65 79 29 0a 20 20  self.pop(key).  
15ba0 20 20 20 20 20 20 20 20 20 20 69 66 20 69 73 69            if isi
15bb0 6e 73 74 61 6e 63 65 28 76 61 6c 2c 20 73 65 6c  nstance(val, sel
15bc0 66 2e 4e 61 6d 65 73 70 61 63 65 29 3a 0a 20 20  f.Namespace):.  
15bd0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72                pr
15be0 65 66 69 78 20 3d 20 6b 65 79 20 2b 20 27 2e 27  efix = key + '.'
15bf0 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
15c00 20 66 6f 72 20 6b 65 79 20 69 6e 20 73 65 6c 66   for key in self
15c10 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
15c20 20 20 20 20 20 20 69 66 20 6b 65 79 2e 73 74 61        if key.sta
15c30 72 74 73 77 69 74 68 28 70 72 65 66 69 78 29 3a  rtswith(prefix):
15c40 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
15c50 20 20 20 20 20 20 20 20 20 64 65 6c 20 73 65 6c           del sel
15c60 66 5b 70 72 65 66 69 78 2b 6b 65 79 5d 0a 0a 20  f[prefix+key].. 
15c70 20 20 20 64 65 66 20 5f 5f 63 61 6c 6c 5f 5f 28     def __call__(
15c80 73 65 6c 66 2c 20 2a 61 2c 20 2a 2a 6b 61 29 3a  self, *a, **ka):
15c90 0a 20 20 20 20 20 20 20 20 64 65 70 72 28 27 43  .        depr('C
15ca0 61 6c 6c 69 6e 67 20 43 6f 6e 66 44 69 63 74 20  alling ConfDict 
15cb0 69 73 20 64 65 70 72 65 63 61 74 65 64 2e 20 55  is deprecated. U
15cc0 73 65 20 74 68 65 20 75 70 64 61 74 65 28 29 20  se the update() 
15cd0 6d 65 74 68 6f 64 2e 27 29 20 23 30 2e 31 32 0a  method.') #0.12.
15ce0 20 20 20 20 20 20 20 20 73 65 6c 66 2e 75 70 64          self.upd
15cf0 61 74 65 28 2a 61 2c 20 2a 2a 6b 61 29 0a 20 20  ate(*a, **ka).  
15d00 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
15d10 66 0a 0a 0a 0a 63 6c 61 73 73 20 41 70 70 53 74  f....class AppSt
15d20 61 63 6b 28 6c 69 73 74 29 3a 0a 20 20 20 20 22  ack(list):.    "
15d30 22 22 20 41 20 73 74 61 63 6b 2d 6c 69 6b 65 20  "" A stack-like 
15d40 6c 69 73 74 2e 20 43 61 6c 6c 69 6e 67 20 69 74  list. Calling it
15d50 20 72 65 74 75 72 6e 73 20 74 68 65 20 68 65 61   returns the hea
15d60 64 20 6f 66 20 74 68 65 20 73 74 61 63 6b 2e 20  d of the stack. 
15d70 22 22 22 0a 0a 20 20 20 20 64 65 66 20 5f 5f 63  """..    def __c
15d80 61 6c 6c 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20  all__(self):.   
15d90 20 20 20 20 20 22 22 22 20 52 65 74 75 72 6e 20       """ Return 
15da0 74 68 65 20 63 75 72 72 65 6e 74 20 64 65 66 61  the current defa
15db0 75 6c 74 20 61 70 70 6c 69 63 61 74 69 6f 6e 2e  ult application.
15dc0 20 22 22 22 0a 20 20 20 20 20 20 20 20 72 65 74   """.        ret
15dd0 75 72 6e 20 73 65 6c 66 5b 2d 31 5d 0a 0a 20 20  urn self[-1]..  
15de0 20 20 64 65 66 20 70 75 73 68 28 73 65 6c 66 2c    def push(self,
15df0 20 76 61 6c 75 65 3d 4e 6f 6e 65 29 3a 0a 20 20   value=None):.  
15e00 20 20 20 20 20 20 22 22 22 20 41 64 64 20 61 20        """ Add a 
15e10 6e 65 77 20 3a 63 6c 61 73 73 3a 60 42 6f 74 74  new :class:`Bott
15e20 6c 65 60 20 69 6e 73 74 61 6e 63 65 20 74 6f 20  le` instance to 
15e30 74 68 65 20 73 74 61 63 6b 20 22 22 22 0a 20 20  the stack """.  
15e40 20 20 20 20 20 20 69 66 20 6e 6f 74 20 69 73 69        if not isi
15e50 6e 73 74 61 6e 63 65 28 76 61 6c 75 65 2c 20 42  nstance(value, B
15e60 6f 74 74 6c 65 29 3a 0a 20 20 20 20 20 20 20 20  ottle):.        
15e70 20 20 20 20 76 61 6c 75 65 20 3d 20 42 6f 74 74      value = Bott
15e80 6c 65 28 29 0a 20 20 20 20 20 20 20 20 73 65 6c  le().        sel
15e90 66 2e 61 70 70 65 6e 64 28 76 61 6c 75 65 29 0a  f.append(value).
15ea0 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 76          return v
15eb0 61 6c 75 65 0a 0a 0a 63 6c 61 73 73 20 57 53 47  alue...class WSG
15ec0 49 46 69 6c 65 57 72 61 70 70 65 72 28 6f 62 6a  IFileWrapper(obj
15ed0 65 63 74 29 3a 0a 0a 20 20 20 20 64 65 66 20 5f  ect):..    def _
15ee0 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 66 70  _init__(self, fp
15ef0 2c 20 62 75 66 66 65 72 5f 73 69 7a 65 3d 31 30  , buffer_size=10
15f00 32 34 2a 36 34 29 3a 0a 20 20 20 20 20 20 20 20  24*64):.        
15f10 73 65 6c 66 2e 66 70 2c 20 73 65 6c 66 2e 62 75  self.fp, self.bu
15f20 66 66 65 72 5f 73 69 7a 65 20 3d 20 66 70 2c 20  ffer_size = fp, 
15f30 62 75 66 66 65 72 5f 73 69 7a 65 0a 20 20 20 20  buffer_size.    
15f40 20 20 20 20 66 6f 72 20 61 74 74 72 20 69 6e 20      for attr in 
15f50 28 27 66 69 6c 65 6e 6f 27 2c 20 27 63 6c 6f 73  ('fileno', 'clos
15f60 65 27 2c 20 27 72 65 61 64 27 2c 20 27 72 65 61  e', 'read', 'rea
15f70 64 6c 69 6e 65 73 27 2c 20 27 74 65 6c 6c 27 2c  dlines', 'tell',
15f80 20 27 73 65 65 6b 27 29 3a 0a 20 20 20 20 20 20   'seek'):.      
15f90 20 20 20 20 20 20 69 66 20 68 61 73 61 74 74 72        if hasattr
15fa0 28 66 70 2c 20 61 74 74 72 29 3a 20 73 65 74 61  (fp, attr): seta
15fb0 74 74 72 28 73 65 6c 66 2c 20 61 74 74 72 2c 20  ttr(self, attr, 
15fc0 67 65 74 61 74 74 72 28 66 70 2c 20 61 74 74 72  getattr(fp, attr
15fd0 29 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 74  ))..    def __it
15fe0 65 72 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20 20  er__(self):.    
15ff0 20 20 20 20 62 75 66 66 2c 20 72 65 61 64 20 3d      buff, read =
16000 20 73 65 6c 66 2e 62 75 66 66 65 72 5f 73 69 7a   self.buffer_siz
16010 65 2c 20 73 65 6c 66 2e 72 65 61 64 0a 20 20 20  e, self.read.   
16020 20 20 20 20 20 77 68 69 6c 65 20 54 72 75 65 3a       while True:
16030 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 61 72  .            par
16040 74 20 3d 20 72 65 61 64 28 62 75 66 66 29 0a 20  t = read(buff). 
16050 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f             if no
16060 74 20 70 61 72 74 3a 20 72 65 74 75 72 6e 0a 20  t part: return. 
16070 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64             yield
16080 20 70 61 72 74 0a 0a 0a 63 6c 61 73 73 20 5f 63   part...class _c
16090 6c 6f 73 65 69 74 65 72 28 6f 62 6a 65 63 74 29  loseiter(object)
160a0 3a 0a 20 20 20 20 27 27 27 20 54 68 69 73 20 6f  :.    ''' This o
160b0 6e 6c 79 20 65 78 69 73 74 73 20 74 6f 20 62 65  nly exists to be
160c0 20 61 62 6c 65 20 74 6f 20 61 74 74 61 63 68 20   able to attach 
160d0 61 20 2e 63 6c 6f 73 65 20 6d 65 74 68 6f 64 20  a .close method 
160e0 74 6f 20 69 74 65 72 61 74 6f 72 73 20 74 68 61  to iterators tha
160f0 74 0a 20 20 20 20 20 20 20 20 64 6f 20 6e 6f 74  t.        do not
16100 20 73 75 70 70 6f 72 74 20 61 74 74 72 69 62 75   support attribu
16110 74 65 20 61 73 73 69 67 6e 6d 65 6e 74 20 28 6d  te assignment (m
16120 6f 73 74 20 6f 66 20 69 74 65 72 74 6f 6f 6c 73  ost of itertools
16130 29 2e 20 27 27 27 0a 0a 20 20 20 20 64 65 66 20  ). '''..    def 
16140 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 69  __init__(self, i
16150 74 65 72 61 74 6f 72 2c 20 63 6c 6f 73 65 3d 4e  terator, close=N
16160 6f 6e 65 29 3a 0a 20 20 20 20 20 20 20 20 73 65  one):.        se
16170 6c 66 2e 69 74 65 72 61 74 6f 72 20 3d 20 69 74  lf.iterator = it
16180 65 72 61 74 6f 72 0a 20 20 20 20 20 20 20 20 73  erator.        s
16190 65 6c 66 2e 63 6c 6f 73 65 5f 63 61 6c 6c 62 61  elf.close_callba
161a0 63 6b 73 20 3d 20 6d 61 6b 65 6c 69 73 74 28 63  cks = makelist(c
161b0 6c 6f 73 65 29 0a 0a 20 20 20 20 64 65 66 20 5f  lose)..    def _
161c0 5f 69 74 65 72 5f 5f 28 73 65 6c 66 29 3a 0a 20  _iter__(self):. 
161d0 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 69 74         return it
161e0 65 72 28 73 65 6c 66 2e 69 74 65 72 61 74 6f 72  er(self.iterator
161f0 29 0a 0a 20 20 20 20 64 65 66 20 63 6c 6f 73 65  )..    def close
16200 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20  (self):.        
16210 66 6f 72 20 66 75 6e 63 20 69 6e 20 73 65 6c 66  for func in self
16220 2e 63 6c 6f 73 65 5f 63 61 6c 6c 62 61 63 6b 73  .close_callbacks
16230 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 75  :.            fu
16240 6e 63 28 29 0a 0a 0a 63 6c 61 73 73 20 52 65 73  nc()...class Res
16250 6f 75 72 63 65 4d 61 6e 61 67 65 72 28 6f 62 6a  ourceManager(obj
16260 65 63 74 29 3a 0a 20 20 20 20 27 27 27 20 54 68  ect):.    ''' Th
16270 69 73 20 63 6c 61 73 73 20 6d 61 6e 61 67 65 73  is class manages
16280 20 61 20 6c 69 73 74 20 6f 66 20 73 65 61 72 63   a list of searc
16290 68 20 70 61 74 68 73 20 61 6e 64 20 68 65 6c 70  h paths and help
162a0 73 20 74 6f 20 66 69 6e 64 20 61 6e 64 20 6f 70  s to find and op
162b0 65 6e 0a 20 20 20 20 20 20 20 20 61 70 70 6c 69  en.        appli
162c0 63 61 74 69 6f 6e 2d 62 6f 75 6e 64 20 72 65 73  cation-bound res
162d0 6f 75 72 63 65 73 20 28 66 69 6c 65 73 29 2e 0a  ources (files)..
162e0 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20  .        :param 
162f0 62 61 73 65 3a 20 64 65 66 61 75 6c 74 20 76 61  base: default va
16300 6c 75 65 20 66 6f 72 20 3a 6d 65 74 68 3a 60 61  lue for :meth:`a
16310 64 64 5f 70 61 74 68 60 20 63 61 6c 6c 73 2e 0a  dd_path` calls..
16320 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 6f          :param o
16330 70 65 6e 65 72 3a 20 63 61 6c 6c 61 62 6c 65 20  pener: callable 
16340 75 73 65 64 20 74 6f 20 6f 70 65 6e 20 72 65 73  used to open res
16350 6f 75 72 63 65 73 2e 0a 20 20 20 20 20 20 20 20  ources..        
16360 3a 70 61 72 61 6d 20 63 61 63 68 65 6d 6f 64 65  :param cachemode
16370 3a 20 63 6f 6e 74 72 6f 6c 73 20 77 68 69 63 68  : controls which
16380 20 6c 6f 6f 6b 75 70 73 20 61 72 65 20 63 61 63   lookups are cac
16390 68 65 64 2e 20 4f 6e 65 20 6f 66 20 27 61 6c 6c  hed. One of 'all
163a0 27 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ',.             
163b0 20 20 20 20 20 20 20 20 20 20 20 20 27 66 6f 75              'fou
163c0 6e 64 27 20 6f 72 20 27 6e 6f 6e 65 27 2e 0a 20  nd' or 'none'.. 
163d0 20 20 20 27 27 27 0a 0a 20 20 20 20 64 65 66 20     '''..    def 
163e0 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 62  __init__(self, b
163f0 61 73 65 3d 27 2e 2f 27 2c 20 6f 70 65 6e 65 72  ase='./', opener
16400 3d 6f 70 65 6e 2c 20 63 61 63 68 65 6d 6f 64 65  =open, cachemode
16410 3d 27 61 6c 6c 27 29 3a 0a 20 20 20 20 20 20 20  ='all'):.       
16420 20 73 65 6c 66 2e 6f 70 65 6e 65 72 20 3d 20 6f   self.opener = o
16430 70 65 6e 0a 20 20 20 20 20 20 20 20 73 65 6c 66  pen.        self
16440 2e 62 61 73 65 20 3d 20 62 61 73 65 0a 20 20 20  .base = base.   
16450 20 20 20 20 20 73 65 6c 66 2e 63 61 63 68 65 6d       self.cachem
16460 6f 64 65 20 3d 20 63 61 63 68 65 6d 6f 64 65 0a  ode = cachemode.
16470 0a 20 20 20 20 20 20 20 20 23 3a 20 41 20 6c 69  .        #: A li
16480 73 74 20 6f 66 20 73 65 61 72 63 68 20 70 61 74  st of search pat
16490 68 73 2e 20 53 65 65 20 3a 6d 65 74 68 3a 60 61  hs. See :meth:`a
164a0 64 64 5f 70 61 74 68 60 20 66 6f 72 20 64 65 74  dd_path` for det
164b0 61 69 6c 73 2e 0a 20 20 20 20 20 20 20 20 73 65  ails..        se
164c0 6c 66 2e 70 61 74 68 20 3d 20 5b 5d 0a 20 20 20  lf.path = [].   
164d0 20 20 20 20 20 23 3a 20 41 20 63 61 63 68 65 20       #: A cache 
164e0 66 6f 72 20 72 65 73 6f 6c 76 65 64 20 70 61 74  for resolved pat
164f0 68 73 2e 20 60 60 72 65 73 2e 63 61 63 68 65 2e  hs. ``res.cache.
16500 63 6c 65 61 72 28 29 60 60 20 63 6c 65 61 72 73  clear()`` clears
16510 20 74 68 65 20 63 61 63 68 65 2e 0a 20 20 20 20   the cache..    
16520 20 20 20 20 73 65 6c 66 2e 63 61 63 68 65 20 3d      self.cache =
16530 20 7b 7d 0a 0a 20 20 20 20 64 65 66 20 61 64 64   {}..    def add
16540 5f 70 61 74 68 28 73 65 6c 66 2c 20 70 61 74 68  _path(self, path
16550 2c 20 62 61 73 65 3d 4e 6f 6e 65 2c 20 69 6e 64  , base=None, ind
16560 65 78 3d 4e 6f 6e 65 2c 20 63 72 65 61 74 65 3d  ex=None, create=
16570 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20  False):.        
16580 27 27 27 20 41 64 64 20 61 20 6e 65 77 20 70 61  ''' Add a new pa
16590 74 68 20 74 6f 20 74 68 65 20 6c 69 73 74 20 6f  th to the list o
165a0 66 20 73 65 61 72 63 68 20 70 61 74 68 73 2e 20  f search paths. 
165b0 52 65 74 75 72 6e 20 46 61 6c 73 65 20 69 66 20  Return False if 
165c0 74 68 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  the.            
165d0 70 61 74 68 20 64 6f 65 73 20 6e 6f 74 20 65 78  path does not ex
165e0 69 73 74 2e 0a 0a 20 20 20 20 20 20 20 20 20 20  ist...          
165f0 20 20 3a 70 61 72 61 6d 20 70 61 74 68 3a 20 54    :param path: T
16600 68 65 20 6e 65 77 20 73 65 61 72 63 68 20 70 61  he new search pa
16610 74 68 2e 20 52 65 6c 61 74 69 76 65 20 70 61 74  th. Relative pat
16620 68 73 20 61 72 65 20 74 75 72 6e 65 64 20 69 6e  hs are turned in
16630 74 6f 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  to.             
16640 20 20 20 61 6e 20 61 62 73 6f 6c 75 74 65 20 61     an absolute a
16650 6e 64 20 6e 6f 72 6d 61 6c 69 7a 65 64 20 66 6f  nd normalized fo
16660 72 6d 2e 20 49 66 20 74 68 65 20 70 61 74 68 20  rm. If the path 
16670 6c 6f 6f 6b 73 20 6c 69 6b 65 20 61 20 66 69 6c  looks like a fil
16680 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
16690 20 20 28 6e 6f 74 20 65 6e 64 69 6e 67 20 69 6e    (not ending in
166a0 20 60 2f 60 29 2c 20 74 68 65 20 66 69 6c 65 6e   `/`), the filen
166b0 61 6d 65 20 69 73 20 73 74 72 69 70 70 65 64 20  ame is stripped 
166c0 6f 66 66 2e 0a 20 20 20 20 20 20 20 20 20 20 20  off..           
166d0 20 3a 70 61 72 61 6d 20 62 61 73 65 3a 20 50 61   :param base: Pa
166e0 74 68 20 75 73 65 64 20 74 6f 20 61 62 73 6f 6c  th used to absol
166f0 75 74 69 7a 65 20 72 65 6c 61 74 69 76 65 20 73  utize relative s
16700 65 61 72 63 68 20 70 61 74 68 73 2e 0a 20 20 20  earch paths..   
16710 20 20 20 20 20 20 20 20 20 20 20 20 20 44 65 66               Def
16720 61 75 6c 74 73 20 74 6f 20 3a 61 74 74 72 3a 60  aults to :attr:`
16730 62 61 73 65 60 20 77 68 69 63 68 20 64 65 66 61  base` which defa
16740 75 6c 74 73 20 74 6f 20 60 60 6f 73 2e 67 65 74  ults to ``os.get
16750 63 77 64 28 29 60 60 2e 0a 20 20 20 20 20 20 20  cwd()``..       
16760 20 20 20 20 20 3a 70 61 72 61 6d 20 69 6e 64 65       :param inde
16770 78 3a 20 50 6f 73 69 74 69 6f 6e 20 77 69 74 68  x: Position with
16780 69 6e 20 74 68 65 20 6c 69 73 74 20 6f 66 20 73  in the list of s
16790 65 61 72 63 68 20 70 61 74 68 73 2e 20 44 65 66  earch paths. Def
167a0 61 75 6c 74 73 0a 20 20 20 20 20 20 20 20 20 20  aults.          
167b0 20 20 20 20 20 20 74 6f 20 6c 61 73 74 20 69 6e        to last in
167c0 64 65 78 20 28 61 70 70 65 6e 64 73 20 74 6f 20  dex (appends to 
167d0 74 68 65 20 6c 69 73 74 29 2e 0a 0a 20 20 20 20  the list)...    
167e0 20 20 20 20 20 20 20 20 54 68 65 20 60 62 61 73          The `bas
167f0 65 60 20 70 61 72 61 6d 65 74 65 72 20 6d 61 6b  e` parameter mak
16800 65 73 20 69 74 20 65 61 73 79 20 74 6f 20 72 65  es it easy to re
16810 66 65 72 65 6e 63 65 20 66 69 6c 65 73 20 69 6e  ference files in
16820 73 74 61 6c 6c 65 64 0a 20 20 20 20 20 20 20 20  stalled.        
16830 20 20 20 20 61 6c 6f 6e 67 20 77 69 74 68 20 61      along with a
16840 20 70 79 74 68 6f 6e 20 6d 6f 64 75 6c 65 20 6f   python module o
16850 72 20 70 61 63 6b 61 67 65 3a 3a 0a 0a 20 20 20  r package::..   
16860 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 73               res
16870 2e 61 64 64 5f 70 61 74 68 28 27 2e 2f 72 65 73  .add_path('./res
16880 6f 75 72 63 65 73 2f 27 2c 20 5f 5f 66 69 6c 65  ources/', __file
16890 5f 5f 29 0a 20 20 20 20 20 20 20 20 27 27 27 0a  __).        '''.
168a0 20 20 20 20 20 20 20 20 62 61 73 65 20 3d 20 6f          base = o
168b0 73 2e 70 61 74 68 2e 61 62 73 70 61 74 68 28 6f  s.path.abspath(o
168c0 73 2e 70 61 74 68 2e 64 69 72 6e 61 6d 65 28 62  s.path.dirname(b
168d0 61 73 65 20 6f 72 20 73 65 6c 66 2e 62 61 73 65  ase or self.base
168e0 29 29 0a 20 20 20 20 20 20 20 20 70 61 74 68 20  )).        path 
168f0 3d 20 6f 73 2e 70 61 74 68 2e 61 62 73 70 61 74  = os.path.abspat
16900 68 28 6f 73 2e 70 61 74 68 2e 6a 6f 69 6e 28 62  h(os.path.join(b
16910 61 73 65 2c 20 6f 73 2e 70 61 74 68 2e 64 69 72  ase, os.path.dir
16920 6e 61 6d 65 28 70 61 74 68 29 29 29 0a 20 20 20  name(path))).   
16930 20 20 20 20 20 70 61 74 68 20 2b 3d 20 6f 73 2e       path += os.
16940 73 65 70 0a 20 20 20 20 20 20 20 20 69 66 20 70  sep.        if p
16950 61 74 68 20 69 6e 20 73 65 6c 66 2e 70 61 74 68  ath in self.path
16960 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65  :.            se
16970 6c 66 2e 70 61 74 68 2e 72 65 6d 6f 76 65 28 70  lf.path.remove(p
16980 61 74 68 29 0a 20 20 20 20 20 20 20 20 69 66 20  ath).        if 
16990 63 72 65 61 74 65 20 61 6e 64 20 6e 6f 74 20 6f  create and not o
169a0 73 2e 70 61 74 68 2e 69 73 64 69 72 28 70 61 74  s.path.isdir(pat
169b0 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  h):.            
169c0 6f 73 2e 6d 61 6b 65 64 69 72 73 28 70 61 74 68  os.makedirs(path
169d0 29 0a 20 20 20 20 20 20 20 20 69 66 20 69 6e 64  ).        if ind
169e0 65 78 20 69 73 20 4e 6f 6e 65 3a 0a 20 20 20 20  ex is None:.    
169f0 20 20 20 20 20 20 20 20 73 65 6c 66 2e 70 61 74          self.pat
16a00 68 2e 61 70 70 65 6e 64 28 70 61 74 68 29 0a 20  h.append(path). 
16a10 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
16a20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 70 61           self.pa
16a30 74 68 2e 69 6e 73 65 72 74 28 69 6e 64 65 78 2c  th.insert(index,
16a40 20 70 61 74 68 29 0a 20 20 20 20 20 20 20 20 73   path).        s
16a50 65 6c 66 2e 63 61 63 68 65 2e 63 6c 65 61 72 28  elf.cache.clear(
16a60 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
16a70 20 6f 73 2e 70 61 74 68 2e 65 78 69 73 74 73 28   os.path.exists(
16a80 70 61 74 68 29 0a 0a 20 20 20 20 64 65 66 20 5f  path)..    def _
16a90 5f 69 74 65 72 5f 5f 28 73 65 6c 66 29 3a 0a 20  _iter__(self):. 
16aa0 20 20 20 20 20 20 20 27 27 27 20 49 74 65 72 61         ''' Itera
16ab0 74 65 20 6f 76 65 72 20 61 6c 6c 20 65 78 69 73  te over all exis
16ac0 74 69 6e 67 20 66 69 6c 65 73 20 69 6e 20 61 6c  ting files in al
16ad0 6c 20 72 65 67 69 73 74 65 72 65 64 20 70 61 74  l registered pat
16ae0 68 73 2e 20 27 27 27 0a 20 20 20 20 20 20 20 20  hs. '''.        
16af0 73 65 61 72 63 68 20 3d 20 73 65 6c 66 2e 70 61  search = self.pa
16b00 74 68 5b 3a 5d 0a 20 20 20 20 20 20 20 20 77 68  th[:].        wh
16b10 69 6c 65 20 73 65 61 72 63 68 3a 0a 20 20 20 20  ile search:.    
16b20 20 20 20 20 20 20 20 20 70 61 74 68 20 3d 20 73          path = s
16b30 65 61 72 63 68 2e 70 6f 70 28 29 0a 20 20 20 20  earch.pop().    
16b40 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 6f          if not o
16b50 73 2e 70 61 74 68 2e 69 73 64 69 72 28 70 61 74  s.path.isdir(pat
16b60 68 29 3a 20 63 6f 6e 74 69 6e 75 65 0a 20 20 20  h): continue.   
16b70 20 20 20 20 20 20 20 20 20 66 6f 72 20 6e 61 6d           for nam
16b80 65 20 69 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28  e in os.listdir(
16b90 70 61 74 68 29 3a 0a 20 20 20 20 20 20 20 20 20  path):.         
16ba0 20 20 20 20 20 20 20 66 75 6c 6c 20 3d 20 6f 73         full = os
16bb0 2e 70 61 74 68 2e 6a 6f 69 6e 28 70 61 74 68 2c  .path.join(path,
16bc0 20 6e 61 6d 65 29 0a 20 20 20 20 20 20 20 20 20   name).         
16bd0 20 20 20 20 20 20 20 69 66 20 6f 73 2e 70 61 74         if os.pat
16be0 68 2e 69 73 64 69 72 28 66 75 6c 6c 29 3a 20 73  h.isdir(full): s
16bf0 65 61 72 63 68 2e 61 70 70 65 6e 64 28 66 75 6c  earch.append(ful
16c00 6c 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  l).             
16c10 20 20 20 65 6c 73 65 3a 20 79 69 65 6c 64 20 66     else: yield f
16c20 75 6c 6c 0a 0a 20 20 20 20 64 65 66 20 6c 6f 6f  ull..    def loo
16c30 6b 75 70 28 73 65 6c 66 2c 20 6e 61 6d 65 29 3a  kup(self, name):
16c40 0a 20 20 20 20 20 20 20 20 27 27 27 20 53 65 61  .        ''' Sea
16c50 72 63 68 20 66 6f 72 20 61 20 72 65 73 6f 75 72  rch for a resour
16c60 63 65 20 61 6e 64 20 72 65 74 75 72 6e 20 61 6e  ce and return an
16c70 20 61 62 73 6f 6c 75 74 65 20 66 69 6c 65 20 70   absolute file p
16c80 61 74 68 2c 20 6f 72 20 60 4e 6f 6e 65 60 2e 0a  ath, or `None`..
16c90 0a 20 20 20 20 20 20 20 20 20 20 20 20 54 68 65  .            The
16ca0 20 3a 61 74 74 72 3a 60 70 61 74 68 60 20 6c 69   :attr:`path` li
16cb0 73 74 20 69 73 20 73 65 61 72 63 68 65 64 20 69  st is searched i
16cc0 6e 20 6f 72 64 65 72 2e 20 54 68 65 20 66 69 72  n order. The fir
16cd0 73 74 20 6d 61 74 63 68 20 69 73 0a 20 20 20 20  st match is.    
16ce0 20 20 20 20 20 20 20 20 72 65 74 75 72 65 6e 64          returend
16cf0 2e 20 53 79 6d 6c 69 6e 6b 73 20 61 72 65 20 66  . Symlinks are f
16d00 6f 6c 6c 6f 77 65 64 2e 20 54 68 65 20 72 65 73  ollowed. The res
16d10 75 6c 74 20 69 73 20 63 61 63 68 65 64 20 74 6f  ult is cached to
16d20 20 73 70 65 65 64 20 75 70 0a 20 20 20 20 20 20   speed up.      
16d30 20 20 20 20 20 20 66 75 74 75 72 65 20 6c 6f 6f        future loo
16d40 6b 75 70 73 2e 20 27 27 27 0a 20 20 20 20 20 20  kups. '''.      
16d50 20 20 69 66 20 6e 61 6d 65 20 6e 6f 74 20 69 6e    if name not in
16d60 20 73 65 6c 66 2e 63 61 63 68 65 20 6f 72 20 44   self.cache or D
16d70 45 42 55 47 3a 0a 20 20 20 20 20 20 20 20 20 20  EBUG:.          
16d80 20 20 66 6f 72 20 70 61 74 68 20 69 6e 20 73 65    for path in se
16d90 6c 66 2e 70 61 74 68 3a 0a 20 20 20 20 20 20 20  lf.path:.       
16da0 20 20 20 20 20 20 20 20 20 66 70 61 74 68 20 3d           fpath =
16db0 20 6f 73 2e 70 61 74 68 2e 6a 6f 69 6e 28 70 61   os.path.join(pa
16dc0 74 68 2c 20 6e 61 6d 65 29 0a 20 20 20 20 20 20  th, name).      
16dd0 20 20 20 20 20 20 20 20 20 20 69 66 20 6f 73 2e            if os.
16de0 70 61 74 68 2e 69 73 66 69 6c 65 28 66 70 61 74  path.isfile(fpat
16df0 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  h):.            
16e00 20 20 20 20 20 20 20 20 69 66 20 73 65 6c 66 2e          if self.
16e10 63 61 63 68 65 6d 6f 64 65 20 69 6e 20 28 27 61  cachemode in ('a
16e20 6c 6c 27 2c 20 27 66 6f 75 6e 64 27 29 3a 0a 20  ll', 'found'):. 
16e30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16e40 20 20 20 20 20 20 20 73 65 6c 66 2e 63 61 63 68         self.cach
16e50 65 5b 6e 61 6d 65 5d 20 3d 20 66 70 61 74 68 0a  e[name] = fpath.
16e60 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16e70 20 20 20 20 72 65 74 75 72 6e 20 66 70 61 74 68      return fpath
16e80 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
16e90 73 65 6c 66 2e 63 61 63 68 65 6d 6f 64 65 20 3d  self.cachemode =
16ea0 3d 20 27 61 6c 6c 27 3a 0a 20 20 20 20 20 20 20  = 'all':.       
16eb0 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 63 61           self.ca
16ec0 63 68 65 5b 6e 61 6d 65 5d 20 3d 20 4e 6f 6e 65  che[name] = None
16ed0 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
16ee0 73 65 6c 66 2e 63 61 63 68 65 5b 6e 61 6d 65 5d  self.cache[name]
16ef0 0a 0a 20 20 20 20 64 65 66 20 6f 70 65 6e 28 73  ..    def open(s
16f00 65 6c 66 2c 20 6e 61 6d 65 2c 20 6d 6f 64 65 3d  elf, name, mode=
16f10 27 72 27 2c 20 2a 61 72 67 73 2c 20 2a 2a 6b 77  'r', *args, **kw
16f20 61 72 67 73 29 3a 0a 20 20 20 20 20 20 20 20 27  args):.        '
16f30 27 27 20 46 69 6e 64 20 61 20 72 65 73 6f 75 72  '' Find a resour
16f40 63 65 20 61 6e 64 20 72 65 74 75 72 6e 20 61 20  ce and return a 
16f50 66 69 6c 65 20 6f 62 6a 65 63 74 2c 20 6f 72 20  file object, or 
16f60 72 61 69 73 65 20 49 4f 45 72 72 6f 72 2e 20 27  raise IOError. '
16f70 27 27 0a 20 20 20 20 20 20 20 20 66 6e 61 6d 65  ''.        fname
16f80 20 3d 20 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 6e   = self.lookup(n
16f90 61 6d 65 29 0a 20 20 20 20 20 20 20 20 69 66 20  ame).        if 
16fa0 6e 6f 74 20 66 6e 61 6d 65 3a 20 72 61 69 73 65  not fname: raise
16fb0 20 49 4f 45 72 72 6f 72 28 22 52 65 73 6f 75 72   IOError("Resour
16fc0 63 65 20 25 72 20 6e 6f 74 20 66 6f 75 6e 64 2e  ce %r not found.
16fd0 22 20 25 20 6e 61 6d 65 29 0a 20 20 20 20 20 20  " % name).      
16fe0 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 6f 70    return self.op
16ff0 65 6e 65 72 28 66 6e 61 6d 65 2c 20 6d 6f 64 65  ener(fname, mode
17000 3d 6d 6f 64 65 2c 20 2a 61 72 67 73 2c 20 2a 2a  =mode, *args, **
17010 6b 77 61 72 67 73 29 0a 0a 0a 63 6c 61 73 73 20  kwargs)...class 
17020 46 69 6c 65 55 70 6c 6f 61 64 28 6f 62 6a 65 63  FileUpload(objec
17030 74 29 3a 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69  t):..    def __i
17040 6e 69 74 5f 5f 28 73 65 6c 66 2c 20 66 69 6c 65  nit__(self, file
17050 6f 62 6a 2c 20 6e 61 6d 65 2c 20 66 69 6c 65 6e  obj, name, filen
17060 61 6d 65 2c 20 68 65 61 64 65 72 73 3d 4e 6f 6e  ame, headers=Non
17070 65 29 3a 0a 20 20 20 20 20 20 20 20 27 27 27 20  e):.        ''' 
17080 57 72 61 70 70 65 72 20 66 6f 72 20 66 69 6c 65  Wrapper for file
17090 20 75 70 6c 6f 61 64 73 2e 20 27 27 27 0a 20 20   uploads. '''.  
170a0 20 20 20 20 20 20 23 3a 20 4f 70 65 6e 20 66 69        #: Open fi
170b0 6c 65 28 2d 6c 69 6b 65 29 20 6f 62 6a 65 63 74  le(-like) object
170c0 20 28 42 79 74 65 73 49 4f 20 62 75 66 66 65 72   (BytesIO buffer
170d0 20 6f 72 20 74 65 6d 70 6f 72 61 72 79 20 66 69   or temporary fi
170e0 6c 65 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  le).        self
170f0 2e 66 69 6c 65 20 3d 20 66 69 6c 65 6f 62 6a 0a  .file = fileobj.
17100 20 20 20 20 20 20 20 20 23 3a 20 4e 61 6d 65 20          #: Name 
17110 6f 66 20 74 68 65 20 75 70 6c 6f 61 64 20 66 6f  of the upload fo
17120 72 6d 20 66 69 65 6c 64 0a 20 20 20 20 20 20 20  rm field.       
17130 20 73 65 6c 66 2e 6e 61 6d 65 20 3d 20 6e 61 6d   self.name = nam
17140 65 0a 20 20 20 20 20 20 20 20 23 3a 20 52 61 77  e.        #: Raw
17150 20 66 69 6c 65 6e 61 6d 65 20 61 73 20 73 65 6e   filename as sen
17160 74 20 62 79 20 74 68 65 20 63 6c 69 65 6e 74 20  t by the client 
17170 28 6d 61 79 20 63 6f 6e 74 61 69 6e 20 75 6e 73  (may contain uns
17180 61 66 65 20 63 68 61 72 61 63 74 65 72 73 29 0a  afe characters).
17190 20 20 20 20 20 20 20 20 73 65 6c 66 2e 72 61 77          self.raw
171a0 5f 66 69 6c 65 6e 61 6d 65 20 3d 20 66 69 6c 65  _filename = file
171b0 6e 61 6d 65 0a 20 20 20 20 20 20 20 20 23 3a 20  name.        #: 
171c0 41 20 3a 63 6c 61 73 73 3a 60 48 65 61 64 65 72  A :class:`Header
171d0 44 69 63 74 60 20 77 69 74 68 20 61 64 64 69 74  Dict` with addit
171e0 69 6f 6e 61 6c 20 68 65 61 64 65 72 73 20 28 65  ional headers (e
171f0 2e 67 2e 20 63 6f 6e 74 65 6e 74 2d 74 79 70 65  .g. content-type
17200 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 68  ).        self.h
17210 65 61 64 65 72 73 20 3d 20 48 65 61 64 65 72 44  eaders = HeaderD
17220 69 63 74 28 68 65 61 64 65 72 73 29 20 69 66 20  ict(headers) if 
17230 68 65 61 64 65 72 73 20 65 6c 73 65 20 48 65 61  headers else Hea
17240 64 65 72 44 69 63 74 28 29 0a 0a 20 20 20 20 63  derDict()..    c
17250 6f 6e 74 65 6e 74 5f 74 79 70 65 20 3d 20 48 65  ontent_type = He
17260 61 64 65 72 50 72 6f 70 65 72 74 79 28 27 43 6f  aderProperty('Co
17270 6e 74 65 6e 74 2d 54 79 70 65 27 29 0a 20 20 20  ntent-Type').   
17280 20 63 6f 6e 74 65 6e 74 5f 6c 65 6e 67 74 68 20   content_length 
17290 3d 20 48 65 61 64 65 72 50 72 6f 70 65 72 74 79  = HeaderProperty
172a0 28 27 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68  ('Content-Length
172b0 27 2c 20 72 65 61 64 65 72 3d 69 6e 74 2c 20 64  ', reader=int, d
172c0 65 66 61 75 6c 74 3d 2d 31 29 0a 0a 20 20 20 20  efault=-1)..    
172d0 64 65 66 20 67 65 74 5f 68 65 61 64 65 72 28 73  def get_header(s
172e0 65 6c 66 2c 20 6e 61 6d 65 2c 20 64 65 66 61 75  elf, name, defau
172f0 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 20 20  lt=None):.      
17300 20 20 22 22 22 20 52 65 74 75 72 6e 20 74 68 65    """ Return the
17310 20 76 61 6c 75 65 20 6f 66 20 61 20 68 65 61 64   value of a head
17320 65 72 20 77 69 74 68 69 6e 20 74 68 65 20 6d 75  er within the mu
17330 6c 72 69 70 61 72 74 20 70 61 72 74 2e 20 22 22  lripart part. ""
17340 22 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ".        return
17350 20 73 65 6c 66 2e 68 65 61 64 65 72 73 2e 67 65   self.headers.ge
17360 74 28 6e 61 6d 65 2c 20 64 65 66 61 75 6c 74 29  t(name, default)
17370 0a 0a 20 20 20 20 40 63 61 63 68 65 64 5f 70 72  ..    @cached_pr
17380 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20 66  operty.    def f
17390 69 6c 65 6e 61 6d 65 28 73 65 6c 66 29 3a 0a 20  ilename(self):. 
173a0 20 20 20 20 20 20 20 27 27 27 20 4e 61 6d 65 20         ''' Name 
173b0 6f 66 20 74 68 65 20 66 69 6c 65 20 6f 6e 20 74  of the file on t
173c0 68 65 20 63 6c 69 65 6e 74 20 66 69 6c 65 20 73  he client file s
173d0 79 73 74 65 6d 2c 20 62 75 74 20 6e 6f 72 6d 61  ystem, but norma
173e0 6c 69 7a 65 64 20 74 6f 20 65 6e 73 75 72 65 0a  lized to ensure.
173f0 20 20 20 20 20 20 20 20 20 20 20 20 66 69 6c 65              file
17400 20 73 79 73 74 65 6d 20 63 6f 6d 70 61 74 69 62   system compatib
17410 69 6c 69 74 79 2e 20 41 6e 20 65 6d 70 74 79 20  ility. An empty 
17420 66 69 6c 65 6e 61 6d 65 20 69 73 20 72 65 74 75  filename is retu
17430 72 6e 65 64 20 61 73 20 27 65 6d 70 74 79 27 2e  rned as 'empty'.
17440 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 4f 6e  ..            On
17450 6c 79 20 41 53 43 49 49 20 6c 65 74 74 65 72 73  ly ASCII letters
17460 2c 20 64 69 67 69 74 73 2c 20 64 61 73 68 65 73  , digits, dashes
17470 2c 20 75 6e 64 65 72 73 63 6f 72 65 73 20 61 6e  , underscores an
17480 64 20 64 6f 74 73 20 61 72 65 0a 20 20 20 20 20  d dots are.     
17490 20 20 20 20 20 20 20 61 6c 6c 6f 77 65 64 20 69         allowed i
174a0 6e 20 74 68 65 20 66 69 6e 61 6c 20 66 69 6c 65  n the final file
174b0 6e 61 6d 65 2e 20 41 63 63 65 6e 74 73 20 61 72  name. Accents ar
174c0 65 20 72 65 6d 6f 76 65 64 2c 20 69 66 20 70 6f  e removed, if po
174d0 73 73 69 62 6c 65 2e 0a 20 20 20 20 20 20 20 20  ssible..        
174e0 20 20 20 20 57 68 69 74 65 73 70 61 63 65 20 69      Whitespace i
174f0 73 20 72 65 70 6c 61 63 65 64 20 62 79 20 61 20  s replaced by a 
17500 73 69 6e 67 6c 65 20 64 61 73 68 2e 20 4c 65 61  single dash. Lea
17510 64 69 6e 67 20 6f 72 20 74 61 69 6c 69 6e 67 20  ding or tailing 
17520 64 6f 74 73 0a 20 20 20 20 20 20 20 20 20 20 20  dots.           
17530 20 6f 72 20 64 61 73 68 65 73 20 61 72 65 20 72   or dashes are r
17540 65 6d 6f 76 65 64 2e 20 54 68 65 20 66 69 6c 65  emoved. The file
17550 6e 61 6d 65 20 69 73 20 6c 69 6d 69 74 65 64 20  name is limited 
17560 74 6f 20 32 35 35 20 63 68 61 72 61 63 74 65 72  to 255 character
17570 73 2e 0a 20 20 20 20 20 20 20 20 27 27 27 0a 20  s..        '''. 
17580 20 20 20 20 20 20 20 66 6e 61 6d 65 20 3d 20 73         fname = s
17590 65 6c 66 2e 72 61 77 5f 66 69 6c 65 6e 61 6d 65  elf.raw_filename
175a0 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
175b0 69 73 69 6e 73 74 61 6e 63 65 28 66 6e 61 6d 65  isinstance(fname
175c0 2c 20 75 6e 69 63 6f 64 65 29 3a 0a 20 20 20 20  , unicode):.    
175d0 20 20 20 20 20 20 20 20 66 6e 61 6d 65 20 3d 20          fname = 
175e0 66 6e 61 6d 65 2e 64 65 63 6f 64 65 28 27 75 74  fname.decode('ut
175f0 66 38 27 2c 20 27 69 67 6e 6f 72 65 27 29 0a 20  f8', 'ignore'). 
17600 20 20 20 20 20 20 20 66 6e 61 6d 65 20 3d 20 6e         fname = n
17610 6f 72 6d 61 6c 69 7a 65 28 27 4e 46 4b 44 27 2c  ormalize('NFKD',
17620 20 66 6e 61 6d 65 29 2e 65 6e 63 6f 64 65 28 27   fname).encode('
17630 41 53 43 49 49 27 2c 20 27 69 67 6e 6f 72 65 27  ASCII', 'ignore'
17640 29 2e 64 65 63 6f 64 65 28 27 41 53 43 49 49 27  ).decode('ASCII'
17650 29 0a 20 20 20 20 20 20 20 20 66 6e 61 6d 65 20  ).        fname 
17660 3d 20 6f 73 2e 70 61 74 68 2e 62 61 73 65 6e 61  = os.path.basena
17670 6d 65 28 66 6e 61 6d 65 2e 72 65 70 6c 61 63 65  me(fname.replace
17680 28 27 5c 5c 27 2c 20 6f 73 2e 70 61 74 68 2e 73  ('\\', os.path.s
17690 65 70 29 29 0a 20 20 20 20 20 20 20 20 66 6e 61  ep)).        fna
176a0 6d 65 20 3d 20 72 65 2e 73 75 62 28 72 27 5b 5e  me = re.sub(r'[^
176b0 61 2d 7a 41 2d 5a 30 2d 39 2d 5f 2e 5c 73 5d 27  a-zA-Z0-9-_.\s]'
176c0 2c 20 27 27 2c 20 66 6e 61 6d 65 29 2e 73 74 72  , '', fname).str
176d0 69 70 28 29 0a 20 20 20 20 20 20 20 20 66 6e 61  ip().        fna
176e0 6d 65 20 3d 20 72 65 2e 73 75 62 28 72 27 5b 2d  me = re.sub(r'[-
176f0 5c 73 5d 2b 27 2c 20 27 2d 27 2c 20 66 6e 61 6d  \s]+', '-', fnam
17700 65 29 2e 73 74 72 69 70 28 27 2e 2d 27 29 0a 20  e).strip('.-'). 
17710 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 66 6e         return fn
17720 61 6d 65 5b 3a 32 35 35 5d 20 6f 72 20 27 65 6d  ame[:255] or 'em
17730 70 74 79 27 0a 0a 20 20 20 20 64 65 66 20 5f 63  pty'..    def _c
17740 6f 70 79 5f 66 69 6c 65 28 73 65 6c 66 2c 20 66  opy_file(self, f
17750 70 2c 20 63 68 75 6e 6b 5f 73 69 7a 65 3d 32 2a  p, chunk_size=2*
17760 2a 31 36 29 3a 0a 20 20 20 20 20 20 20 20 72 65  *16):.        re
17770 61 64 2c 20 77 72 69 74 65 2c 20 6f 66 66 73 65  ad, write, offse
17780 74 20 3d 20 73 65 6c 66 2e 66 69 6c 65 2e 72 65  t = self.file.re
17790 61 64 2c 20 66 70 2e 77 72 69 74 65 2c 20 73 65  ad, fp.write, se
177a0 6c 66 2e 66 69 6c 65 2e 74 65 6c 6c 28 29 0a 20  lf.file.tell(). 
177b0 20 20 20 20 20 20 20 77 68 69 6c 65 20 31 3a 0a         while 1:.
177c0 20 20 20 20 20 20 20 20 20 20 20 20 62 75 66 20              buf 
177d0 3d 20 72 65 61 64 28 63 68 75 6e 6b 5f 73 69 7a  = read(chunk_siz
177e0 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  e).            i
177f0 66 20 6e 6f 74 20 62 75 66 3a 20 62 72 65 61 6b  f not buf: break
17800 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 72 69  .            wri
17810 74 65 28 62 75 66 29 0a 20 20 20 20 20 20 20 20  te(buf).        
17820 73 65 6c 66 2e 66 69 6c 65 2e 73 65 65 6b 28 6f  self.file.seek(o
17830 66 66 73 65 74 29 0a 0a 20 20 20 20 64 65 66 20  ffset)..    def 
17840 73 61 76 65 28 73 65 6c 66 2c 20 64 65 73 74 69  save(self, desti
17850 6e 61 74 69 6f 6e 2c 20 6f 76 65 72 77 72 69 74  nation, overwrit
17860 65 3d 46 61 6c 73 65 2c 20 63 68 75 6e 6b 5f 73  e=False, chunk_s
17870 69 7a 65 3d 32 2a 2a 31 36 29 3a 0a 20 20 20 20  ize=2**16):.    
17880 20 20 20 20 27 27 27 20 53 61 76 65 20 66 69 6c      ''' Save fil
17890 65 20 74 6f 20 64 69 73 6b 20 6f 72 20 63 6f 70  e to disk or cop
178a0 79 20 69 74 73 20 63 6f 6e 74 65 6e 74 20 74 6f  y its content to
178b0 20 61 6e 20 6f 70 65 6e 20 66 69 6c 65 28 2d 6c   an open file(-l
178c0 69 6b 65 29 20 6f 62 6a 65 63 74 2e 0a 20 20 20  ike) object..   
178d0 20 20 20 20 20 20 20 20 20 49 66 20 2a 64 65 73           If *des
178e0 74 69 6e 61 74 69 6f 6e 2a 20 69 73 20 61 20 64  tination* is a d
178f0 69 72 65 63 74 6f 72 79 2c 20 3a 61 74 74 72 3a  irectory, :attr:
17900 60 66 69 6c 65 6e 61 6d 65 60 20 69 73 20 61 64  `filename` is ad
17910 64 65 64 20 74 6f 20 74 68 65 0a 20 20 20 20 20  ded to the.     
17920 20 20 20 20 20 20 20 70 61 74 68 2e 20 45 78 69         path. Exi
17930 73 74 69 6e 67 20 66 69 6c 65 73 20 61 72 65 20  sting files are 
17940 6e 6f 74 20 6f 76 65 72 77 72 69 74 74 65 6e 20  not overwritten 
17950 62 79 20 64 65 66 61 75 6c 74 20 28 49 4f 45 72  by default (IOEr
17960 72 6f 72 29 2e 0a 0a 20 20 20 20 20 20 20 20 20  ror)...         
17970 20 20 20 3a 70 61 72 61 6d 20 64 65 73 74 69 6e     :param destin
17980 61 74 69 6f 6e 3a 20 46 69 6c 65 20 70 61 74 68  ation: File path
17990 2c 20 64 69 72 65 63 74 6f 72 79 20 6f 72 20 66  , directory or f
179a0 69 6c 65 28 2d 6c 69 6b 65 29 20 6f 62 6a 65 63  ile(-like) objec
179b0 74 2e 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a  t..            :
179c0 70 61 72 61 6d 20 6f 76 65 72 77 72 69 74 65 3a  param overwrite:
179d0 20 49 66 20 54 72 75 65 2c 20 72 65 70 6c 61 63   If True, replac
179e0 65 20 65 78 69 73 74 69 6e 67 20 66 69 6c 65 73  e existing files
179f0 2e 20 28 64 65 66 61 75 6c 74 3a 20 46 61 6c 73  . (default: Fals
17a00 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 3a  e).            :
17a10 70 61 72 61 6d 20 63 68 75 6e 6b 5f 73 69 7a 65  param chunk_size
17a20 3a 20 42 79 74 65 73 20 74 6f 20 72 65 61 64 20  : Bytes to read 
17a30 61 74 20 61 20 74 69 6d 65 2e 20 28 64 65 66 61  at a time. (defa
17a40 75 6c 74 3a 20 36 34 6b 62 29 0a 20 20 20 20 20  ult: 64kb).     
17a50 20 20 20 27 27 27 0a 20 20 20 20 20 20 20 20 69     '''.        i
17a60 66 20 69 73 69 6e 73 74 61 6e 63 65 28 64 65 73  f isinstance(des
17a70 74 69 6e 61 74 69 6f 6e 2c 20 62 61 73 65 73 74  tination, basest
17a80 72 69 6e 67 29 3a 20 23 20 45 78 63 65 70 74 20  ring): # Except 
17a90 66 69 6c 65 2d 6c 69 6b 65 73 20 68 65 72 65 0a  file-likes here.
17aa0 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6f              if o
17ab0 73 2e 70 61 74 68 2e 69 73 64 69 72 28 64 65 73  s.path.isdir(des
17ac0 74 69 6e 61 74 69 6f 6e 29 3a 0a 20 20 20 20 20  tination):.     
17ad0 20 20 20 20 20 20 20 20 20 20 20 64 65 73 74 69             desti
17ae0 6e 61 74 69 6f 6e 20 3d 20 6f 73 2e 70 61 74 68  nation = os.path
17af0 2e 6a 6f 69 6e 28 64 65 73 74 69 6e 61 74 69 6f  .join(destinatio
17b00 6e 2c 20 73 65 6c 66 2e 66 69 6c 65 6e 61 6d 65  n, self.filename
17b10 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
17b20 20 6e 6f 74 20 6f 76 65 72 77 72 69 74 65 20 61   not overwrite a
17b30 6e 64 20 6f 73 2e 70 61 74 68 2e 65 78 69 73 74  nd os.path.exist
17b40 73 28 64 65 73 74 69 6e 61 74 69 6f 6e 29 3a 0a  s(destination):.
17b50 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
17b60 72 61 69 73 65 20 49 4f 45 72 72 6f 72 28 27 46  raise IOError('F
17b70 69 6c 65 20 65 78 69 73 74 73 2e 27 29 0a 20 20  ile exists.').  
17b80 20 20 20 20 20 20 20 20 20 20 77 69 74 68 20 6f            with o
17b90 70 65 6e 28 64 65 73 74 69 6e 61 74 69 6f 6e 2c  pen(destination,
17ba0 20 27 77 62 27 29 20 61 73 20 66 70 3a 0a 20 20   'wb') as fp:.  
17bb0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
17bc0 6c 66 2e 5f 63 6f 70 79 5f 66 69 6c 65 28 66 70  lf._copy_file(fp
17bd0 2c 20 63 68 75 6e 6b 5f 73 69 7a 65 29 0a 20 20  , chunk_size).  
17be0 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
17bf0 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 63 6f          self._co
17c00 70 79 5f 66 69 6c 65 28 64 65 73 74 69 6e 61 74  py_file(destinat
17c10 69 6f 6e 2c 20 63 68 75 6e 6b 5f 73 69 7a 65 29  ion, chunk_size)
17c20 0a 0a 0a 0a 0a 0a 0a 23 23 23 23 23 23 23 23 23  .......#########
17c30 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17c40 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17c50 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17c60 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17c70 23 23 23 23 23 23 0a 23 20 41 70 70 6c 69 63 61  ######.# Applica
17c80 74 69 6f 6e 20 48 65 6c 70 65 72 20 23 23 23 23  tion Helper ####
17c90 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17ca0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17cb0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17cc0 23 23 23 23 23 23 23 0a 23 23 23 23 23 23 23 23  #######.########
17cd0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17ce0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17cf0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17d00 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
17d10 23 23 23 23 23 23 23 0a 0a 0a 64 65 66 20 61 62  #######...def ab
17d20 6f 72 74 28 63 6f 64 65 3d 35 30 30 2c 20 74 65  ort(code=500, te
17d30 78 74 3d 27 55 6e 6b 6e 6f 77 6e 20 45 72 72 6f  xt='Unknown Erro
17d40 72 2e 27 29 3a 0a 20 20 20 20 22 22 22 20 41 62  r.'):.    """ Ab
17d50 6f 72 74 73 20 65 78 65 63 75 74 69 6f 6e 20 61  orts execution a
17d60 6e 64 20 63 61 75 73 65 73 20 61 20 48 54 54 50  nd causes a HTTP
17d70 20 65 72 72 6f 72 2e 20 22 22 22 0a 20 20 20 20   error. """.    
17d80 72 61 69 73 65 20 48 54 54 50 45 72 72 6f 72 28  raise HTTPError(
17d90 63 6f 64 65 2c 20 74 65 78 74 29 0a 0a 0a 64 65  code, text)...de
17da0 66 20 72 65 64 69 72 65 63 74 28 75 72 6c 2c 20  f redirect(url, 
17db0 63 6f 64 65 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20  code=None):.    
17dc0 22 22 22 20 41 62 6f 72 74 73 20 65 78 65 63 75  """ Aborts execu
17dd0 74 69 6f 6e 20 61 6e 64 20 63 61 75 73 65 73 20  tion and causes 
17de0 61 20 33 30 33 20 6f 72 20 33 30 32 20 72 65 64  a 303 or 302 red
17df0 69 72 65 63 74 2c 20 64 65 70 65 6e 64 69 6e 67  irect, depending
17e00 20 6f 6e 0a 20 20 20 20 20 20 20 20 74 68 65 20   on.        the 
17e10 48 54 54 50 20 70 72 6f 74 6f 63 6f 6c 20 76 65  HTTP protocol ve
17e20 72 73 69 6f 6e 2e 20 22 22 22 0a 20 20 20 20 69  rsion. """.    i
17e30 66 20 6e 6f 74 20 63 6f 64 65 3a 0a 20 20 20 20  f not code:.    
17e40 20 20 20 20 63 6f 64 65 20 3d 20 33 30 33 20 69      code = 303 i
17e50 66 20 72 65 71 75 65 73 74 2e 67 65 74 28 27 53  f request.get('S
17e60 45 52 56 45 52 5f 50 52 4f 54 4f 43 4f 4c 27 29  ERVER_PROTOCOL')
17e70 20 3d 3d 20 22 48 54 54 50 2f 31 2e 31 22 20 65   == "HTTP/1.1" e
17e80 6c 73 65 20 33 30 32 0a 20 20 20 20 72 65 73 20  lse 302.    res 
17e90 3d 20 72 65 73 70 6f 6e 73 65 2e 63 6f 70 79 28  = response.copy(
17ea0 63 6c 73 3d 48 54 54 50 52 65 73 70 6f 6e 73 65  cls=HTTPResponse
17eb0 29 0a 20 20 20 20 72 65 73 2e 73 74 61 74 75 73  ).    res.status
17ec0 20 3d 20 63 6f 64 65 0a 20 20 20 20 72 65 73 2e   = code.    res.
17ed0 62 6f 64 79 20 3d 20 22 22 0a 20 20 20 20 72 65  body = "".    re
17ee0 73 2e 73 65 74 5f 68 65 61 64 65 72 28 27 4c 6f  s.set_header('Lo
17ef0 63 61 74 69 6f 6e 27 2c 20 75 72 6c 6a 6f 69 6e  cation', urljoin
17f00 28 72 65 71 75 65 73 74 2e 75 72 6c 2c 20 75 72  (request.url, ur
17f10 6c 29 29 0a 20 20 20 20 72 61 69 73 65 20 72 65  l)).    raise re
17f20 73 0a 0a 0a 64 65 66 20 5f 66 69 6c 65 5f 69 74  s...def _file_it
17f30 65 72 5f 72 61 6e 67 65 28 66 70 2c 20 6f 66 66  er_range(fp, off
17f40 73 65 74 2c 20 62 79 74 65 73 2c 20 6d 61 78 72  set, bytes, maxr
17f50 65 61 64 3d 31 30 32 34 2a 31 30 32 34 29 3a 0a  ead=1024*1024):.
17f60 20 20 20 20 27 27 27 20 59 69 65 6c 64 20 63 68      ''' Yield ch
17f70 75 6e 6b 73 20 66 72 6f 6d 20 61 20 72 61 6e 67  unks from a rang
17f80 65 20 69 6e 20 61 20 66 69 6c 65 2e 20 4e 6f 20  e in a file. No 
17f90 63 68 75 6e 6b 20 69 73 20 62 69 67 67 65 72 20  chunk is bigger 
17fa0 74 68 61 6e 20 6d 61 78 72 65 61 64 2e 27 27 27  than maxread.'''
17fb0 0a 20 20 20 20 66 70 2e 73 65 65 6b 28 6f 66 66  .    fp.seek(off
17fc0 73 65 74 29 0a 20 20 20 20 77 68 69 6c 65 20 62  set).    while b
17fd0 79 74 65 73 20 3e 20 30 3a 0a 20 20 20 20 20 20  ytes > 0:.      
17fe0 20 20 70 61 72 74 20 3d 20 66 70 2e 72 65 61 64    part = fp.read
17ff0 28 6d 69 6e 28 62 79 74 65 73 2c 20 6d 61 78 72  (min(bytes, maxr
18000 65 61 64 29 29 0a 20 20 20 20 20 20 20 20 69 66  ead)).        if
18010 20 6e 6f 74 20 70 61 72 74 3a 20 62 72 65 61 6b   not part: break
18020 0a 20 20 20 20 20 20 20 20 62 79 74 65 73 20 2d  .        bytes -
18030 3d 20 6c 65 6e 28 70 61 72 74 29 0a 20 20 20 20  = len(part).    
18040 20 20 20 20 79 69 65 6c 64 20 70 61 72 74 0a 0a      yield part..
18050 0a 64 65 66 20 73 74 61 74 69 63 5f 66 69 6c 65  .def static_file
18060 28 66 69 6c 65 6e 61 6d 65 2c 20 72 6f 6f 74 2c  (filename, root,
18070 20 6d 69 6d 65 74 79 70 65 3d 27 61 75 74 6f 27   mimetype='auto'
18080 2c 20 64 6f 77 6e 6c 6f 61 64 3d 46 61 6c 73 65  , download=False
18090 2c 20 63 68 61 72 73 65 74 3d 27 55 54 46 2d 38  , charset='UTF-8
180a0 27 29 3a 0a 20 20 20 20 22 22 22 20 4f 70 65 6e  '):.    """ Open
180b0 20 61 20 66 69 6c 65 20 69 6e 20 61 20 73 61 66   a file in a saf
180c0 65 20 77 61 79 20 61 6e 64 20 72 65 74 75 72 6e  e way and return
180d0 20 3a 65 78 63 3a 60 48 54 54 50 52 65 73 70 6f   :exc:`HTTPRespo
180e0 6e 73 65 60 20 77 69 74 68 20 73 74 61 74 75 73  nse` with status
180f0 0a 20 20 20 20 20 20 20 20 63 6f 64 65 20 32 30  .        code 20
18100 30 2c 20 33 30 35 2c 20 34 30 33 20 6f 72 20 34  0, 305, 403 or 4
18110 30 34 2e 20 54 68 65 20 60 60 43 6f 6e 74 65 6e  04. The ``Conten
18120 74 2d 54 79 70 65 60 60 2c 20 60 60 43 6f 6e 74  t-Type``, ``Cont
18130 65 6e 74 2d 45 6e 63 6f 64 69 6e 67 60 60 2c 0a  ent-Encoding``,.
18140 20 20 20 20 20 20 20 20 60 60 43 6f 6e 74 65 6e          ``Conten
18150 74 2d 4c 65 6e 67 74 68 60 60 20 61 6e 64 20 60  t-Length`` and `
18160 60 4c 61 73 74 2d 4d 6f 64 69 66 69 65 64 60 60  `Last-Modified``
18170 20 68 65 61 64 65 72 73 20 61 72 65 20 73 65 74   headers are set
18180 20 69 66 20 70 6f 73 73 69 62 6c 65 2e 0a 20 20   if possible..  
18190 20 20 20 20 20 20 53 70 65 63 69 61 6c 20 73 75        Special su
181a0 70 70 6f 72 74 20 66 6f 72 20 60 60 49 66 2d 4d  pport for ``If-M
181b0 6f 64 69 66 69 65 64 2d 53 69 6e 63 65 60 60 2c  odified-Since``,
181c0 20 60 60 52 61 6e 67 65 60 60 20 61 6e 64 20 60   ``Range`` and `
181d0 60 48 45 41 44 60 60 0a 20 20 20 20 20 20 20 20  `HEAD``.        
181e0 72 65 71 75 65 73 74 73 2e 0a 0a 20 20 20 20 20  requests...     
181f0 20 20 20 3a 70 61 72 61 6d 20 66 69 6c 65 6e 61     :param filena
18200 6d 65 3a 20 4e 61 6d 65 20 6f 72 20 70 61 74 68  me: Name or path
18210 20 6f 66 20 74 68 65 20 66 69 6c 65 20 74 6f 20   of the file to 
18220 73 65 6e 64 2e 0a 20 20 20 20 20 20 20 20 3a 70  send..        :p
18230 61 72 61 6d 20 72 6f 6f 74 3a 20 52 6f 6f 74 20  aram root: Root 
18240 70 61 74 68 20 66 6f 72 20 66 69 6c 65 20 6c 6f  path for file lo
18250 6f 6b 75 70 73 2e 20 53 68 6f 75 6c 64 20 62 65  okups. Should be
18260 20 61 6e 20 61 62 73 6f 6c 75 74 65 20 64 69 72   an absolute dir
18270 65 63 74 6f 72 79 0a 20 20 20 20 20 20 20 20 20  ectory.         
18280 20 20 20 70 61 74 68 2e 0a 20 20 20 20 20 20 20     path..       
18290 20 3a 70 61 72 61 6d 20 6d 69 6d 65 74 79 70 65   :param mimetype
182a0 3a 20 44 65 66 69 6e 65 73 20 74 68 65 20 63 6f  : Defines the co
182b0 6e 74 65 6e 74 2d 74 79 70 65 20 68 65 61 64 65  ntent-type heade
182c0 72 20 28 64 65 66 61 75 6c 74 3a 20 67 75 65 73  r (default: gues
182d0 73 20 66 72 6f 6d 0a 20 20 20 20 20 20 20 20 20  s from.         
182e0 20 20 20 66 69 6c 65 20 65 78 74 65 6e 73 69 6f     file extensio
182f0 6e 29 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61  n).        :para
18300 6d 20 64 6f 77 6e 6c 6f 61 64 3a 20 49 66 20 54  m download: If T
18310 72 75 65 2c 20 61 73 6b 20 74 68 65 20 62 72 6f  rue, ask the bro
18320 77 73 65 72 20 74 6f 20 6f 70 65 6e 20 61 20 60  wser to open a `
18330 53 61 76 65 20 61 73 2e 2e 2e 60 20 64 69 61 6c  Save as...` dial
18340 6f 67 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  og.            i
18350 6e 73 74 65 61 64 20 6f 66 20 6f 70 65 6e 69 6e  nstead of openin
18360 67 20 74 68 65 20 66 69 6c 65 20 77 69 74 68 20  g the file with 
18370 74 68 65 20 61 73 73 6f 63 69 61 74 65 64 20 70  the associated p
18380 72 6f 67 72 61 6d 2e 20 59 6f 75 20 63 61 6e 0a  rogram. You can.
18390 20 20 20 20 20 20 20 20 20 20 20 20 73 70 65 63              spec
183a0 69 66 79 20 61 20 63 75 73 74 6f 6d 20 66 69 6c  ify a custom fil
183b0 65 6e 61 6d 65 20 61 73 20 61 20 73 74 72 69 6e  ename as a strin
183c0 67 2e 20 49 66 20 6e 6f 74 20 73 70 65 63 69 66  g. If not specif
183d0 69 65 64 2c 20 74 68 65 0a 20 20 20 20 20 20 20  ied, the.       
183e0 20 20 20 20 20 6f 72 69 67 69 6e 61 6c 20 66 69       original fi
183f0 6c 65 6e 61 6d 65 20 69 73 20 75 73 65 64 20 28  lename is used (
18400 64 65 66 61 75 6c 74 3a 20 46 61 6c 73 65 29 2e  default: False).
18410 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20  .        :param 
18420 63 68 61 72 73 65 74 3a 20 54 68 65 20 63 68 61  charset: The cha
18430 72 73 65 74 20 74 6f 20 75 73 65 20 66 6f 72 20  rset to use for 
18440 66 69 6c 65 73 20 77 69 74 68 20 61 20 60 60 74  files with a ``t
18450 65 78 74 2f 2a 60 60 0a 20 20 20 20 20 20 20 20  ext/*``.        
18460 20 20 20 20 6d 69 6d 65 2d 74 79 70 65 2e 20 28      mime-type. (
18470 64 65 66 61 75 6c 74 3a 20 55 54 46 2d 38 29 0a  default: UTF-8).
18480 20 20 20 20 22 22 22 0a 0a 20 20 20 20 72 6f 6f      """..    roo
18490 74 20 3d 20 6f 73 2e 70 61 74 68 2e 61 62 73 70  t = os.path.absp
184a0 61 74 68 28 72 6f 6f 74 29 20 2b 20 6f 73 2e 73  ath(root) + os.s
184b0 65 70 0a 20 20 20 20 66 69 6c 65 6e 61 6d 65 20  ep.    filename 
184c0 3d 20 6f 73 2e 70 61 74 68 2e 61 62 73 70 61 74  = os.path.abspat
184d0 68 28 6f 73 2e 70 61 74 68 2e 6a 6f 69 6e 28 72  h(os.path.join(r
184e0 6f 6f 74 2c 20 66 69 6c 65 6e 61 6d 65 2e 73 74  oot, filename.st
184f0 72 69 70 28 27 2f 5c 5c 27 29 29 29 0a 20 20 20  rip('/\\'))).   
18500 20 68 65 61 64 65 72 73 20 3d 20 64 69 63 74 28   headers = dict(
18510 29 0a 0a 20 20 20 20 69 66 20 6e 6f 74 20 66 69  )..    if not fi
18520 6c 65 6e 61 6d 65 2e 73 74 61 72 74 73 77 69 74  lename.startswit
18530 68 28 72 6f 6f 74 29 3a 0a 20 20 20 20 20 20 20  h(root):.       
18540 20 72 65 74 75 72 6e 20 48 54 54 50 45 72 72 6f   return HTTPErro
18550 72 28 34 30 33 2c 20 22 41 63 63 65 73 73 20 64  r(403, "Access d
18560 65 6e 69 65 64 2e 22 29 0a 20 20 20 20 69 66 20  enied.").    if 
18570 6e 6f 74 20 6f 73 2e 70 61 74 68 2e 65 78 69 73  not os.path.exis
18580 74 73 28 66 69 6c 65 6e 61 6d 65 29 20 6f 72 20  ts(filename) or 
18590 6e 6f 74 20 6f 73 2e 70 61 74 68 2e 69 73 66 69  not os.path.isfi
185a0 6c 65 28 66 69 6c 65 6e 61 6d 65 29 3a 0a 20 20  le(filename):.  
185b0 20 20 20 20 20 20 72 65 74 75 72 6e 20 48 54 54        return HTT
185c0 50 45 72 72 6f 72 28 34 30 34 2c 20 22 46 69 6c  PError(404, "Fil
185d0 65 20 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74  e does not exist
185e0 2e 22 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6f  .").    if not o
185f0 73 2e 61 63 63 65 73 73 28 66 69 6c 65 6e 61 6d  s.access(filenam
18600 65 2c 20 6f 73 2e 52 5f 4f 4b 29 3a 0a 20 20 20  e, os.R_OK):.   
18610 20 20 20 20 20 72 65 74 75 72 6e 20 48 54 54 50       return HTTP
18620 45 72 72 6f 72 28 34 30 33 2c 20 22 59 6f 75 20  Error(403, "You 
18630 64 6f 20 6e 6f 74 20 68 61 76 65 20 70 65 72 6d  do not have perm
18640 69 73 73 69 6f 6e 20 74 6f 20 61 63 63 65 73 73  ission to access
18650 20 74 68 69 73 20 66 69 6c 65 2e 22 29 0a 0a 20   this file.").. 
18660 20 20 20 69 66 20 6d 69 6d 65 74 79 70 65 20 3d     if mimetype =
18670 3d 20 27 61 75 74 6f 27 3a 0a 20 20 20 20 20 20  = 'auto':.      
18680 20 20 6d 69 6d 65 74 79 70 65 2c 20 65 6e 63 6f    mimetype, enco
18690 64 69 6e 67 20 3d 20 6d 69 6d 65 74 79 70 65 73  ding = mimetypes
186a0 2e 67 75 65 73 73 5f 74 79 70 65 28 66 69 6c 65  .guess_type(file
186b0 6e 61 6d 65 29 0a 20 20 20 20 20 20 20 20 69 66  name).        if
186c0 20 65 6e 63 6f 64 69 6e 67 3a 20 68 65 61 64 65   encoding: heade
186d0 72 73 5b 27 43 6f 6e 74 65 6e 74 2d 45 6e 63 6f  rs['Content-Enco
186e0 64 69 6e 67 27 5d 20 3d 20 65 6e 63 6f 64 69 6e  ding'] = encodin
186f0 67 0a 0a 20 20 20 20 69 66 20 6d 69 6d 65 74 79  g..    if mimety
18700 70 65 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6d  pe:.        if m
18710 69 6d 65 74 79 70 65 5b 3a 35 5d 20 3d 3d 20 27  imetype[:5] == '
18720 74 65 78 74 2f 27 20 61 6e 64 20 63 68 61 72 73  text/' and chars
18730 65 74 20 61 6e 64 20 27 63 68 61 72 73 65 74 27  et and 'charset'
18740 20 6e 6f 74 20 69 6e 20 6d 69 6d 65 74 79 70 65   not in mimetype
18750 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6d 69  :.            mi
18760 6d 65 74 79 70 65 20 2b 3d 20 27 3b 20 63 68 61  metype += '; cha
18770 72 73 65 74 3d 25 73 27 20 25 20 63 68 61 72 73  rset=%s' % chars
18780 65 74 0a 20 20 20 20 20 20 20 20 68 65 61 64 65  et.        heade
18790 72 73 5b 27 43 6f 6e 74 65 6e 74 2d 54 79 70 65  rs['Content-Type
187a0 27 5d 20 3d 20 6d 69 6d 65 74 79 70 65 0a 0a 20  '] = mimetype.. 
187b0 20 20 20 69 66 20 64 6f 77 6e 6c 6f 61 64 3a 0a     if download:.
187c0 20 20 20 20 20 20 20 20 64 6f 77 6e 6c 6f 61 64          download
187d0 20 3d 20 6f 73 2e 70 61 74 68 2e 62 61 73 65 6e   = os.path.basen
187e0 61 6d 65 28 66 69 6c 65 6e 61 6d 65 20 69 66 20  ame(filename if 
187f0 64 6f 77 6e 6c 6f 61 64 20 3d 3d 20 54 72 75 65  download == True
18800 20 65 6c 73 65 20 64 6f 77 6e 6c 6f 61 64 29 0a   else download).
18810 20 20 20 20 20 20 20 20 68 65 61 64 65 72 73 5b          headers[
18820 27 43 6f 6e 74 65 6e 74 2d 44 69 73 70 6f 73 69  'Content-Disposi
18830 74 69 6f 6e 27 5d 20 3d 20 27 61 74 74 61 63 68  tion'] = 'attach
18840 6d 65 6e 74 3b 20 66 69 6c 65 6e 61 6d 65 3d 22  ment; filename="
18850 25 73 22 27 20 25 20 64 6f 77 6e 6c 6f 61 64 0a  %s"' % download.
18860 0a 20 20 20 20 73 74 61 74 73 20 3d 20 6f 73 2e  .    stats = os.
18870 73 74 61 74 28 66 69 6c 65 6e 61 6d 65 29 0a 20  stat(filename). 
18880 20 20 20 68 65 61 64 65 72 73 5b 27 43 6f 6e 74     headers['Cont
18890 65 6e 74 2d 4c 65 6e 67 74 68 27 5d 20 3d 20 63  ent-Length'] = c
188a0 6c 65 6e 20 3d 20 73 74 61 74 73 2e 73 74 5f 73  len = stats.st_s
188b0 69 7a 65 0a 20 20 20 20 6c 6d 20 3d 20 74 69 6d  ize.    lm = tim
188c0 65 2e 73 74 72 66 74 69 6d 65 28 22 25 61 2c 20  e.strftime("%a, 
188d0 25 64 20 25 62 20 25 59 20 25 48 3a 25 4d 3a 25  %d %b %Y %H:%M:%
188e0 53 20 47 4d 54 22 2c 20 74 69 6d 65 2e 67 6d 74  S GMT", time.gmt
188f0 69 6d 65 28 73 74 61 74 73 2e 73 74 5f 6d 74 69  ime(stats.st_mti
18900 6d 65 29 29 0a 20 20 20 20 68 65 61 64 65 72 73  me)).    headers
18910 5b 27 4c 61 73 74 2d 4d 6f 64 69 66 69 65 64 27  ['Last-Modified'
18920 5d 20 3d 20 6c 6d 0a 0a 20 20 20 20 69 6d 73 20  ] = lm..    ims 
18930 3d 20 72 65 71 75 65 73 74 2e 65 6e 76 69 72 6f  = request.enviro
18940 6e 2e 67 65 74 28 27 48 54 54 50 5f 49 46 5f 4d  n.get('HTTP_IF_M
18950 4f 44 49 46 49 45 44 5f 53 49 4e 43 45 27 29 0a  ODIFIED_SINCE').
18960 20 20 20 20 69 66 20 69 6d 73 3a 0a 20 20 20 20      if ims:.    
18970 20 20 20 20 69 6d 73 20 3d 20 70 61 72 73 65 5f      ims = parse_
18980 64 61 74 65 28 69 6d 73 2e 73 70 6c 69 74 28 22  date(ims.split("
18990 3b 22 29 5b 30 5d 2e 73 74 72 69 70 28 29 29 0a  ;")[0].strip()).
189a0 20 20 20 20 69 66 20 69 6d 73 20 69 73 20 6e 6f      if ims is no
189b0 74 20 4e 6f 6e 65 20 61 6e 64 20 69 6d 73 20 3e  t None and ims >
189c0 3d 20 69 6e 74 28 73 74 61 74 73 2e 73 74 5f 6d  = int(stats.st_m
189d0 74 69 6d 65 29 3a 0a 20 20 20 20 20 20 20 20 68  time):.        h
189e0 65 61 64 65 72 73 5b 27 44 61 74 65 27 5d 20 3d  eaders['Date'] =
189f0 20 74 69 6d 65 2e 73 74 72 66 74 69 6d 65 28 22   time.strftime("
18a00 25 61 2c 20 25 64 20 25 62 20 25 59 20 25 48 3a  %a, %d %b %Y %H:
18a10 25 4d 3a 25 53 20 47 4d 54 22 2c 20 74 69 6d 65  %M:%S GMT", time
18a20 2e 67 6d 74 69 6d 65 28 29 29 0a 20 20 20 20 20  .gmtime()).     
18a30 20 20 20 72 65 74 75 72 6e 20 48 54 54 50 52 65     return HTTPRe
18a40 73 70 6f 6e 73 65 28 73 74 61 74 75 73 3d 33 30  sponse(status=30
18a50 34 2c 20 2a 2a 68 65 61 64 65 72 73 29 0a 0a 20  4, **headers).. 
18a60 20 20 20 62 6f 64 79 20 3d 20 27 27 20 69 66 20     body = '' if 
18a70 72 65 71 75 65 73 74 2e 6d 65 74 68 6f 64 20 3d  request.method =
18a80 3d 20 27 48 45 41 44 27 20 65 6c 73 65 20 6f 70  = 'HEAD' else op
18a90 65 6e 28 66 69 6c 65 6e 61 6d 65 2c 20 27 72 62  en(filename, 'rb
18aa0 27 29 0a 0a 20 20 20 20 68 65 61 64 65 72 73 5b  ')..    headers[
18ab0 22 41 63 63 65 70 74 2d 52 61 6e 67 65 73 22 5d  "Accept-Ranges"]
18ac0 20 3d 20 22 62 79 74 65 73 22 0a 20 20 20 20 72   = "bytes".    r
18ad0 61 6e 67 65 73 20 3d 20 72 65 71 75 65 73 74 2e  anges = request.
18ae0 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27 48 54 54  environ.get('HTT
18af0 50 5f 52 41 4e 47 45 27 29 0a 20 20 20 20 69 66  P_RANGE').    if
18b00 20 27 48 54 54 50 5f 52 41 4e 47 45 27 20 69 6e   'HTTP_RANGE' in
18b10 20 72 65 71 75 65 73 74 2e 65 6e 76 69 72 6f 6e   request.environ
18b20 3a 0a 20 20 20 20 20 20 20 20 72 61 6e 67 65 73  :.        ranges
18b30 20 3d 20 6c 69 73 74 28 70 61 72 73 65 5f 72 61   = list(parse_ra
18b40 6e 67 65 5f 68 65 61 64 65 72 28 72 65 71 75 65  nge_header(reque
18b50 73 74 2e 65 6e 76 69 72 6f 6e 5b 27 48 54 54 50  st.environ['HTTP
18b60 5f 52 41 4e 47 45 27 5d 2c 20 63 6c 65 6e 29 29  _RANGE'], clen))
18b70 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
18b80 72 61 6e 67 65 73 3a 0a 20 20 20 20 20 20 20 20  ranges:.        
18b90 20 20 20 20 72 65 74 75 72 6e 20 48 54 54 50 45      return HTTPE
18ba0 72 72 6f 72 28 34 31 36 2c 20 22 52 65 71 75 65  rror(416, "Reque
18bb0 73 74 65 64 20 52 61 6e 67 65 20 4e 6f 74 20 53  sted Range Not S
18bc0 61 74 69 73 66 69 61 62 6c 65 22 29 0a 20 20 20  atisfiable").   
18bd0 20 20 20 20 20 6f 66 66 73 65 74 2c 20 65 6e 64       offset, end
18be0 20 3d 20 72 61 6e 67 65 73 5b 30 5d 0a 20 20 20   = ranges[0].   
18bf0 20 20 20 20 20 68 65 61 64 65 72 73 5b 22 43 6f       headers["Co
18c00 6e 74 65 6e 74 2d 52 61 6e 67 65 22 5d 20 3d 20  ntent-Range"] = 
18c10 22 62 79 74 65 73 20 25 64 2d 25 64 2f 25 64 22  "bytes %d-%d/%d"
18c20 20 25 20 28 6f 66 66 73 65 74 2c 20 65 6e 64 2d   % (offset, end-
18c30 31 2c 20 63 6c 65 6e 29 0a 20 20 20 20 20 20 20  1, clen).       
18c40 20 68 65 61 64 65 72 73 5b 22 43 6f 6e 74 65 6e   headers["Conten
18c50 74 2d 4c 65 6e 67 74 68 22 5d 20 3d 20 73 74 72  t-Length"] = str
18c60 28 65 6e 64 2d 6f 66 66 73 65 74 29 0a 20 20 20  (end-offset).   
18c70 20 20 20 20 20 69 66 20 62 6f 64 79 3a 20 62 6f       if body: bo
18c80 64 79 20 3d 20 5f 66 69 6c 65 5f 69 74 65 72 5f  dy = _file_iter_
18c90 72 61 6e 67 65 28 62 6f 64 79 2c 20 6f 66 66 73  range(body, offs
18ca0 65 74 2c 20 65 6e 64 2d 6f 66 66 73 65 74 29 0a  et, end-offset).
18cb0 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 48          return H
18cc0 54 54 50 52 65 73 70 6f 6e 73 65 28 62 6f 64 79  TTPResponse(body
18cd0 2c 20 73 74 61 74 75 73 3d 32 30 36 2c 20 2a 2a  , status=206, **
18ce0 68 65 61 64 65 72 73 29 0a 20 20 20 20 72 65 74  headers).    ret
18cf0 75 72 6e 20 48 54 54 50 52 65 73 70 6f 6e 73 65  urn HTTPResponse
18d00 28 62 6f 64 79 2c 20 2a 2a 68 65 61 64 65 72 73  (body, **headers
18d10 29 0a 0a 0a 0a 0a 0a 0a 23 23 23 23 23 23 23 23  ).......########
18d20 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18d30 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18d40 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18d50 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18d60 23 23 23 23 23 23 23 0a 23 20 48 54 54 50 20 55  #######.# HTTP U
18d70 74 69 6c 69 74 69 65 73 20 61 6e 64 20 4d 49 53  tilities and MIS
18d80 43 20 28 54 4f 44 4f 29 20 23 23 23 23 23 23 23  C (TODO) #######
18d90 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18da0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18db0 23 23 23 23 23 23 23 23 0a 23 23 23 23 23 23 23  ########.#######
18dc0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18dd0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18de0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18df0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
18e00 23 23 23 23 23 23 23 23 0a 0a 0a 64 65 66 20 64  ########...def d
18e10 65 62 75 67 28 6d 6f 64 65 3d 54 72 75 65 29 3a  ebug(mode=True):
18e20 0a 20 20 20 20 22 22 22 20 43 68 61 6e 67 65 20  .    """ Change 
18e30 74 68 65 20 64 65 62 75 67 20 6c 65 76 65 6c 2e  the debug level.
18e40 0a 20 20 20 20 54 68 65 72 65 20 69 73 20 6f 6e  .    There is on
18e50 6c 79 20 6f 6e 65 20 64 65 62 75 67 20 6c 65 76  ly one debug lev
18e60 65 6c 20 73 75 70 70 6f 72 74 65 64 20 61 74 20  el supported at 
18e70 74 68 65 20 6d 6f 6d 65 6e 74 2e 22 22 22 0a 20  the moment.""". 
18e80 20 20 20 67 6c 6f 62 61 6c 20 44 45 42 55 47 0a     global DEBUG.
18e90 20 20 20 20 69 66 20 6d 6f 64 65 3a 20 77 61 72      if mode: war
18ea0 6e 69 6e 67 73 2e 73 69 6d 70 6c 65 66 69 6c 74  nings.simplefilt
18eb0 65 72 28 27 64 65 66 61 75 6c 74 27 29 0a 20 20  er('default').  
18ec0 20 20 44 45 42 55 47 20 3d 20 62 6f 6f 6c 28 6d    DEBUG = bool(m
18ed0 6f 64 65 29 0a 0a 64 65 66 20 68 74 74 70 5f 64  ode)..def http_d
18ee0 61 74 65 28 76 61 6c 75 65 29 3a 0a 20 20 20 20  ate(value):.    
18ef0 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 76 61  if isinstance(va
18f00 6c 75 65 2c 20 28 64 61 74 65 64 61 74 65 2c 20  lue, (datedate, 
18f10 64 61 74 65 74 69 6d 65 29 29 3a 0a 20 20 20 20  datetime)):.    
18f20 20 20 20 20 76 61 6c 75 65 20 3d 20 76 61 6c 75      value = valu
18f30 65 2e 75 74 63 74 69 6d 65 74 75 70 6c 65 28 29  e.utctimetuple()
18f40 0a 20 20 20 20 65 6c 69 66 20 69 73 69 6e 73 74  .    elif isinst
18f50 61 6e 63 65 28 76 61 6c 75 65 2c 20 28 69 6e 74  ance(value, (int
18f60 2c 20 66 6c 6f 61 74 29 29 3a 0a 20 20 20 20 20  , float)):.     
18f70 20 20 20 76 61 6c 75 65 20 3d 20 74 69 6d 65 2e     value = time.
18f80 67 6d 74 69 6d 65 28 76 61 6c 75 65 29 0a 20 20  gmtime(value).  
18f90 20 20 69 66 20 6e 6f 74 20 69 73 69 6e 73 74 61    if not isinsta
18fa0 6e 63 65 28 76 61 6c 75 65 2c 20 62 61 73 65 73  nce(value, bases
18fb0 74 72 69 6e 67 29 3a 0a 20 20 20 20 20 20 20 20  tring):.        
18fc0 76 61 6c 75 65 20 3d 20 74 69 6d 65 2e 73 74 72  value = time.str
18fd0 66 74 69 6d 65 28 22 25 61 2c 20 25 64 20 25 62  ftime("%a, %d %b
18fe0 20 25 59 20 25 48 3a 25 4d 3a 25 53 20 47 4d 54   %Y %H:%M:%S GMT
18ff0 22 2c 20 76 61 6c 75 65 29 0a 20 20 20 20 72 65  ", value).    re
19000 74 75 72 6e 20 76 61 6c 75 65 0a 0a 64 65 66 20  turn value..def 
19010 70 61 72 73 65 5f 64 61 74 65 28 69 6d 73 29 3a  parse_date(ims):
19020 0a 20 20 20 20 22 22 22 20 50 61 72 73 65 20 72  .    """ Parse r
19030 66 63 31 31 32 33 2c 20 72 66 63 38 35 30 20 61  fc1123, rfc850 a
19040 6e 64 20 61 73 63 74 69 6d 65 20 74 69 6d 65 73  nd asctime times
19050 74 61 6d 70 73 20 61 6e 64 20 72 65 74 75 72 6e  tamps and return
19060 20 55 54 43 20 65 70 6f 63 68 2e 20 22 22 22 0a   UTC epoch. """.
19070 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
19080 20 74 73 20 3d 20 65 6d 61 69 6c 2e 75 74 69 6c   ts = email.util
19090 73 2e 70 61 72 73 65 64 61 74 65 5f 74 7a 28 69  s.parsedate_tz(i
190a0 6d 73 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  ms).        retu
190b0 72 6e 20 74 69 6d 65 2e 6d 6b 74 69 6d 65 28 74  rn time.mktime(t
190c0 73 5b 3a 38 5d 20 2b 20 28 30 2c 29 29 20 2d 20  s[:8] + (0,)) - 
190d0 28 74 73 5b 39 5d 20 6f 72 20 30 29 20 2d 20 74  (ts[9] or 0) - t
190e0 69 6d 65 2e 74 69 6d 65 7a 6f 6e 65 0a 20 20 20  ime.timezone.   
190f0 20 65 78 63 65 70 74 20 28 54 79 70 65 45 72 72   except (TypeErr
19100 6f 72 2c 20 56 61 6c 75 65 45 72 72 6f 72 2c 20  or, ValueError, 
19110 49 6e 64 65 78 45 72 72 6f 72 2c 20 4f 76 65 72  IndexError, Over
19120 66 6c 6f 77 45 72 72 6f 72 29 3a 0a 20 20 20 20  flowError):.    
19130 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a      return None.
19140 0a 64 65 66 20 70 61 72 73 65 5f 61 75 74 68 28  .def parse_auth(
19150 68 65 61 64 65 72 29 3a 0a 20 20 20 20 22 22 22  header):.    """
19160 20 50 61 72 73 65 20 72 66 63 32 36 31 37 20 48   Parse rfc2617 H
19170 54 54 50 20 61 75 74 68 65 6e 74 69 63 61 74 69  TTP authenticati
19180 6f 6e 20 68 65 61 64 65 72 20 73 74 72 69 6e 67  on header string
19190 20 28 62 61 73 69 63 29 20 61 6e 64 20 72 65 74   (basic) and ret
191a0 75 72 6e 20 28 75 73 65 72 2c 70 61 73 73 29 20  urn (user,pass) 
191b0 74 75 70 6c 65 20 6f 72 20 4e 6f 6e 65 22 22 22  tuple or None"""
191c0 0a 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20  .    try:.      
191d0 20 20 6d 65 74 68 6f 64 2c 20 64 61 74 61 20 3d    method, data =
191e0 20 68 65 61 64 65 72 2e 73 70 6c 69 74 28 4e 6f   header.split(No
191f0 6e 65 2c 20 31 29 0a 20 20 20 20 20 20 20 20 69  ne, 1).        i
19200 66 20 6d 65 74 68 6f 64 2e 6c 6f 77 65 72 28 29  f method.lower()
19210 20 3d 3d 20 27 62 61 73 69 63 27 3a 0a 20 20 20   == 'basic':.   
19220 20 20 20 20 20 20 20 20 20 75 73 65 72 2c 20 70           user, p
19230 77 64 20 3d 20 74 6f 75 6e 69 28 62 61 73 65 36  wd = touni(base6
19240 34 2e 62 36 34 64 65 63 6f 64 65 28 74 6f 62 28  4.b64decode(tob(
19250 64 61 74 61 29 29 29 2e 73 70 6c 69 74 28 27 3a  data))).split(':
19260 27 2c 31 29 0a 20 20 20 20 20 20 20 20 20 20 20  ',1).           
19270 20 72 65 74 75 72 6e 20 75 73 65 72 2c 20 70 77   return user, pw
19280 64 0a 20 20 20 20 65 78 63 65 70 74 20 28 4b 65  d.    except (Ke
19290 79 45 72 72 6f 72 2c 20 56 61 6c 75 65 45 72 72  yError, ValueErr
192a0 6f 72 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74  or):.        ret
192b0 75 72 6e 20 4e 6f 6e 65 0a 0a 64 65 66 20 70 61  urn None..def pa
192c0 72 73 65 5f 72 61 6e 67 65 5f 68 65 61 64 65 72  rse_range_header
192d0 28 68 65 61 64 65 72 2c 20 6d 61 78 6c 65 6e 3d  (header, maxlen=
192e0 30 29 3a 0a 20 20 20 20 27 27 27 20 59 69 65 6c  0):.    ''' Yiel
192f0 64 20 28 73 74 61 72 74 2c 20 65 6e 64 29 20 72  d (start, end) r
19300 61 6e 67 65 73 20 70 61 72 73 65 64 20 66 72 6f  anges parsed fro
19310 6d 20 61 20 48 54 54 50 20 52 61 6e 67 65 20 68  m a HTTP Range h
19320 65 61 64 65 72 2e 20 53 6b 69 70 0a 20 20 20 20  eader. Skip.    
19330 20 20 20 20 75 6e 73 61 74 69 73 66 69 61 62 6c      unsatisfiabl
19340 65 20 72 61 6e 67 65 73 2e 20 54 68 65 20 65 6e  e ranges. The en
19350 64 20 69 6e 64 65 78 20 69 73 20 6e 6f 6e 2d 69  d index is non-i
19360 6e 63 6c 75 73 69 76 65 2e 27 27 27 0a 20 20 20  nclusive.'''.   
19370 20 69 66 20 6e 6f 74 20 68 65 61 64 65 72 20 6f   if not header o
19380 72 20 68 65 61 64 65 72 5b 3a 36 5d 20 21 3d 20  r header[:6] != 
19390 27 62 79 74 65 73 3d 27 3a 20 72 65 74 75 72 6e  'bytes=': return
193a0 0a 20 20 20 20 72 61 6e 67 65 73 20 3d 20 5b 72  .    ranges = [r
193b0 2e 73 70 6c 69 74 28 27 2d 27 2c 20 31 29 20 66  .split('-', 1) f
193c0 6f 72 20 72 20 69 6e 20 68 65 61 64 65 72 5b 36  or r in header[6
193d0 3a 5d 2e 73 70 6c 69 74 28 27 2c 27 29 20 69 66  :].split(',') if
193e0 20 27 2d 27 20 69 6e 20 72 5d 0a 20 20 20 20 66   '-' in r].    f
193f0 6f 72 20 73 74 61 72 74 2c 20 65 6e 64 20 69 6e  or start, end in
19400 20 72 61 6e 67 65 73 3a 0a 20 20 20 20 20 20 20   ranges:.       
19410 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20   try:.          
19420 20 20 69 66 20 6e 6f 74 20 73 74 61 72 74 3a 20    if not start: 
19430 20 23 20 62 79 74 65 73 3d 2d 31 30 30 20 20 20   # bytes=-100   
19440 20 2d 3e 20 6c 61 73 74 20 31 30 30 20 62 79 74   -> last 100 byt
19450 65 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  es.             
19460 20 20 20 73 74 61 72 74 2c 20 65 6e 64 20 3d 20     start, end = 
19470 6d 61 78 28 30 2c 20 6d 61 78 6c 65 6e 2d 69 6e  max(0, maxlen-in
19480 74 28 65 6e 64 29 29 2c 20 6d 61 78 6c 65 6e 0a  t(end)), maxlen.
19490 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
194a0 20 6e 6f 74 20 65 6e 64 3a 20 20 23 20 62 79 74   not end:  # byt
194b0 65 73 3d 31 30 30 2d 20 20 20 20 2d 3e 20 61 6c  es=100-    -> al
194c0 6c 20 62 75 74 20 74 68 65 20 66 69 72 73 74 20  l but the first 
194d0 39 39 20 62 79 74 65 73 0a 20 20 20 20 20 20 20  99 bytes.       
194e0 20 20 20 20 20 20 20 20 20 73 74 61 72 74 2c 20           start, 
194f0 65 6e 64 20 3d 20 69 6e 74 28 73 74 61 72 74 29  end = int(start)
19500 2c 20 6d 61 78 6c 65 6e 0a 20 20 20 20 20 20 20  , maxlen.       
19510 20 20 20 20 20 65 6c 73 65 3a 20 20 20 20 20 20       else:      
19520 20 20 20 20 23 20 62 79 74 65 73 3d 31 30 30 2d      # bytes=100-
19530 32 30 30 20 2d 3e 20 62 79 74 65 73 20 31 30 30  200 -> bytes 100
19540 2d 32 30 30 20 28 69 6e 63 6c 75 73 69 76 65 29  -200 (inclusive)
19550 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
19560 20 73 74 61 72 74 2c 20 65 6e 64 20 3d 20 69 6e   start, end = in
19570 74 28 73 74 61 72 74 29 2c 20 6d 69 6e 28 69 6e  t(start), min(in
19580 74 28 65 6e 64 29 2b 31 2c 20 6d 61 78 6c 65 6e  t(end)+1, maxlen
19590 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
195a0 20 30 20 3c 3d 20 73 74 61 72 74 20 3c 20 65 6e   0 <= start < en
195b0 64 20 3c 3d 20 6d 61 78 6c 65 6e 3a 0a 20 20 20  d <= maxlen:.   
195c0 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65               yie
195d0 6c 64 20 73 74 61 72 74 2c 20 65 6e 64 0a 20 20  ld start, end.  
195e0 20 20 20 20 20 20 65 78 63 65 70 74 20 56 61 6c        except Val
195f0 75 65 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20  ueError:.       
19600 20 20 20 20 20 70 61 73 73 0a 0a 64 65 66 20 5f       pass..def _
19610 70 61 72 73 65 5f 71 73 6c 28 71 73 29 3a 0a 20  parse_qsl(qs):. 
19620 20 20 20 72 20 3d 20 5b 5d 0a 20 20 20 20 66 6f     r = [].    fo
19630 72 20 70 61 69 72 20 69 6e 20 71 73 2e 72 65 70  r pair in qs.rep
19640 6c 61 63 65 28 27 3b 27 2c 27 26 27 29 2e 73 70  lace(';','&').sp
19650 6c 69 74 28 27 26 27 29 3a 0a 20 20 20 20 20 20  lit('&'):.      
19660 20 20 69 66 20 6e 6f 74 20 70 61 69 72 3a 20 63    if not pair: c
19670 6f 6e 74 69 6e 75 65 0a 20 20 20 20 20 20 20 20  ontinue.        
19680 6e 76 20 3d 20 70 61 69 72 2e 73 70 6c 69 74 28  nv = pair.split(
19690 27 3d 27 2c 20 31 29 0a 20 20 20 20 20 20 20 20  '=', 1).        
196a0 69 66 20 6c 65 6e 28 6e 76 29 20 21 3d 20 32 3a  if len(nv) != 2:
196b0 20 6e 76 2e 61 70 70 65 6e 64 28 27 27 29 0a 20   nv.append(''). 
196c0 20 20 20 20 20 20 20 6b 65 79 20 3d 20 75 72 6c         key = url
196d0 75 6e 71 75 6f 74 65 28 6e 76 5b 30 5d 2e 72 65  unquote(nv[0].re
196e0 70 6c 61 63 65 28 27 2b 27 2c 20 27 20 27 29 29  place('+', ' '))
196f0 0a 20 20 20 20 20 20 20 20 76 61 6c 75 65 20 3d  .        value =
19700 20 75 72 6c 75 6e 71 75 6f 74 65 28 6e 76 5b 31   urlunquote(nv[1
19710 5d 2e 72 65 70 6c 61 63 65 28 27 2b 27 2c 20 27  ].replace('+', '
19720 20 27 29 29 0a 20 20 20 20 20 20 20 20 72 2e 61   ')).        r.a
19730 70 70 65 6e 64 28 28 6b 65 79 2c 20 76 61 6c 75  ppend((key, valu
19740 65 29 29 0a 20 20 20 20 72 65 74 75 72 6e 20 72  e)).    return r
19750 0a 0a 64 65 66 20 5f 6c 73 63 6d 70 28 61 2c 20  ..def _lscmp(a, 
19760 62 29 3a 0a 20 20 20 20 27 27 27 20 43 6f 6d 70  b):.    ''' Comp
19770 61 72 65 73 20 74 77 6f 20 73 74 72 69 6e 67 73  ares two strings
19780 20 69 6e 20 61 20 63 72 79 70 74 6f 67 72 61 70   in a cryptograp
19790 68 69 63 61 6c 6c 79 20 73 61 66 65 20 77 61 79  hically safe way
197a0 3a 0a 20 20 20 20 20 20 20 20 52 75 6e 74 69 6d  :.        Runtim
197b0 65 20 69 73 20 6e 6f 74 20 61 66 66 65 63 74 65  e is not affecte
197c0 64 20 62 79 20 6c 65 6e 67 74 68 20 6f 66 20 63  d by length of c
197d0 6f 6d 6d 6f 6e 20 70 72 65 66 69 78 2e 20 27 27  ommon prefix. ''
197e0 27 0a 20 20 20 20 72 65 74 75 72 6e 20 6e 6f 74  '.    return not
197f0 20 73 75 6d 28 30 20 69 66 20 78 3d 3d 79 20 65   sum(0 if x==y e
19800 6c 73 65 20 31 20 66 6f 72 20 78 2c 20 79 20 69  lse 1 for x, y i
19810 6e 20 7a 69 70 28 61 2c 20 62 29 29 20 61 6e 64  n zip(a, b)) and
19820 20 6c 65 6e 28 61 29 20 3d 3d 20 6c 65 6e 28 62   len(a) == len(b
19830 29 0a 0a 0a 64 65 66 20 63 6f 6f 6b 69 65 5f 65  )...def cookie_e
19840 6e 63 6f 64 65 28 64 61 74 61 2c 20 6b 65 79 29  ncode(data, key)
19850 3a 0a 20 20 20 20 27 27 27 20 45 6e 63 6f 64 65  :.    ''' Encode
19860 20 61 6e 64 20 73 69 67 6e 20 61 20 70 69 63 6b   and sign a pick
19870 6c 65 2d 61 62 6c 65 20 6f 62 6a 65 63 74 2e 20  le-able object. 
19880 52 65 74 75 72 6e 20 61 20 28 62 79 74 65 29 20  Return a (byte) 
19890 73 74 72 69 6e 67 20 27 27 27 0a 20 20 20 20 6d  string '''.    m
198a0 73 67 20 3d 20 62 61 73 65 36 34 2e 62 36 34 65  sg = base64.b64e
198b0 6e 63 6f 64 65 28 70 69 63 6b 6c 65 2e 64 75 6d  ncode(pickle.dum
198c0 70 73 28 64 61 74 61 2c 20 2d 31 29 29 0a 20 20  ps(data, -1)).  
198d0 20 20 73 69 67 20 3d 20 62 61 73 65 36 34 2e 62    sig = base64.b
198e0 36 34 65 6e 63 6f 64 65 28 68 6d 61 63 2e 6e 65  64encode(hmac.ne
198f0 77 28 74 6f 62 28 6b 65 79 29 2c 20 6d 73 67 29  w(tob(key), msg)
19900 2e 64 69 67 65 73 74 28 29 29 0a 20 20 20 20 72  .digest()).    r
19910 65 74 75 72 6e 20 74 6f 62 28 27 21 27 29 20 2b  eturn tob('!') +
19920 20 73 69 67 20 2b 20 74 6f 62 28 27 3f 27 29 20   sig + tob('?') 
19930 2b 20 6d 73 67 0a 0a 0a 64 65 66 20 63 6f 6f 6b  + msg...def cook
19940 69 65 5f 64 65 63 6f 64 65 28 64 61 74 61 2c 20  ie_decode(data, 
19950 6b 65 79 29 3a 0a 20 20 20 20 27 27 27 20 56 65  key):.    ''' Ve
19960 72 69 66 79 20 61 6e 64 20 64 65 63 6f 64 65 20  rify and decode 
19970 61 6e 20 65 6e 63 6f 64 65 64 20 73 74 72 69 6e  an encoded strin
19980 67 2e 20 52 65 74 75 72 6e 20 61 6e 20 6f 62 6a  g. Return an obj
19990 65 63 74 20 6f 72 20 4e 6f 6e 65 2e 27 27 27 0a  ect or None.'''.
199a0 20 20 20 20 64 61 74 61 20 3d 20 74 6f 62 28 64      data = tob(d
199b0 61 74 61 29 0a 20 20 20 20 69 66 20 63 6f 6f 6b  ata).    if cook
199c0 69 65 5f 69 73 5f 65 6e 63 6f 64 65 64 28 64 61  ie_is_encoded(da
199d0 74 61 29 3a 0a 20 20 20 20 20 20 20 20 73 69 67  ta):.        sig
199e0 2c 20 6d 73 67 20 3d 20 64 61 74 61 2e 73 70 6c  , msg = data.spl
199f0 69 74 28 74 6f 62 28 27 3f 27 29 2c 20 31 29 0a  it(tob('?'), 1).
19a00 20 20 20 20 20 20 20 20 69 66 20 5f 6c 73 63 6d          if _lscm
19a10 70 28 73 69 67 5b 31 3a 5d 2c 20 62 61 73 65 36  p(sig[1:], base6
19a20 34 2e 62 36 34 65 6e 63 6f 64 65 28 68 6d 61 63  4.b64encode(hmac
19a30 2e 6e 65 77 28 74 6f 62 28 6b 65 79 29 2c 20 6d  .new(tob(key), m
19a40 73 67 29 2e 64 69 67 65 73 74 28 29 29 29 3a 0a  sg).digest())):.
19a50 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
19a60 72 6e 20 70 69 63 6b 6c 65 2e 6c 6f 61 64 73 28  rn pickle.loads(
19a70 62 61 73 65 36 34 2e 62 36 34 64 65 63 6f 64 65  base64.b64decode
19a80 28 6d 73 67 29 29 0a 20 20 20 20 72 65 74 75 72  (msg)).    retur
19a90 6e 20 4e 6f 6e 65 0a 0a 0a 64 65 66 20 63 6f 6f  n None...def coo
19aa0 6b 69 65 5f 69 73 5f 65 6e 63 6f 64 65 64 28 64  kie_is_encoded(d
19ab0 61 74 61 29 3a 0a 20 20 20 20 27 27 27 20 52 65  ata):.    ''' Re
19ac0 74 75 72 6e 20 54 72 75 65 20 69 66 20 74 68 65  turn True if the
19ad0 20 61 72 67 75 6d 65 6e 74 20 6c 6f 6f 6b 73 20   argument looks 
19ae0 6c 69 6b 65 20 61 20 65 6e 63 6f 64 65 64 20 63  like a encoded c
19af0 6f 6f 6b 69 65 2e 27 27 27 0a 20 20 20 20 72 65  ookie.'''.    re
19b00 74 75 72 6e 20 62 6f 6f 6c 28 64 61 74 61 2e 73  turn bool(data.s
19b10 74 61 72 74 73 77 69 74 68 28 74 6f 62 28 27 21  tartswith(tob('!
19b20 27 29 29 20 61 6e 64 20 74 6f 62 28 27 3f 27 29  ')) and tob('?')
19b30 20 69 6e 20 64 61 74 61 29 0a 0a 0a 64 65 66 20   in data)...def 
19b40 68 74 6d 6c 5f 65 73 63 61 70 65 28 73 74 72 69  html_escape(stri
19b50 6e 67 29 3a 0a 20 20 20 20 27 27 27 20 45 73 63  ng):.    ''' Esc
19b60 61 70 65 20 48 54 4d 4c 20 73 70 65 63 69 61 6c  ape HTML special
19b70 20 63 68 61 72 61 63 74 65 72 73 20 60 60 26 3c   characters ``&<
19b80 3e 60 60 20 61 6e 64 20 71 75 6f 74 65 73 20 60  >`` and quotes `
19b90 60 27 22 60 60 2e 20 27 27 27 0a 20 20 20 20 72  `'"``. '''.    r
19ba0 65 74 75 72 6e 20 73 74 72 69 6e 67 2e 72 65 70  eturn string.rep
19bb0 6c 61 63 65 28 27 26 27 2c 27 26 61 6d 70 3b 27  lace('&','&amp;'
19bc0 29 2e 72 65 70 6c 61 63 65 28 27 3c 27 2c 27 26  ).replace('<','&
19bd0 6c 74 3b 27 29 2e 72 65 70 6c 61 63 65 28 27 3e  lt;').replace('>
19be0 27 2c 27 26 67 74 3b 27 29 5c 0a 20 20 20 20 20  ','&gt;')\.     
19bf0 20 20 20 20 20 20 20 20 20 20 20 20 2e 72 65 70              .rep
19c00 6c 61 63 65 28 27 22 27 2c 27 26 71 75 6f 74 3b  lace('"','&quot;
19c10 27 29 2e 72 65 70 6c 61 63 65 28 22 27 22 2c 27  ').replace("'",'
19c20 26 23 30 33 39 3b 27 29 0a 0a 0a 64 65 66 20 68  &#039;')...def h
19c30 74 6d 6c 5f 71 75 6f 74 65 28 73 74 72 69 6e 67  tml_quote(string
19c40 29 3a 0a 20 20 20 20 27 27 27 20 45 73 63 61 70  ):.    ''' Escap
19c50 65 20 61 6e 64 20 71 75 6f 74 65 20 61 20 73 74  e and quote a st
19c60 72 69 6e 67 20 74 6f 20 62 65 20 75 73 65 64 20  ring to be used 
19c70 61 73 20 61 6e 20 48 54 54 50 20 61 74 74 72 69  as an HTTP attri
19c80 62 75 74 65 2e 27 27 27 0a 20 20 20 20 72 65 74  bute.'''.    ret
19c90 75 72 6e 20 27 22 25 73 22 27 20 25 20 68 74 6d  urn '"%s"' % htm
19ca0 6c 5f 65 73 63 61 70 65 28 73 74 72 69 6e 67 29  l_escape(string)
19cb0 2e 72 65 70 6c 61 63 65 28 27 5c 6e 27 2c 27 26  .replace('\n','&
19cc0 23 31 30 3b 27 29 5c 0a 20 20 20 20 20 20 20 20  #10;')\.        
19cd0 20 20 20 20 20 20 20 20 20 20 20 20 2e 72 65 70              .rep
19ce0 6c 61 63 65 28 27 5c 72 27 2c 27 26 23 31 33 3b  lace('\r','&#13;
19cf0 27 29 2e 72 65 70 6c 61 63 65 28 27 5c 74 27 2c  ').replace('\t',
19d00 27 26 23 39 3b 27 29 0a 0a 0a 64 65 66 20 79 69  '&#9;')...def yi
19d10 65 6c 64 72 6f 75 74 65 73 28 66 75 6e 63 29 3a  eldroutes(func):
19d20 0a 20 20 20 20 22 22 22 20 52 65 74 75 72 6e 20  .    """ Return 
19d30 61 20 67 65 6e 65 72 61 74 6f 72 20 66 6f 72 20  a generator for 
19d40 72 6f 75 74 65 73 20 74 68 61 74 20 6d 61 74 63  routes that matc
19d50 68 20 74 68 65 20 73 69 67 6e 61 74 75 72 65 20  h the signature 
19d60 28 6e 61 6d 65 2c 20 61 72 67 73 29 0a 20 20 20  (name, args).   
19d70 20 6f 66 20 74 68 65 20 66 75 6e 63 20 70 61 72   of the func par
19d80 61 6d 65 74 65 72 2e 20 54 68 69 73 20 6d 61 79  ameter. This may
19d90 20 79 69 65 6c 64 20 6d 6f 72 65 20 74 68 61 6e   yield more than
19da0 20 6f 6e 65 20 72 6f 75 74 65 20 69 66 20 74 68   one route if th
19db0 65 20 66 75 6e 63 74 69 6f 6e 0a 20 20 20 20 74  e function.    t
19dc0 61 6b 65 73 20 6f 70 74 69 6f 6e 61 6c 20 6b 65  akes optional ke
19dd0 79 77 6f 72 64 20 61 72 67 75 6d 65 6e 74 73 2e  yword arguments.
19de0 20 54 68 65 20 6f 75 74 70 75 74 20 69 73 20 62   The output is b
19df0 65 73 74 20 64 65 73 63 72 69 62 65 64 20 62 79  est described by
19e00 20 65 78 61 6d 70 6c 65 3a 3a 0a 0a 20 20 20 20   example::..    
19e10 20 20 20 20 61 28 29 20 20 20 20 20 20 20 20 20      a()         
19e20 2d 3e 20 27 2f 61 27 0a 20 20 20 20 20 20 20 20  -> '/a'.        
19e30 62 28 78 2c 20 79 29 20 20 20 20 20 2d 3e 20 27  b(x, y)     -> '
19e40 2f 62 2f 3c 78 3e 2f 3c 79 3e 27 0a 20 20 20 20  /b/<x>/<y>'.    
19e50 20 20 20 20 63 28 78 2c 20 79 3d 35 29 20 20 20      c(x, y=5)   
19e60 2d 3e 20 27 2f 63 2f 3c 78 3e 27 20 61 6e 64 20  -> '/c/<x>' and 
19e70 27 2f 63 2f 3c 78 3e 2f 3c 79 3e 27 0a 20 20 20  '/c/<x>/<y>'.   
19e80 20 20 20 20 20 64 28 78 3d 35 2c 20 79 3d 36 29       d(x=5, y=6)
19e90 20 2d 3e 20 27 2f 64 27 20 61 6e 64 20 27 2f 64   -> '/d' and '/d
19ea0 2f 3c 78 3e 27 20 61 6e 64 20 27 2f 64 2f 3c 78  /<x>' and '/d/<x
19eb0 3e 2f 3c 79 3e 27 0a 20 20 20 20 22 22 22 0a 20  >/<y>'.    """. 
19ec0 20 20 20 70 61 74 68 20 3d 20 27 2f 27 20 2b 20     path = '/' + 
19ed0 66 75 6e 63 2e 5f 5f 6e 61 6d 65 5f 5f 2e 72 65  func.__name__.re
19ee0 70 6c 61 63 65 28 27 5f 5f 27 2c 27 2f 27 29 2e  place('__','/').
19ef0 6c 73 74 72 69 70 28 27 2f 27 29 0a 20 20 20 20  lstrip('/').    
19f00 73 70 65 63 20 3d 20 67 65 74 61 72 67 73 70 65  spec = getargspe
19f10 63 28 66 75 6e 63 29 0a 20 20 20 20 61 72 67 63  c(func).    argc
19f20 20 3d 20 6c 65 6e 28 73 70 65 63 5b 30 5d 29 20   = len(spec[0]) 
19f30 2d 20 6c 65 6e 28 73 70 65 63 5b 33 5d 20 6f 72  - len(spec[3] or
19f40 20 5b 5d 29 0a 20 20 20 20 70 61 74 68 20 2b 3d   []).    path +=
19f50 20 28 27 2f 3c 25 73 3e 27 20 2a 20 61 72 67 63   ('/<%s>' * argc
19f60 29 20 25 20 74 75 70 6c 65 28 73 70 65 63 5b 30  ) % tuple(spec[0
19f70 5d 5b 3a 61 72 67 63 5d 29 0a 20 20 20 20 79 69  ][:argc]).    yi
19f80 65 6c 64 20 70 61 74 68 0a 20 20 20 20 66 6f 72  eld path.    for
19f90 20 61 72 67 20 69 6e 20 73 70 65 63 5b 30 5d 5b   arg in spec[0][
19fa0 61 72 67 63 3a 5d 3a 0a 20 20 20 20 20 20 20 20  argc:]:.        
19fb0 70 61 74 68 20 2b 3d 20 27 2f 3c 25 73 3e 27 20  path += '/<%s>' 
19fc0 25 20 61 72 67 0a 20 20 20 20 20 20 20 20 79 69  % arg.        yi
19fd0 65 6c 64 20 70 61 74 68 0a 0a 0a 64 65 66 20 70  eld path...def p
19fe0 61 74 68 5f 73 68 69 66 74 28 73 63 72 69 70 74  ath_shift(script
19ff0 5f 6e 61 6d 65 2c 20 70 61 74 68 5f 69 6e 66 6f  _name, path_info
1a000 2c 20 73 68 69 66 74 3d 31 29 3a 0a 20 20 20 20  , shift=1):.    
1a010 27 27 27 20 53 68 69 66 74 20 70 61 74 68 20 66  ''' Shift path f
1a020 72 61 67 6d 65 6e 74 73 20 66 72 6f 6d 20 50 41  ragments from PA
1a030 54 48 5f 49 4e 46 4f 20 74 6f 20 53 43 52 49 50  TH_INFO to SCRIP
1a040 54 5f 4e 41 4d 45 20 61 6e 64 20 76 69 63 65 20  T_NAME and vice 
1a050 76 65 72 73 61 2e 0a 0a 20 20 20 20 20 20 20 20  versa...        
1a060 3a 72 65 74 75 72 6e 3a 20 54 68 65 20 6d 6f 64  :return: The mod
1a070 69 66 69 65 64 20 70 61 74 68 73 2e 0a 20 20 20  ified paths..   
1a080 20 20 20 20 20 3a 70 61 72 61 6d 20 73 63 72 69       :param scri
1a090 70 74 5f 6e 61 6d 65 3a 20 54 68 65 20 53 43 52  pt_name: The SCR
1a0a0 49 50 54 5f 4e 41 4d 45 20 70 61 74 68 2e 0a 20  IPT_NAME path.. 
1a0b0 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 73 63         :param sc
1a0c0 72 69 70 74 5f 6e 61 6d 65 3a 20 54 68 65 20 50  ript_name: The P
1a0d0 41 54 48 5f 49 4e 46 4f 20 70 61 74 68 2e 0a 20  ATH_INFO path.. 
1a0e0 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 73 68         :param sh
1a0f0 69 66 74 3a 20 54 68 65 20 6e 75 6d 62 65 72 20  ift: The number 
1a100 6f 66 20 70 61 74 68 20 66 72 61 67 6d 65 6e 74  of path fragment
1a110 73 20 74 6f 20 73 68 69 66 74 2e 20 4d 61 79 20  s to shift. May 
1a120 62 65 20 6e 65 67 61 74 69 76 65 20 74 6f 0a 20  be negative to. 
1a130 20 20 20 20 20 20 20 20 20 63 68 61 6e 67 65 20           change 
1a140 74 68 65 20 73 68 69 66 74 20 64 69 72 65 63 74  the shift direct
1a150 69 6f 6e 2e 20 28 64 65 66 61 75 6c 74 3a 20 31  ion. (default: 1
1a160 29 0a 20 20 20 20 27 27 27 0a 20 20 20 20 69 66  ).    '''.    if
1a170 20 73 68 69 66 74 20 3d 3d 20 30 3a 20 72 65 74   shift == 0: ret
1a180 75 72 6e 20 73 63 72 69 70 74 5f 6e 61 6d 65 2c  urn script_name,
1a190 20 70 61 74 68 5f 69 6e 66 6f 0a 20 20 20 20 70   path_info.    p
1a1a0 61 74 68 6c 69 73 74 20 3d 20 70 61 74 68 5f 69  athlist = path_i
1a1b0 6e 66 6f 2e 73 74 72 69 70 28 27 2f 27 29 2e 73  nfo.strip('/').s
1a1c0 70 6c 69 74 28 27 2f 27 29 0a 20 20 20 20 73 63  plit('/').    sc
1a1d0 72 69 70 74 6c 69 73 74 20 3d 20 73 63 72 69 70  riptlist = scrip
1a1e0 74 5f 6e 61 6d 65 2e 73 74 72 69 70 28 27 2f 27  t_name.strip('/'
1a1f0 29 2e 73 70 6c 69 74 28 27 2f 27 29 0a 20 20 20  ).split('/').   
1a200 20 69 66 20 70 61 74 68 6c 69 73 74 20 61 6e 64   if pathlist and
1a210 20 70 61 74 68 6c 69 73 74 5b 30 5d 20 3d 3d 20   pathlist[0] == 
1a220 27 27 3a 20 70 61 74 68 6c 69 73 74 20 3d 20 5b  '': pathlist = [
1a230 5d 0a 20 20 20 20 69 66 20 73 63 72 69 70 74 6c  ].    if scriptl
1a240 69 73 74 20 61 6e 64 20 73 63 72 69 70 74 6c 69  ist and scriptli
1a250 73 74 5b 30 5d 20 3d 3d 20 27 27 3a 20 73 63 72  st[0] == '': scr
1a260 69 70 74 6c 69 73 74 20 3d 20 5b 5d 0a 20 20 20  iptlist = [].   
1a270 20 69 66 20 73 68 69 66 74 20 3e 20 30 20 61 6e   if shift > 0 an
1a280 64 20 73 68 69 66 74 20 3c 3d 20 6c 65 6e 28 70  d shift <= len(p
1a290 61 74 68 6c 69 73 74 29 3a 0a 20 20 20 20 20 20  athlist):.      
1a2a0 20 20 6d 6f 76 65 64 20 3d 20 70 61 74 68 6c 69    moved = pathli
1a2b0 73 74 5b 3a 73 68 69 66 74 5d 0a 20 20 20 20 20  st[:shift].     
1a2c0 20 20 20 73 63 72 69 70 74 6c 69 73 74 20 3d 20     scriptlist = 
1a2d0 73 63 72 69 70 74 6c 69 73 74 20 2b 20 6d 6f 76  scriptlist + mov
1a2e0 65 64 0a 20 20 20 20 20 20 20 20 70 61 74 68 6c  ed.        pathl
1a2f0 69 73 74 20 3d 20 70 61 74 68 6c 69 73 74 5b 73  ist = pathlist[s
1a300 68 69 66 74 3a 5d 0a 20 20 20 20 65 6c 69 66 20  hift:].    elif 
1a310 73 68 69 66 74 20 3c 20 30 20 61 6e 64 20 73 68  shift < 0 and sh
1a320 69 66 74 20 3e 3d 20 2d 6c 65 6e 28 73 63 72 69  ift >= -len(scri
1a330 70 74 6c 69 73 74 29 3a 0a 20 20 20 20 20 20 20  ptlist):.       
1a340 20 6d 6f 76 65 64 20 3d 20 73 63 72 69 70 74 6c   moved = scriptl
1a350 69 73 74 5b 73 68 69 66 74 3a 5d 0a 20 20 20 20  ist[shift:].    
1a360 20 20 20 20 70 61 74 68 6c 69 73 74 20 3d 20 6d      pathlist = m
1a370 6f 76 65 64 20 2b 20 70 61 74 68 6c 69 73 74 0a  oved + pathlist.
1a380 20 20 20 20 20 20 20 20 73 63 72 69 70 74 6c 69          scriptli
1a390 73 74 20 3d 20 73 63 72 69 70 74 6c 69 73 74 5b  st = scriptlist[
1a3a0 3a 73 68 69 66 74 5d 0a 20 20 20 20 65 6c 73 65  :shift].    else
1a3b0 3a 0a 20 20 20 20 20 20 20 20 65 6d 70 74 79 20  :.        empty 
1a3c0 3d 20 27 53 43 52 49 50 54 5f 4e 41 4d 45 27 20  = 'SCRIPT_NAME' 
1a3d0 69 66 20 73 68 69 66 74 20 3c 20 30 20 65 6c 73  if shift < 0 els
1a3e0 65 20 27 50 41 54 48 5f 49 4e 46 4f 27 0a 20 20  e 'PATH_INFO'.  
1a3f0 20 20 20 20 20 20 72 61 69 73 65 20 41 73 73 65        raise Asse
1a400 72 74 69 6f 6e 45 72 72 6f 72 28 22 43 61 6e 6e  rtionError("Cann
1a410 6f 74 20 73 68 69 66 74 2e 20 4e 6f 74 68 69 6e  ot shift. Nothin
1a420 67 20 6c 65 66 74 20 66 72 6f 6d 20 25 73 22 20  g left from %s" 
1a430 25 20 65 6d 70 74 79 29 0a 20 20 20 20 6e 65 77  % empty).    new
1a440 5f 73 63 72 69 70 74 5f 6e 61 6d 65 20 3d 20 27  _script_name = '
1a450 2f 27 20 2b 20 27 2f 27 2e 6a 6f 69 6e 28 73 63  /' + '/'.join(sc
1a460 72 69 70 74 6c 69 73 74 29 0a 20 20 20 20 6e 65  riptlist).    ne
1a470 77 5f 70 61 74 68 5f 69 6e 66 6f 20 3d 20 27 2f  w_path_info = '/
1a480 27 20 2b 20 27 2f 27 2e 6a 6f 69 6e 28 70 61 74  ' + '/'.join(pat
1a490 68 6c 69 73 74 29 0a 20 20 20 20 69 66 20 70 61  hlist).    if pa
1a4a0 74 68 5f 69 6e 66 6f 2e 65 6e 64 73 77 69 74 68  th_info.endswith
1a4b0 28 27 2f 27 29 20 61 6e 64 20 70 61 74 68 6c 69  ('/') and pathli
1a4c0 73 74 3a 20 6e 65 77 5f 70 61 74 68 5f 69 6e 66  st: new_path_inf
1a4d0 6f 20 2b 3d 20 27 2f 27 0a 20 20 20 20 72 65 74  o += '/'.    ret
1a4e0 75 72 6e 20 6e 65 77 5f 73 63 72 69 70 74 5f 6e  urn new_script_n
1a4f0 61 6d 65 2c 20 6e 65 77 5f 70 61 74 68 5f 69 6e  ame, new_path_in
1a500 66 6f 0a 0a 0a 64 65 66 20 61 75 74 68 5f 62 61  fo...def auth_ba
1a510 73 69 63 28 63 68 65 63 6b 2c 20 72 65 61 6c 6d  sic(check, realm
1a520 3d 22 70 72 69 76 61 74 65 22 2c 20 74 65 78 74  ="private", text
1a530 3d 22 41 63 63 65 73 73 20 64 65 6e 69 65 64 22  ="Access denied"
1a540 29 3a 0a 20 20 20 20 27 27 27 20 43 61 6c 6c 62  ):.    ''' Callb
1a550 61 63 6b 20 64 65 63 6f 72 61 74 6f 72 20 74 6f  ack decorator to
1a560 20 72 65 71 75 69 72 65 20 48 54 54 50 20 61 75   require HTTP au
1a570 74 68 20 28 62 61 73 69 63 29 2e 0a 20 20 20 20  th (basic)..    
1a580 20 20 20 20 54 4f 44 4f 3a 20 41 64 64 20 72 6f      TODO: Add ro
1a590 75 74 65 28 63 68 65 63 6b 5f 61 75 74 68 3d 2e  ute(check_auth=.
1a5a0 2e 2e 29 20 70 61 72 61 6d 65 74 65 72 2e 20 27  ..) parameter. '
1a5b0 27 27 0a 20 20 20 20 64 65 66 20 64 65 63 6f 72  ''.    def decor
1a5c0 61 74 6f 72 28 66 75 6e 63 29 3a 0a 20 20 20 20  ator(func):.    
1a5d0 20 20 20 20 64 65 66 20 77 72 61 70 70 65 72 28      def wrapper(
1a5e0 2a 61 2c 20 2a 2a 6b 61 29 3a 0a 20 20 20 20 20  *a, **ka):.     
1a5f0 20 20 20 20 20 20 20 75 73 65 72 2c 20 70 61 73         user, pas
1a600 73 77 6f 72 64 20 3d 20 72 65 71 75 65 73 74 2e  sword = request.
1a610 61 75 74 68 20 6f 72 20 28 4e 6f 6e 65 2c 20 4e  auth or (None, N
1a620 6f 6e 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  one).           
1a630 20 69 66 20 75 73 65 72 20 69 73 20 4e 6f 6e 65   if user is None
1a640 20 6f 72 20 6e 6f 74 20 63 68 65 63 6b 28 75 73   or not check(us
1a650 65 72 2c 20 70 61 73 73 77 6f 72 64 29 3a 0a 20  er, password):. 
1a660 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
1a670 72 72 20 3d 20 48 54 54 50 45 72 72 6f 72 28 34  rr = HTTPError(4
1a680 30 31 2c 20 74 65 78 74 29 0a 20 20 20 20 20 20  01, text).      
1a690 20 20 20 20 20 20 20 20 20 20 65 72 72 2e 61 64            err.ad
1a6a0 64 5f 68 65 61 64 65 72 28 27 57 57 57 2d 41 75  d_header('WWW-Au
1a6b0 74 68 65 6e 74 69 63 61 74 65 27 2c 20 27 42 61  thenticate', 'Ba
1a6c0 73 69 63 20 72 65 61 6c 6d 3d 22 25 73 22 27 20  sic realm="%s"' 
1a6d0 25 20 72 65 61 6c 6d 29 0a 20 20 20 20 20 20 20  % realm).       
1a6e0 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
1a6f0 65 72 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  err.            
1a700 72 65 74 75 72 6e 20 66 75 6e 63 28 2a 61 2c 20  return func(*a, 
1a710 2a 2a 6b 61 29 0a 20 20 20 20 20 20 20 20 72 65  **ka).        re
1a720 74 75 72 6e 20 77 72 61 70 70 65 72 0a 20 20 20  turn wrapper.   
1a730 20 72 65 74 75 72 6e 20 64 65 63 6f 72 61 74 6f   return decorato
1a740 72 0a 0a 0a 23 20 53 68 6f 72 74 63 75 74 73 20  r...# Shortcuts 
1a750 66 6f 72 20 63 6f 6d 6d 6f 6e 20 42 6f 74 74 6c  for common Bottl
1a760 65 20 6d 65 74 68 6f 64 73 2e 0a 23 20 54 68 65  e methods..# The
1a770 79 20 61 6c 6c 20 72 65 66 65 72 20 74 6f 20 74  y all refer to t
1a780 68 65 20 63 75 72 72 65 6e 74 20 64 65 66 61 75  he current defau
1a790 6c 74 20 61 70 70 6c 69 63 61 74 69 6f 6e 2e 0a  lt application..
1a7a0 0a 64 65 66 20 6d 61 6b 65 5f 64 65 66 61 75 6c  .def make_defaul
1a7b0 74 5f 61 70 70 5f 77 72 61 70 70 65 72 28 6e 61  t_app_wrapper(na
1a7c0 6d 65 29 3a 0a 20 20 20 20 27 27 27 20 52 65 74  me):.    ''' Ret
1a7d0 75 72 6e 20 61 20 63 61 6c 6c 61 62 6c 65 20 74  urn a callable t
1a7e0 68 61 74 20 72 65 6c 61 79 73 20 63 61 6c 6c 73  hat relays calls
1a7f0 20 74 6f 20 74 68 65 20 63 75 72 72 65 6e 74 20   to the current 
1a800 64 65 66 61 75 6c 74 20 61 70 70 2e 20 27 27 27  default app. '''
1a810 0a 20 20 20 20 40 66 75 6e 63 74 6f 6f 6c 73 2e  .    @functools.
1a820 77 72 61 70 73 28 67 65 74 61 74 74 72 28 42 6f  wraps(getattr(Bo
1a830 74 74 6c 65 2c 20 6e 61 6d 65 29 29 0a 20 20 20  ttle, name)).   
1a840 20 64 65 66 20 77 72 61 70 70 65 72 28 2a 61 2c   def wrapper(*a,
1a850 20 2a 2a 6b 61 29 3a 0a 20 20 20 20 20 20 20 20   **ka):.        
1a860 72 65 74 75 72 6e 20 67 65 74 61 74 74 72 28 61  return getattr(a
1a870 70 70 28 29 2c 20 6e 61 6d 65 29 28 2a 61 2c 20  pp(), name)(*a, 
1a880 2a 2a 6b 61 29 0a 20 20 20 20 72 65 74 75 72 6e  **ka).    return
1a890 20 77 72 61 70 70 65 72 0a 0a 72 6f 75 74 65 20   wrapper..route 
1a8a0 20 20 20 20 3d 20 6d 61 6b 65 5f 64 65 66 61 75      = make_defau
1a8b0 6c 74 5f 61 70 70 5f 77 72 61 70 70 65 72 28 27  lt_app_wrapper('
1a8c0 72 6f 75 74 65 27 29 0a 67 65 74 20 20 20 20 20  route').get     
1a8d0 20 20 3d 20 6d 61 6b 65 5f 64 65 66 61 75 6c 74    = make_default
1a8e0 5f 61 70 70 5f 77 72 61 70 70 65 72 28 27 67 65  _app_wrapper('ge
1a8f0 74 27 29 0a 70 6f 73 74 20 20 20 20 20 20 3d 20  t').post      = 
1a900 6d 61 6b 65 5f 64 65 66 61 75 6c 74 5f 61 70 70  make_default_app
1a910 5f 77 72 61 70 70 65 72 28 27 70 6f 73 74 27 29  _wrapper('post')
1a920 0a 70 75 74 20 20 20 20 20 20 20 3d 20 6d 61 6b  .put       = mak
1a930 65 5f 64 65 66 61 75 6c 74 5f 61 70 70 5f 77 72  e_default_app_wr
1a940 61 70 70 65 72 28 27 70 75 74 27 29 0a 64 65 6c  apper('put').del
1a950 65 74 65 20 20 20 20 3d 20 6d 61 6b 65 5f 64 65  ete    = make_de
1a960 66 61 75 6c 74 5f 61 70 70 5f 77 72 61 70 70 65  fault_app_wrappe
1a970 72 28 27 64 65 6c 65 74 65 27 29 0a 65 72 72 6f  r('delete').erro
1a980 72 20 20 20 20 20 3d 20 6d 61 6b 65 5f 64 65 66  r     = make_def
1a990 61 75 6c 74 5f 61 70 70 5f 77 72 61 70 70 65 72  ault_app_wrapper
1a9a0 28 27 65 72 72 6f 72 27 29 0a 6d 6f 75 6e 74 20  ('error').mount 
1a9b0 20 20 20 20 3d 20 6d 61 6b 65 5f 64 65 66 61 75      = make_defau
1a9c0 6c 74 5f 61 70 70 5f 77 72 61 70 70 65 72 28 27  lt_app_wrapper('
1a9d0 6d 6f 75 6e 74 27 29 0a 68 6f 6f 6b 20 20 20 20  mount').hook    
1a9e0 20 20 3d 20 6d 61 6b 65 5f 64 65 66 61 75 6c 74    = make_default
1a9f0 5f 61 70 70 5f 77 72 61 70 70 65 72 28 27 68 6f  _app_wrapper('ho
1aa00 6f 6b 27 29 0a 69 6e 73 74 61 6c 6c 20 20 20 3d  ok').install   =
1aa10 20 6d 61 6b 65 5f 64 65 66 61 75 6c 74 5f 61 70   make_default_ap
1aa20 70 5f 77 72 61 70 70 65 72 28 27 69 6e 73 74 61  p_wrapper('insta
1aa30 6c 6c 27 29 0a 75 6e 69 6e 73 74 61 6c 6c 20 3d  ll').uninstall =
1aa40 20 6d 61 6b 65 5f 64 65 66 61 75 6c 74 5f 61 70   make_default_ap
1aa50 70 5f 77 72 61 70 70 65 72 28 27 75 6e 69 6e 73  p_wrapper('unins
1aa60 74 61 6c 6c 27 29 0a 75 72 6c 20 20 20 20 20 20  tall').url      
1aa70 20 3d 20 6d 61 6b 65 5f 64 65 66 61 75 6c 74 5f   = make_default_
1aa80 61 70 70 5f 77 72 61 70 70 65 72 28 27 67 65 74  app_wrapper('get
1aa90 5f 75 72 6c 27 29 0a 0a 0a 0a 0a 0a 0a 0a 23 23  _url')........##
1aaa0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1aab0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1aac0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1aad0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1aae0 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 23 20  #############.# 
1aaf0 53 65 72 76 65 72 20 41 64 61 70 74 65 72 20 23  Server Adapter #
1ab00 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab10 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab20 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab30 23 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 23  ##############.#
1ab40 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab50 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab60 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab70 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ab80 23 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 0a  ##############..
1ab90 0a 63 6c 61 73 73 20 53 65 72 76 65 72 41 64 61  .class ServerAda
1aba0 70 74 65 72 28 6f 62 6a 65 63 74 29 3a 0a 20 20  pter(object):.  
1abb0 20 20 71 75 69 65 74 20 3d 20 46 61 6c 73 65 0a    quiet = False.
1abc0 20 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f      def __init__
1abd0 28 73 65 6c 66 2c 20 68 6f 73 74 3d 27 31 32 37  (self, host='127
1abe0 2e 30 2e 30 2e 31 27 2c 20 70 6f 72 74 3d 38 30  .0.0.1', port=80
1abf0 38 30 2c 20 2a 2a 6f 70 74 69 6f 6e 73 29 3a 0a  80, **options):.
1ac00 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6f 70 74          self.opt
1ac10 69 6f 6e 73 20 3d 20 6f 70 74 69 6f 6e 73 0a 20  ions = options. 
1ac20 20 20 20 20 20 20 20 73 65 6c 66 2e 68 6f 73 74         self.host
1ac30 20 3d 20 68 6f 73 74 0a 20 20 20 20 20 20 20 20   = host.        
1ac40 73 65 6c 66 2e 70 6f 72 74 20 3d 20 69 6e 74 28  self.port = int(
1ac50 70 6f 72 74 29 0a 0a 20 20 20 20 64 65 66 20 72  port)..    def r
1ac60 75 6e 28 73 65 6c 66 2c 20 68 61 6e 64 6c 65 72  un(self, handler
1ac70 29 3a 20 23 20 70 72 61 67 6d 61 3a 20 6e 6f 20  ): # pragma: no 
1ac80 63 6f 76 65 72 0a 20 20 20 20 20 20 20 20 70 61  cover.        pa
1ac90 73 73 0a 0a 20 20 20 20 64 65 66 20 5f 5f 72 65  ss..    def __re
1aca0 70 72 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20 20  pr__(self):.    
1acb0 20 20 20 20 61 72 67 73 20 3d 20 27 2c 20 27 2e      args = ', '.
1acc0 6a 6f 69 6e 28 5b 27 25 73 3d 25 73 27 25 28 6b  join(['%s=%s'%(k
1acd0 2c 72 65 70 72 28 76 29 29 20 66 6f 72 20 6b 2c  ,repr(v)) for k,
1ace0 20 76 20 69 6e 20 73 65 6c 66 2e 6f 70 74 69 6f   v in self.optio
1acf0 6e 73 2e 69 74 65 6d 73 28 29 5d 29 0a 20 20 20  ns.items()]).   
1ad00 20 20 20 20 20 72 65 74 75 72 6e 20 22 25 73 28       return "%s(
1ad10 25 73 29 22 20 25 20 28 73 65 6c 66 2e 5f 5f 63  %s)" % (self.__c
1ad20 6c 61 73 73 5f 5f 2e 5f 5f 6e 61 6d 65 5f 5f 2c  lass__.__name__,
1ad30 20 61 72 67 73 29 0a 0a 0a 63 6c 61 73 73 20 43   args)...class C
1ad40 47 49 53 65 72 76 65 72 28 53 65 72 76 65 72 41  GIServer(ServerA
1ad50 64 61 70 74 65 72 29 3a 0a 20 20 20 20 71 75 69  dapter):.    qui
1ad60 65 74 20 3d 20 54 72 75 65 0a 20 20 20 20 64 65  et = True.    de
1ad70 66 20 72 75 6e 28 73 65 6c 66 2c 20 68 61 6e 64  f run(self, hand
1ad80 6c 65 72 29 3a 20 23 20 70 72 61 67 6d 61 3a 20  ler): # pragma: 
1ad90 6e 6f 20 63 6f 76 65 72 0a 20 20 20 20 20 20 20  no cover.       
1ada0 20 66 72 6f 6d 20 77 73 67 69 72 65 66 2e 68 61   from wsgiref.ha
1adb0 6e 64 6c 65 72 73 20 69 6d 70 6f 72 74 20 43 47  ndlers import CG
1adc0 49 48 61 6e 64 6c 65 72 0a 20 20 20 20 20 20 20  IHandler.       
1add0 20 64 65 66 20 66 69 78 65 64 5f 65 6e 76 69 72   def fixed_envir
1ade0 6f 6e 28 65 6e 76 69 72 6f 6e 2c 20 73 74 61 72  on(environ, star
1adf0 74 5f 72 65 73 70 6f 6e 73 65 29 3a 0a 20 20 20  t_response):.   
1ae00 20 20 20 20 20 20 20 20 20 65 6e 76 69 72 6f 6e           environ
1ae10 2e 73 65 74 64 65 66 61 75 6c 74 28 27 50 41 54  .setdefault('PAT
1ae20 48 5f 49 4e 46 4f 27 2c 20 27 27 29 0a 20 20 20  H_INFO', '').   
1ae30 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
1ae40 68 61 6e 64 6c 65 72 28 65 6e 76 69 72 6f 6e 2c  handler(environ,
1ae50 20 73 74 61 72 74 5f 72 65 73 70 6f 6e 73 65 29   start_response)
1ae60 0a 20 20 20 20 20 20 20 20 43 47 49 48 61 6e 64  .        CGIHand
1ae70 6c 65 72 28 29 2e 72 75 6e 28 66 69 78 65 64 5f  ler().run(fixed_
1ae80 65 6e 76 69 72 6f 6e 29 0a 0a 0a 63 6c 61 73 73  environ)...class
1ae90 20 46 6c 75 70 46 43 47 49 53 65 72 76 65 72 28   FlupFCGIServer(
1aea0 53 65 72 76 65 72 41 64 61 70 74 65 72 29 3a 0a  ServerAdapter):.
1aeb0 20 20 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66      def run(self
1aec0 2c 20 68 61 6e 64 6c 65 72 29 3a 20 23 20 70 72  , handler): # pr
1aed0 61 67 6d 61 3a 20 6e 6f 20 63 6f 76 65 72 0a 20  agma: no cover. 
1aee0 20 20 20 20 20 20 20 69 6d 70 6f 72 74 20 66 6c         import fl
1aef0 75 70 2e 73 65 72 76 65 72 2e 66 63 67 69 0a 20  up.server.fcgi. 
1af00 20 20 20 20 20 20 20 73 65 6c 66 2e 6f 70 74 69         self.opti
1af10 6f 6e 73 2e 73 65 74 64 65 66 61 75 6c 74 28 27  ons.setdefault('
1af20 62 69 6e 64 41 64 64 72 65 73 73 27 2c 20 28 73  bindAddress', (s
1af30 65 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66 2e 70  elf.host, self.p
1af40 6f 72 74 29 29 0a 20 20 20 20 20 20 20 20 66 6c  ort)).        fl
1af50 75 70 2e 73 65 72 76 65 72 2e 66 63 67 69 2e 57  up.server.fcgi.W
1af60 53 47 49 53 65 72 76 65 72 28 68 61 6e 64 6c 65  SGIServer(handle
1af70 72 2c 20 2a 2a 73 65 6c 66 2e 6f 70 74 69 6f 6e  r, **self.option
1af80 73 29 2e 72 75 6e 28 29 0a 0a 0a 63 6c 61 73 73  s).run()...class
1af90 20 57 53 47 49 52 65 66 53 65 72 76 65 72 28 53   WSGIRefServer(S
1afa0 65 72 76 65 72 41 64 61 70 74 65 72 29 3a 0a 20  erverAdapter):. 
1afb0 20 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c     def run(self,
1afc0 20 61 70 70 29 3a 20 23 20 70 72 61 67 6d 61 3a   app): # pragma:
1afd0 20 6e 6f 20 63 6f 76 65 72 0a 20 20 20 20 20 20   no cover.      
1afe0 20 20 66 72 6f 6d 20 77 73 67 69 72 65 66 2e 73    from wsgiref.s
1aff0 69 6d 70 6c 65 5f 73 65 72 76 65 72 20 69 6d 70  imple_server imp
1b000 6f 72 74 20 57 53 47 49 52 65 71 75 65 73 74 48  ort WSGIRequestH
1b010 61 6e 64 6c 65 72 2c 20 57 53 47 49 53 65 72 76  andler, WSGIServ
1b020 65 72 0a 20 20 20 20 20 20 20 20 66 72 6f 6d 20  er.        from 
1b030 77 73 67 69 72 65 66 2e 73 69 6d 70 6c 65 5f 73  wsgiref.simple_s
1b040 65 72 76 65 72 20 69 6d 70 6f 72 74 20 6d 61 6b  erver import mak
1b050 65 5f 73 65 72 76 65 72 0a 20 20 20 20 20 20 20  e_server.       
1b060 20 69 6d 70 6f 72 74 20 73 6f 63 6b 65 74 0a 0a   import socket..
1b070 20 20 20 20 20 20 20 20 63 6c 61 73 73 20 46 69          class Fi
1b080 78 65 64 48 61 6e 64 6c 65 72 28 57 53 47 49 52  xedHandler(WSGIR
1b090 65 71 75 65 73 74 48 61 6e 64 6c 65 72 29 3a 0a  equestHandler):.
1b0a0 20 20 20 20 20 20 20 20 20 20 20 20 64 65 66 20              def 
1b0b0 61 64 64 72 65 73 73 5f 73 74 72 69 6e 67 28 73  address_string(s
1b0c0 65 6c 66 29 3a 20 23 20 50 72 65 76 65 6e 74 20  elf): # Prevent 
1b0d0 72 65 76 65 72 73 65 20 44 4e 53 20 6c 6f 6f 6b  reverse DNS look
1b0e0 75 70 73 20 70 6c 65 61 73 65 2e 0a 20 20 20 20  ups please..    
1b0f0 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
1b100 72 6e 20 73 65 6c 66 2e 63 6c 69 65 6e 74 5f 61  rn self.client_a
1b110 64 64 72 65 73 73 5b 30 5d 0a 20 20 20 20 20 20  ddress[0].      
1b120 20 20 20 20 20 20 64 65 66 20 6c 6f 67 5f 72 65        def log_re
1b130 71 75 65 73 74 28 2a 61 72 67 73 2c 20 2a 2a 6b  quest(*args, **k
1b140 77 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  w):.            
1b150 20 20 20 20 69 66 20 6e 6f 74 20 73 65 6c 66 2e      if not self.
1b160 71 75 69 65 74 3a 0a 20 20 20 20 20 20 20 20 20  quiet:.         
1b170 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
1b180 6e 20 57 53 47 49 52 65 71 75 65 73 74 48 61 6e  n WSGIRequestHan
1b190 64 6c 65 72 2e 6c 6f 67 5f 72 65 71 75 65 73 74  dler.log_request
1b1a0 28 2a 61 72 67 73 2c 20 2a 2a 6b 77 29 0a 0a 20  (*args, **kw).. 
1b1b0 20 20 20 20 20 20 20 68 61 6e 64 6c 65 72 5f 63         handler_c
1b1c0 6c 73 20 3d 20 73 65 6c 66 2e 6f 70 74 69 6f 6e  ls = self.option
1b1d0 73 2e 67 65 74 28 27 68 61 6e 64 6c 65 72 5f 63  s.get('handler_c
1b1e0 6c 61 73 73 27 2c 20 46 69 78 65 64 48 61 6e 64  lass', FixedHand
1b1f0 6c 65 72 29 0a 20 20 20 20 20 20 20 20 73 65 72  ler).        ser
1b200 76 65 72 5f 63 6c 73 20 20 3d 20 73 65 6c 66 2e  ver_cls  = self.
1b210 6f 70 74 69 6f 6e 73 2e 67 65 74 28 27 73 65 72  options.get('ser
1b220 76 65 72 5f 63 6c 61 73 73 27 2c 20 57 53 47 49  ver_class', WSGI
1b230 53 65 72 76 65 72 29 0a 0a 20 20 20 20 20 20 20  Server)..       
1b240 20 69 66 20 27 3a 27 20 69 6e 20 73 65 6c 66 2e   if ':' in self.
1b250 68 6f 73 74 3a 20 23 20 46 69 78 20 77 73 67 69  host: # Fix wsgi
1b260 72 65 66 20 66 6f 72 20 49 50 76 36 20 61 64 64  ref for IPv6 add
1b270 72 65 73 73 65 73 2e 0a 20 20 20 20 20 20 20 20  resses..        
1b280 20 20 20 20 69 66 20 67 65 74 61 74 74 72 28 73      if getattr(s
1b290 65 72 76 65 72 5f 63 6c 73 2c 20 27 61 64 64 72  erver_cls, 'addr
1b2a0 65 73 73 5f 66 61 6d 69 6c 79 27 29 20 3d 3d 20  ess_family') == 
1b2b0 73 6f 63 6b 65 74 2e 41 46 5f 49 4e 45 54 3a 0a  socket.AF_INET:.
1b2c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b2d0 63 6c 61 73 73 20 73 65 72 76 65 72 5f 63 6c 73  class server_cls
1b2e0 28 73 65 72 76 65 72 5f 63 6c 73 29 3a 0a 20 20  (server_cls):.  
1b2f0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b300 20 20 61 64 64 72 65 73 73 5f 66 61 6d 69 6c 79    address_family
1b310 20 3d 20 73 6f 63 6b 65 74 2e 41 46 5f 49 4e 45   = socket.AF_INE
1b320 54 36 0a 0a 20 20 20 20 20 20 20 20 73 72 76 20  T6..        srv 
1b330 3d 20 6d 61 6b 65 5f 73 65 72 76 65 72 28 73 65  = make_server(se
1b340 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66 2e 70 6f  lf.host, self.po
1b350 72 74 2c 20 61 70 70 2c 20 73 65 72 76 65 72 5f  rt, app, server_
1b360 63 6c 73 2c 20 68 61 6e 64 6c 65 72 5f 63 6c 73  cls, handler_cls
1b370 29 0a 20 20 20 20 20 20 20 20 73 72 76 2e 73 65  ).        srv.se
1b380 72 76 65 5f 66 6f 72 65 76 65 72 28 29 0a 0a 0a  rve_forever()...
1b390 63 6c 61 73 73 20 43 68 65 72 72 79 50 79 53 65  class CherryPySe
1b3a0 72 76 65 72 28 53 65 72 76 65 72 41 64 61 70 74  rver(ServerAdapt
1b3b0 65 72 29 3a 0a 20 20 20 20 64 65 66 20 72 75 6e  er):.    def run
1b3c0 28 73 65 6c 66 2c 20 68 61 6e 64 6c 65 72 29 3a  (self, handler):
1b3d0 20 23 20 70 72 61 67 6d 61 3a 20 6e 6f 20 63 6f   # pragma: no co
1b3e0 76 65 72 0a 20 20 20 20 20 20 20 20 66 72 6f 6d  ver.        from
1b3f0 20 63 68 65 72 72 79 70 79 20 69 6d 70 6f 72 74   cherrypy import
1b400 20 77 73 67 69 73 65 72 76 65 72 0a 20 20 20 20   wsgiserver.    
1b410 20 20 20 20 73 65 6c 66 2e 6f 70 74 69 6f 6e 73      self.options
1b420 5b 27 62 69 6e 64 5f 61 64 64 72 27 5d 20 3d 20  ['bind_addr'] = 
1b430 28 73 65 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66  (self.host, self
1b440 2e 70 6f 72 74 29 0a 20 20 20 20 20 20 20 20 73  .port).        s
1b450 65 6c 66 2e 6f 70 74 69 6f 6e 73 5b 27 77 73 67  elf.options['wsg
1b460 69 5f 61 70 70 27 5d 20 3d 20 68 61 6e 64 6c 65  i_app'] = handle
1b470 72 0a 0a 20 20 20 20 20 20 20 20 63 65 72 74 66  r..        certf
1b480 69 6c 65 20 3d 20 73 65 6c 66 2e 6f 70 74 69 6f  ile = self.optio
1b490 6e 73 2e 67 65 74 28 27 63 65 72 74 66 69 6c 65  ns.get('certfile
1b4a0 27 29 0a 20 20 20 20 20 20 20 20 69 66 20 63 65  ').        if ce
1b4b0 72 74 66 69 6c 65 3a 0a 20 20 20 20 20 20 20 20  rtfile:.        
1b4c0 20 20 20 20 64 65 6c 20 73 65 6c 66 2e 6f 70 74      del self.opt
1b4d0 69 6f 6e 73 5b 27 63 65 72 74 66 69 6c 65 27 5d  ions['certfile']
1b4e0 0a 20 20 20 20 20 20 20 20 6b 65 79 66 69 6c 65  .        keyfile
1b4f0 20 3d 20 73 65 6c 66 2e 6f 70 74 69 6f 6e 73 2e   = self.options.
1b500 67 65 74 28 27 6b 65 79 66 69 6c 65 27 29 0a 20  get('keyfile'). 
1b510 20 20 20 20 20 20 20 69 66 20 6b 65 79 66 69 6c         if keyfil
1b520 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  e:.            d
1b530 65 6c 20 73 65 6c 66 2e 6f 70 74 69 6f 6e 73 5b  el self.options[
1b540 27 6b 65 79 66 69 6c 65 27 5d 0a 0a 20 20 20 20  'keyfile']..    
1b550 20 20 20 20 73 65 72 76 65 72 20 3d 20 77 73 67      server = wsg
1b560 69 73 65 72 76 65 72 2e 43 68 65 72 72 79 50 79  iserver.CherryPy
1b570 57 53 47 49 53 65 72 76 65 72 28 2a 2a 73 65 6c  WSGIServer(**sel
1b580 66 2e 6f 70 74 69 6f 6e 73 29 0a 20 20 20 20 20  f.options).     
1b590 20 20 20 69 66 20 63 65 72 74 66 69 6c 65 3a 0a     if certfile:.
1b5a0 20 20 20 20 20 20 20 20 20 20 20 20 73 65 72 76              serv
1b5b0 65 72 2e 73 73 6c 5f 63 65 72 74 69 66 69 63 61  er.ssl_certifica
1b5c0 74 65 20 3d 20 63 65 72 74 66 69 6c 65 0a 20 20  te = certfile.  
1b5d0 20 20 20 20 20 20 69 66 20 6b 65 79 66 69 6c 65        if keyfile
1b5e0 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65  :.            se
1b5f0 72 76 65 72 2e 73 73 6c 5f 70 72 69 76 61 74 65  rver.ssl_private
1b600 5f 6b 65 79 20 3d 20 6b 65 79 66 69 6c 65 0a 0a  _key = keyfile..
1b610 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20          try:.   
1b620 20 20 20 20 20 20 20 20 20 73 65 72 76 65 72 2e           server.
1b630 73 74 61 72 74 28 29 0a 20 20 20 20 20 20 20 20  start().        
1b640 66 69 6e 61 6c 6c 79 3a 0a 20 20 20 20 20 20 20  finally:.       
1b650 20 20 20 20 20 73 65 72 76 65 72 2e 73 74 6f 70       server.stop
1b660 28 29 0a 0a 0a 63 6c 61 73 73 20 57 61 69 74 72  ()...class Waitr
1b670 65 73 73 53 65 72 76 65 72 28 53 65 72 76 65 72  essServer(Server
1b680 41 64 61 70 74 65 72 29 3a 0a 20 20 20 20 64 65  Adapter):.    de
1b690 66 20 72 75 6e 28 73 65 6c 66 2c 20 68 61 6e 64  f run(self, hand
1b6a0 6c 65 72 29 3a 0a 20 20 20 20 20 20 20 20 66 72  ler):.        fr
1b6b0 6f 6d 20 77 61 69 74 72 65 73 73 20 69 6d 70 6f  om waitress impo
1b6c0 72 74 20 73 65 72 76 65 0a 20 20 20 20 20 20 20  rt serve.       
1b6d0 20 73 65 72 76 65 28 68 61 6e 64 6c 65 72 2c 20   serve(handler, 
1b6e0 68 6f 73 74 3d 73 65 6c 66 2e 68 6f 73 74 2c 20  host=self.host, 
1b6f0 70 6f 72 74 3d 73 65 6c 66 2e 70 6f 72 74 29 0a  port=self.port).
1b700 0a 0a 63 6c 61 73 73 20 50 61 73 74 65 53 65 72  ..class PasteSer
1b710 76 65 72 28 53 65 72 76 65 72 41 64 61 70 74 65  ver(ServerAdapte
1b720 72 29 3a 0a 20 20 20 20 64 65 66 20 72 75 6e 28  r):.    def run(
1b730 73 65 6c 66 2c 20 68 61 6e 64 6c 65 72 29 3a 20  self, handler): 
1b740 23 20 70 72 61 67 6d 61 3a 20 6e 6f 20 63 6f 76  # pragma: no cov
1b750 65 72 0a 20 20 20 20 20 20 20 20 66 72 6f 6d 20  er.        from 
1b760 70 61 73 74 65 20 69 6d 70 6f 72 74 20 68 74 74  paste import htt
1b770 70 73 65 72 76 65 72 0a 20 20 20 20 20 20 20 20  pserver.        
1b780 66 72 6f 6d 20 70 61 73 74 65 2e 74 72 61 6e 73  from paste.trans
1b790 6c 6f 67 67 65 72 20 69 6d 70 6f 72 74 20 54 72  logger import Tr
1b7a0 61 6e 73 4c 6f 67 67 65 72 0a 20 20 20 20 20 20  ansLogger.      
1b7b0 20 20 68 61 6e 64 6c 65 72 20 3d 20 54 72 61 6e    handler = Tran
1b7c0 73 4c 6f 67 67 65 72 28 68 61 6e 64 6c 65 72 2c  sLogger(handler,
1b7d0 20 73 65 74 75 70 5f 63 6f 6e 73 6f 6c 65 5f 68   setup_console_h
1b7e0 61 6e 64 6c 65 72 3d 28 6e 6f 74 20 73 65 6c 66  andler=(not self
1b7f0 2e 71 75 69 65 74 29 29 0a 20 20 20 20 20 20 20  .quiet)).       
1b800 20 68 74 74 70 73 65 72 76 65 72 2e 73 65 72 76   httpserver.serv
1b810 65 28 68 61 6e 64 6c 65 72 2c 20 68 6f 73 74 3d  e(handler, host=
1b820 73 65 6c 66 2e 68 6f 73 74 2c 20 70 6f 72 74 3d  self.host, port=
1b830 73 74 72 28 73 65 6c 66 2e 70 6f 72 74 29 2c 0a  str(self.port),.
1b840 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b850 20 20 20 20 20 20 20 20 20 2a 2a 73 65 6c 66 2e           **self.
1b860 6f 70 74 69 6f 6e 73 29 0a 0a 0a 63 6c 61 73 73  options)...class
1b870 20 4d 65 69 6e 68 65 6c 64 53 65 72 76 65 72 28   MeinheldServer(
1b880 53 65 72 76 65 72 41 64 61 70 74 65 72 29 3a 0a  ServerAdapter):.
1b890 20 20 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66      def run(self
1b8a0 2c 20 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20  , handler):.    
1b8b0 20 20 20 20 66 72 6f 6d 20 6d 65 69 6e 68 65 6c      from meinhel
1b8c0 64 20 69 6d 70 6f 72 74 20 73 65 72 76 65 72 0a  d import server.
1b8d0 20 20 20 20 20 20 20 20 73 65 72 76 65 72 2e 6c          server.l
1b8e0 69 73 74 65 6e 28 28 73 65 6c 66 2e 68 6f 73 74  isten((self.host
1b8f0 2c 20 73 65 6c 66 2e 70 6f 72 74 29 29 0a 20 20  , self.port)).  
1b900 20 20 20 20 20 20 73 65 72 76 65 72 2e 72 75 6e        server.run
1b910 28 68 61 6e 64 6c 65 72 29 0a 0a 0a 63 6c 61 73  (handler)...clas
1b920 73 20 46 61 70 77 73 53 65 72 76 65 72 28 53 65  s FapwsServer(Se
1b930 72 76 65 72 41 64 61 70 74 65 72 29 3a 0a 20 20  rverAdapter):.  
1b940 20 20 22 22 22 20 45 78 74 72 65 6d 65 6c 79 20    """ Extremely 
1b950 66 61 73 74 20 77 65 62 73 65 72 76 65 72 20 75  fast webserver u
1b960 73 69 6e 67 20 6c 69 62 65 76 2e 20 53 65 65 20  sing libev. See 
1b970 68 74 74 70 3a 2f 2f 77 77 77 2e 66 61 70 77 73  http://www.fapws
1b980 2e 6f 72 67 2f 20 22 22 22 0a 20 20 20 20 64 65  .org/ """.    de
1b990 66 20 72 75 6e 28 73 65 6c 66 2c 20 68 61 6e 64  f run(self, hand
1b9a0 6c 65 72 29 3a 20 23 20 70 72 61 67 6d 61 3a 20  ler): # pragma: 
1b9b0 6e 6f 20 63 6f 76 65 72 0a 20 20 20 20 20 20 20  no cover.       
1b9c0 20 69 6d 70 6f 72 74 20 66 61 70 77 73 2e 5f 65   import fapws._e
1b9d0 76 77 73 67 69 20 61 73 20 65 76 77 73 67 69 0a  vwsgi as evwsgi.
1b9e0 20 20 20 20 20 20 20 20 66 72 6f 6d 20 66 61 70          from fap
1b9f0 77 73 20 69 6d 70 6f 72 74 20 62 61 73 65 2c 20  ws import base, 
1ba00 63 6f 6e 66 69 67 0a 20 20 20 20 20 20 20 20 70  config.        p
1ba10 6f 72 74 20 3d 20 73 65 6c 66 2e 70 6f 72 74 0a  ort = self.port.
1ba20 20 20 20 20 20 20 20 20 69 66 20 66 6c 6f 61 74          if float
1ba30 28 63 6f 6e 66 69 67 2e 53 45 52 56 45 52 5f 49  (config.SERVER_I
1ba40 44 45 4e 54 5b 2d 32 3a 5d 29 20 3e 20 30 2e 34  DENT[-2:]) > 0.4
1ba50 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20  :.            # 
1ba60 66 61 70 77 73 33 20 73 69 6c 65 6e 74 6c 79 20  fapws3 silently 
1ba70 63 68 61 6e 67 65 64 20 69 74 73 20 41 50 49 20  changed its API 
1ba80 69 6e 20 30 2e 35 0a 20 20 20 20 20 20 20 20 20  in 0.5.         
1ba90 20 20 20 70 6f 72 74 20 3d 20 73 74 72 28 70 6f     port = str(po
1baa0 72 74 29 0a 20 20 20 20 20 20 20 20 65 76 77 73  rt).        evws
1bab0 67 69 2e 73 74 61 72 74 28 73 65 6c 66 2e 68 6f  gi.start(self.ho
1bac0 73 74 2c 20 70 6f 72 74 29 0a 20 20 20 20 20 20  st, port).      
1bad0 20 20 23 20 66 61 70 77 73 33 20 6e 65 76 65 72    # fapws3 never
1bae0 20 72 65 6c 65 61 73 65 73 20 74 68 65 20 47 49   releases the GI
1baf0 4c 2e 20 43 6f 6d 70 6c 61 69 6e 20 75 70 73 74  L. Complain upst
1bb00 72 65 61 6d 2e 20 49 20 74 72 69 65 64 2e 20 4e  ream. I tried. N
1bb10 6f 20 6c 75 63 6b 2e 0a 20 20 20 20 20 20 20 20  o luck..        
1bb20 69 66 20 27 42 4f 54 54 4c 45 5f 43 48 49 4c 44  if 'BOTTLE_CHILD
1bb30 27 20 69 6e 20 6f 73 2e 65 6e 76 69 72 6f 6e 20  ' in os.environ 
1bb40 61 6e 64 20 6e 6f 74 20 73 65 6c 66 2e 71 75 69  and not self.qui
1bb50 65 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  et:.            
1bb60 5f 73 74 64 65 72 72 28 22 57 41 52 4e 49 4e 47  _stderr("WARNING
1bb70 3a 20 41 75 74 6f 2d 72 65 6c 6f 61 64 69 6e 67  : Auto-reloading
1bb80 20 64 6f 65 73 20 6e 6f 74 20 77 6f 72 6b 20 77   does not work w
1bb90 69 74 68 20 46 61 70 77 73 33 2e 5c 6e 22 29 0a  ith Fapws3.\n").
1bba0 20 20 20 20 20 20 20 20 20 20 20 20 5f 73 74 64              _std
1bbb0 65 72 72 28 22 20 20 20 20 20 20 20 20 20 28 46  err("         (F
1bbc0 61 70 77 73 33 20 62 72 65 61 6b 73 20 70 79 74  apws3 breaks pyt
1bbd0 68 6f 6e 20 74 68 72 65 61 64 20 73 75 70 70 6f  hon thread suppo
1bbe0 72 74 29 5c 6e 22 29 0a 20 20 20 20 20 20 20 20  rt)\n").        
1bbf0 65 76 77 73 67 69 2e 73 65 74 5f 62 61 73 65 5f  evwsgi.set_base_
1bc00 6d 6f 64 75 6c 65 28 62 61 73 65 29 0a 20 20 20  module(base).   
1bc10 20 20 20 20 20 64 65 66 20 61 70 70 28 65 6e 76       def app(env
1bc20 69 72 6f 6e 2c 20 73 74 61 72 74 5f 72 65 73 70  iron, start_resp
1bc30 6f 6e 73 65 29 3a 0a 20 20 20 20 20 20 20 20 20  onse):.         
1bc40 20 20 20 65 6e 76 69 72 6f 6e 5b 27 77 73 67 69     environ['wsgi
1bc50 2e 6d 75 6c 74 69 70 72 6f 63 65 73 73 27 5d 20  .multiprocess'] 
1bc60 3d 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20  = False.        
1bc70 20 20 20 20 72 65 74 75 72 6e 20 68 61 6e 64 6c      return handl
1bc80 65 72 28 65 6e 76 69 72 6f 6e 2c 20 73 74 61 72  er(environ, star
1bc90 74 5f 72 65 73 70 6f 6e 73 65 29 0a 20 20 20 20  t_response).    
1bca0 20 20 20 20 65 76 77 73 67 69 2e 77 73 67 69 5f      evwsgi.wsgi_
1bcb0 63 62 28 28 27 27 2c 20 61 70 70 29 29 0a 20 20  cb(('', app)).  
1bcc0 20 20 20 20 20 20 65 76 77 73 67 69 2e 72 75 6e        evwsgi.run
1bcd0 28 29 0a 0a 0a 63 6c 61 73 73 20 54 6f 72 6e 61  ()...class Torna
1bce0 64 6f 53 65 72 76 65 72 28 53 65 72 76 65 72 41  doServer(ServerA
1bcf0 64 61 70 74 65 72 29 3a 0a 20 20 20 20 22 22 22  dapter):.    """
1bd00 20 54 68 65 20 73 75 70 65 72 20 68 79 70 65 64   The super hyped
1bd10 20 61 73 79 6e 63 68 72 6f 6e 6f 75 73 20 73 65   asynchronous se
1bd20 72 76 65 72 20 62 79 20 66 61 63 65 62 6f 6f 6b  rver by facebook
1bd30 2e 20 55 6e 74 65 73 74 65 64 2e 20 22 22 22 0a  . Untested. """.
1bd40 20 20 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66      def run(self
1bd50 2c 20 68 61 6e 64 6c 65 72 29 3a 20 23 20 70 72  , handler): # pr
1bd60 61 67 6d 61 3a 20 6e 6f 20 63 6f 76 65 72 0a 20  agma: no cover. 
1bd70 20 20 20 20 20 20 20 69 6d 70 6f 72 74 20 74 6f         import to
1bd80 72 6e 61 64 6f 2e 77 73 67 69 2c 20 74 6f 72 6e  rnado.wsgi, torn
1bd90 61 64 6f 2e 68 74 74 70 73 65 72 76 65 72 2c 20  ado.httpserver, 
1bda0 74 6f 72 6e 61 64 6f 2e 69 6f 6c 6f 6f 70 0a 20  tornado.ioloop. 
1bdb0 20 20 20 20 20 20 20 63 6f 6e 74 61 69 6e 65 72         container
1bdc0 20 3d 20 74 6f 72 6e 61 64 6f 2e 77 73 67 69 2e   = tornado.wsgi.
1bdd0 57 53 47 49 43 6f 6e 74 61 69 6e 65 72 28 68 61  WSGIContainer(ha
1bde0 6e 64 6c 65 72 29 0a 20 20 20 20 20 20 20 20 73  ndler).        s
1bdf0 65 72 76 65 72 20 3d 20 74 6f 72 6e 61 64 6f 2e  erver = tornado.
1be00 68 74 74 70 73 65 72 76 65 72 2e 48 54 54 50 53  httpserver.HTTPS
1be10 65 72 76 65 72 28 63 6f 6e 74 61 69 6e 65 72 29  erver(container)
1be20 0a 20 20 20 20 20 20 20 20 73 65 72 76 65 72 2e  .        server.
1be30 6c 69 73 74 65 6e 28 70 6f 72 74 3d 73 65 6c 66  listen(port=self
1be40 2e 70 6f 72 74 2c 61 64 64 72 65 73 73 3d 73 65  .port,address=se
1be50 6c 66 2e 68 6f 73 74 29 0a 20 20 20 20 20 20 20  lf.host).       
1be60 20 74 6f 72 6e 61 64 6f 2e 69 6f 6c 6f 6f 70 2e   tornado.ioloop.
1be70 49 4f 4c 6f 6f 70 2e 69 6e 73 74 61 6e 63 65 28  IOLoop.instance(
1be80 29 2e 73 74 61 72 74 28 29 0a 0a 0a 63 6c 61 73  ).start()...clas
1be90 73 20 41 70 70 45 6e 67 69 6e 65 53 65 72 76 65  s AppEngineServe
1bea0 72 28 53 65 72 76 65 72 41 64 61 70 74 65 72 29  r(ServerAdapter)
1beb0 3a 0a 20 20 20 20 22 22 22 20 41 64 61 70 74 65  :.    """ Adapte
1bec0 72 20 66 6f 72 20 47 6f 6f 67 6c 65 20 41 70 70  r for Google App
1bed0 20 45 6e 67 69 6e 65 2e 20 22 22 22 0a 20 20 20   Engine. """.   
1bee0 20 71 75 69 65 74 20 3d 20 54 72 75 65 0a 20 20   quiet = True.  
1bef0 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c 20    def run(self, 
1bf00 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20 20  handler):.      
1bf10 20 20 66 72 6f 6d 20 67 6f 6f 67 6c 65 2e 61 70    from google.ap
1bf20 70 65 6e 67 69 6e 65 2e 65 78 74 2e 77 65 62 61  pengine.ext.weba
1bf30 70 70 20 69 6d 70 6f 72 74 20 75 74 69 6c 0a 20  pp import util. 
1bf40 20 20 20 20 20 20 20 23 20 41 20 6d 61 69 6e 28         # A main(
1bf50 29 20 66 75 6e 63 74 69 6f 6e 20 69 6e 20 74 68  ) function in th
1bf60 65 20 68 61 6e 64 6c 65 72 20 73 63 72 69 70 74  e handler script
1bf70 20 65 6e 61 62 6c 65 73 20 27 41 70 70 20 43 61   enables 'App Ca
1bf80 63 68 69 6e 67 27 2e 0a 20 20 20 20 20 20 20 20  ching'..        
1bf90 23 20 4c 65 74 73 20 6d 61 6b 65 73 20 73 75 72  # Lets makes sur
1bfa0 65 20 69 74 20 69 73 20 74 68 65 72 65 2e 20 54  e it is there. T
1bfb0 68 69 73 20 5f 72 65 61 6c 6c 79 5f 20 69 6d 70  his _really_ imp
1bfc0 72 6f 76 65 73 20 70 65 72 66 6f 72 6d 61 6e 63  roves performanc
1bfd0 65 2e 0a 20 20 20 20 20 20 20 20 6d 6f 64 75 6c  e..        modul
1bfe0 65 20 3d 20 73 79 73 2e 6d 6f 64 75 6c 65 73 2e  e = sys.modules.
1bff0 67 65 74 28 27 5f 5f 6d 61 69 6e 5f 5f 27 29 0a  get('__main__').
1c000 20 20 20 20 20 20 20 20 69 66 20 6d 6f 64 75 6c          if modul
1c010 65 20 61 6e 64 20 6e 6f 74 20 68 61 73 61 74 74  e and not hasatt
1c020 72 28 6d 6f 64 75 6c 65 2c 20 27 6d 61 69 6e 27  r(module, 'main'
1c030 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6d  ):.            m
1c040 6f 64 75 6c 65 2e 6d 61 69 6e 20 3d 20 6c 61 6d  odule.main = lam
1c050 62 64 61 3a 20 75 74 69 6c 2e 72 75 6e 5f 77 73  bda: util.run_ws
1c060 67 69 5f 61 70 70 28 68 61 6e 64 6c 65 72 29 0a  gi_app(handler).
1c070 20 20 20 20 20 20 20 20 75 74 69 6c 2e 72 75 6e          util.run
1c080 5f 77 73 67 69 5f 61 70 70 28 68 61 6e 64 6c 65  _wsgi_app(handle
1c090 72 29 0a 0a 0a 63 6c 61 73 73 20 54 77 69 73 74  r)...class Twist
1c0a0 65 64 53 65 72 76 65 72 28 53 65 72 76 65 72 41  edServer(ServerA
1c0b0 64 61 70 74 65 72 29 3a 0a 20 20 20 20 22 22 22  dapter):.    """
1c0c0 20 55 6e 74 65 73 74 65 64 2e 20 22 22 22 0a 20   Untested. """. 
1c0d0 20 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c     def run(self,
1c0e0 20 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20   handler):.     
1c0f0 20 20 20 66 72 6f 6d 20 74 77 69 73 74 65 64 2e     from twisted.
1c100 77 65 62 20 69 6d 70 6f 72 74 20 73 65 72 76 65  web import serve
1c110 72 2c 20 77 73 67 69 0a 20 20 20 20 20 20 20 20  r, wsgi.        
1c120 66 72 6f 6d 20 74 77 69 73 74 65 64 2e 70 79 74  from twisted.pyt
1c130 68 6f 6e 2e 74 68 72 65 61 64 70 6f 6f 6c 20 69  hon.threadpool i
1c140 6d 70 6f 72 74 20 54 68 72 65 61 64 50 6f 6f 6c  mport ThreadPool
1c150 0a 20 20 20 20 20 20 20 20 66 72 6f 6d 20 74 77  .        from tw
1c160 69 73 74 65 64 2e 69 6e 74 65 72 6e 65 74 20 69  isted.internet i
1c170 6d 70 6f 72 74 20 72 65 61 63 74 6f 72 0a 20 20  mport reactor.  
1c180 20 20 20 20 20 20 74 68 72 65 61 64 5f 70 6f 6f        thread_poo
1c190 6c 20 3d 20 54 68 72 65 61 64 50 6f 6f 6c 28 29  l = ThreadPool()
1c1a0 0a 20 20 20 20 20 20 20 20 74 68 72 65 61 64 5f  .        thread_
1c1b0 70 6f 6f 6c 2e 73 74 61 72 74 28 29 0a 20 20 20  pool.start().   
1c1c0 20 20 20 20 20 72 65 61 63 74 6f 72 2e 61 64 64       reactor.add
1c1d0 53 79 73 74 65 6d 45 76 65 6e 74 54 72 69 67 67  SystemEventTrigg
1c1e0 65 72 28 27 61 66 74 65 72 27 2c 20 27 73 68 75  er('after', 'shu
1c1f0 74 64 6f 77 6e 27 2c 20 74 68 72 65 61 64 5f 70  tdown', thread_p
1c200 6f 6f 6c 2e 73 74 6f 70 29 0a 20 20 20 20 20 20  ool.stop).      
1c210 20 20 66 61 63 74 6f 72 79 20 3d 20 73 65 72 76    factory = serv
1c220 65 72 2e 53 69 74 65 28 77 73 67 69 2e 57 53 47  er.Site(wsgi.WSG
1c230 49 52 65 73 6f 75 72 63 65 28 72 65 61 63 74 6f  IResource(reacto
1c240 72 2c 20 74 68 72 65 61 64 5f 70 6f 6f 6c 2c 20  r, thread_pool, 
1c250 68 61 6e 64 6c 65 72 29 29 0a 20 20 20 20 20 20  handler)).      
1c260 20 20 72 65 61 63 74 6f 72 2e 6c 69 73 74 65 6e    reactor.listen
1c270 54 43 50 28 73 65 6c 66 2e 70 6f 72 74 2c 20 66  TCP(self.port, f
1c280 61 63 74 6f 72 79 2c 20 69 6e 74 65 72 66 61 63  actory, interfac
1c290 65 3d 73 65 6c 66 2e 68 6f 73 74 29 0a 20 20 20  e=self.host).   
1c2a0 20 20 20 20 20 72 65 61 63 74 6f 72 2e 72 75 6e       reactor.run
1c2b0 28 29 0a 0a 0a 63 6c 61 73 73 20 44 69 65 73 65  ()...class Diese
1c2c0 6c 53 65 72 76 65 72 28 53 65 72 76 65 72 41 64  lServer(ServerAd
1c2d0 61 70 74 65 72 29 3a 0a 20 20 20 20 22 22 22 20  apter):.    """ 
1c2e0 55 6e 74 65 73 74 65 64 2e 20 22 22 22 0a 20 20  Untested. """.  
1c2f0 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c 20    def run(self, 
1c300 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20 20  handler):.      
1c310 20 20 66 72 6f 6d 20 64 69 65 73 65 6c 2e 70 72    from diesel.pr
1c320 6f 74 6f 63 6f 6c 73 2e 77 73 67 69 20 69 6d 70  otocols.wsgi imp
1c330 6f 72 74 20 57 53 47 49 41 70 70 6c 69 63 61 74  ort WSGIApplicat
1c340 69 6f 6e 0a 20 20 20 20 20 20 20 20 61 70 70 20  ion.        app 
1c350 3d 20 57 53 47 49 41 70 70 6c 69 63 61 74 69 6f  = WSGIApplicatio
1c360 6e 28 68 61 6e 64 6c 65 72 2c 20 70 6f 72 74 3d  n(handler, port=
1c370 73 65 6c 66 2e 70 6f 72 74 29 0a 20 20 20 20 20  self.port).     
1c380 20 20 20 61 70 70 2e 72 75 6e 28 29 0a 0a 0a 63     app.run()...c
1c390 6c 61 73 73 20 47 65 76 65 6e 74 53 65 72 76 65  lass GeventServe
1c3a0 72 28 53 65 72 76 65 72 41 64 61 70 74 65 72 29  r(ServerAdapter)
1c3b0 3a 0a 20 20 20 20 22 22 22 20 55 6e 74 65 73 74  :.    """ Untest
1c3c0 65 64 2e 20 4f 70 74 69 6f 6e 73 3a 0a 0a 20 20  ed. Options:..  
1c3d0 20 20 20 20 20 20 2a 20 60 66 61 73 74 60 20 28        * `fast` (
1c3e0 64 65 66 61 75 6c 74 3a 20 46 61 6c 73 65 29 20  default: False) 
1c3f0 75 73 65 73 20 6c 69 62 65 76 65 6e 74 27 73 20  uses libevent's 
1c400 68 74 74 70 20 73 65 72 76 65 72 2c 20 62 75 74  http server, but
1c410 20 68 61 73 20 73 6f 6d 65 0a 20 20 20 20 20 20   has some.      
1c420 20 20 20 20 69 73 73 75 65 73 3a 20 4e 6f 20 73      issues: No s
1c430 74 72 65 61 6d 69 6e 67 2c 20 6e 6f 20 70 69 70  treaming, no pip
1c440 65 6c 69 6e 69 6e 67 2c 20 6e 6f 20 53 53 4c 2e  elining, no SSL.
1c450 0a 20 20 20 20 20 20 20 20 2a 20 53 65 65 20 67  .        * See g
1c460 65 76 65 6e 74 2e 77 73 67 69 2e 57 53 47 49 53  event.wsgi.WSGIS
1c470 65 72 76 65 72 28 29 20 64 6f 63 75 6d 65 6e 74  erver() document
1c480 61 74 69 6f 6e 20 66 6f 72 20 6d 6f 72 65 20 6f  ation for more o
1c490 70 74 69 6f 6e 73 2e 0a 20 20 20 20 22 22 22 0a  ptions..    """.
1c4a0 20 20 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66      def run(self
1c4b0 2c 20 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20  , handler):.    
1c4c0 20 20 20 20 66 72 6f 6d 20 67 65 76 65 6e 74 20      from gevent 
1c4d0 69 6d 70 6f 72 74 20 77 73 67 69 2c 20 70 79 77  import wsgi, pyw
1c4e0 73 67 69 2c 20 6c 6f 63 61 6c 0a 20 20 20 20 20  sgi, local.     
1c4f0 20 20 20 69 66 20 6e 6f 74 20 69 73 69 6e 73 74     if not isinst
1c500 61 6e 63 65 28 74 68 72 65 61 64 69 6e 67 2e 6c  ance(threading.l
1c510 6f 63 61 6c 28 29 2c 20 6c 6f 63 61 6c 2e 6c 6f  ocal(), local.lo
1c520 63 61 6c 29 3a 0a 20 20 20 20 20 20 20 20 20 20  cal):.          
1c530 20 20 6d 73 67 20 3d 20 22 42 6f 74 74 6c 65 20    msg = "Bottle 
1c540 72 65 71 75 69 72 65 73 20 67 65 76 65 6e 74 2e  requires gevent.
1c550 6d 6f 6e 6b 65 79 2e 70 61 74 63 68 5f 61 6c 6c  monkey.patch_all
1c560 28 29 20 28 62 65 66 6f 72 65 20 69 6d 70 6f 72  () (before impor
1c570 74 29 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  t)".            
1c580 72 61 69 73 65 20 52 75 6e 74 69 6d 65 45 72 72  raise RuntimeErr
1c590 6f 72 28 6d 73 67 29 0a 20 20 20 20 20 20 20 20  or(msg).        
1c5a0 69 66 20 6e 6f 74 20 73 65 6c 66 2e 6f 70 74 69  if not self.opti
1c5b0 6f 6e 73 2e 70 6f 70 28 27 66 61 73 74 27 2c 20  ons.pop('fast', 
1c5c0 4e 6f 6e 65 29 3a 20 77 73 67 69 20 3d 20 70 79  None): wsgi = py
1c5d0 77 73 67 69 0a 20 20 20 20 20 20 20 20 73 65 6c  wsgi.        sel
1c5e0 66 2e 6f 70 74 69 6f 6e 73 5b 27 6c 6f 67 27 5d  f.options['log']
1c5f0 20 3d 20 4e 6f 6e 65 20 69 66 20 73 65 6c 66 2e   = None if self.
1c600 71 75 69 65 74 20 65 6c 73 65 20 27 64 65 66 61  quiet else 'defa
1c610 75 6c 74 27 0a 20 20 20 20 20 20 20 20 61 64 64  ult'.        add
1c620 72 65 73 73 20 3d 20 28 73 65 6c 66 2e 68 6f 73  ress = (self.hos
1c630 74 2c 20 73 65 6c 66 2e 70 6f 72 74 29 0a 20 20  t, self.port).  
1c640 20 20 20 20 20 20 73 65 72 76 65 72 20 3d 20 77        server = w
1c650 73 67 69 2e 57 53 47 49 53 65 72 76 65 72 28 61  sgi.WSGIServer(a
1c660 64 64 72 65 73 73 2c 20 68 61 6e 64 6c 65 72 2c  ddress, handler,
1c670 20 2a 2a 73 65 6c 66 2e 6f 70 74 69 6f 6e 73 29   **self.options)
1c680 0a 20 20 20 20 20 20 20 20 69 66 20 27 42 4f 54  .        if 'BOT
1c690 54 4c 45 5f 43 48 49 4c 44 27 20 69 6e 20 6f 73  TLE_CHILD' in os
1c6a0 2e 65 6e 76 69 72 6f 6e 3a 0a 20 20 20 20 20 20  .environ:.      
1c6b0 20 20 20 20 20 20 69 6d 70 6f 72 74 20 73 69 67        import sig
1c6c0 6e 61 6c 0a 20 20 20 20 20 20 20 20 20 20 20 20  nal.            
1c6d0 73 69 67 6e 61 6c 2e 73 69 67 6e 61 6c 28 73 69  signal.signal(si
1c6e0 67 6e 61 6c 2e 53 49 47 49 4e 54 2c 20 6c 61 6d  gnal.SIGINT, lam
1c6f0 62 64 61 20 73 2c 20 66 3a 20 73 65 72 76 65 72  bda s, f: server
1c700 2e 73 74 6f 70 28 29 29 0a 20 20 20 20 20 20 20  .stop()).       
1c710 20 73 65 72 76 65 72 2e 73 65 72 76 65 5f 66 6f   server.serve_fo
1c720 72 65 76 65 72 28 29 0a 0a 0a 63 6c 61 73 73 20  rever()...class 
1c730 47 65 76 65 6e 74 53 6f 63 6b 65 74 49 4f 53 65  GeventSocketIOSe
1c740 72 76 65 72 28 53 65 72 76 65 72 41 64 61 70 74  rver(ServerAdapt
1c750 65 72 29 3a 0a 20 20 20 20 64 65 66 20 72 75 6e  er):.    def run
1c760 28 73 65 6c 66 2c 68 61 6e 64 6c 65 72 29 3a 0a  (self,handler):.
1c770 20 20 20 20 20 20 20 20 66 72 6f 6d 20 73 6f 63          from soc
1c780 6b 65 74 69 6f 20 69 6d 70 6f 72 74 20 73 65 72  ketio import ser
1c790 76 65 72 0a 20 20 20 20 20 20 20 20 61 64 64 72  ver.        addr
1c7a0 65 73 73 20 3d 20 28 73 65 6c 66 2e 68 6f 73 74  ess = (self.host
1c7b0 2c 20 73 65 6c 66 2e 70 6f 72 74 29 0a 20 20 20  , self.port).   
1c7c0 20 20 20 20 20 73 65 72 76 65 72 2e 53 6f 63 6b       server.Sock
1c7d0 65 74 49 4f 53 65 72 76 65 72 28 61 64 64 72 65  etIOServer(addre
1c7e0 73 73 2c 20 68 61 6e 64 6c 65 72 2c 20 2a 2a 73  ss, handler, **s
1c7f0 65 6c 66 2e 6f 70 74 69 6f 6e 73 29 2e 73 65 72  elf.options).ser
1c800 76 65 5f 66 6f 72 65 76 65 72 28 29 0a 0a 0a 63  ve_forever()...c
1c810 6c 61 73 73 20 47 75 6e 69 63 6f 72 6e 53 65 72  lass GunicornSer
1c820 76 65 72 28 53 65 72 76 65 72 41 64 61 70 74 65  ver(ServerAdapte
1c830 72 29 3a 0a 20 20 20 20 22 22 22 20 55 6e 74 65  r):.    """ Unte
1c840 73 74 65 64 2e 20 53 65 65 20 68 74 74 70 3a 2f  sted. See http:/
1c850 2f 67 75 6e 69 63 6f 72 6e 2e 6f 72 67 2f 63 6f  /gunicorn.org/co
1c860 6e 66 69 67 75 72 65 2e 68 74 6d 6c 20 66 6f 72  nfigure.html for
1c870 20 6f 70 74 69 6f 6e 73 2e 20 22 22 22 0a 20 20   options. """.  
1c880 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c 20    def run(self, 
1c890 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20 20  handler):.      
1c8a0 20 20 66 72 6f 6d 20 67 75 6e 69 63 6f 72 6e 2e    from gunicorn.
1c8b0 61 70 70 2e 62 61 73 65 20 69 6d 70 6f 72 74 20  app.base import 
1c8c0 41 70 70 6c 69 63 61 74 69 6f 6e 0a 0a 20 20 20  Application..   
1c8d0 20 20 20 20 20 63 6f 6e 66 69 67 20 3d 20 7b 27       config = {'
1c8e0 62 69 6e 64 27 3a 20 22 25 73 3a 25 64 22 20 25  bind': "%s:%d" %
1c8f0 20 28 73 65 6c 66 2e 68 6f 73 74 2c 20 69 6e 74   (self.host, int
1c900 28 73 65 6c 66 2e 70 6f 72 74 29 29 7d 0a 20 20  (self.port))}.  
1c910 20 20 20 20 20 20 63 6f 6e 66 69 67 2e 75 70 64        config.upd
1c920 61 74 65 28 73 65 6c 66 2e 6f 70 74 69 6f 6e 73  ate(self.options
1c930 29 0a 0a 20 20 20 20 20 20 20 20 63 6c 61 73 73  )..        class
1c940 20 47 75 6e 69 63 6f 72 6e 41 70 70 6c 69 63 61   GunicornApplica
1c950 74 69 6f 6e 28 41 70 70 6c 69 63 61 74 69 6f 6e  tion(Application
1c960 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  ):.            d
1c970 65 66 20 69 6e 69 74 28 73 65 6c 66 2c 20 70 61  ef init(self, pa
1c980 72 73 65 72 2c 20 6f 70 74 73 2c 20 61 72 67 73  rser, opts, args
1c990 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
1c9a0 20 20 20 72 65 74 75 72 6e 20 63 6f 6e 66 69 67     return config
1c9b0 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 65  ..            de
1c9c0 66 20 6c 6f 61 64 28 73 65 6c 66 29 3a 0a 20 20  f load(self):.  
1c9d0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
1c9e0 74 75 72 6e 20 68 61 6e 64 6c 65 72 0a 0a 20 20  turn handler..  
1c9f0 20 20 20 20 20 20 47 75 6e 69 63 6f 72 6e 41 70        GunicornAp
1ca00 70 6c 69 63 61 74 69 6f 6e 28 29 2e 72 75 6e 28  plication().run(
1ca10 29 0a 0a 0a 63 6c 61 73 73 20 45 76 65 6e 74 6c  )...class Eventl
1ca20 65 74 53 65 72 76 65 72 28 53 65 72 76 65 72 41  etServer(ServerA
1ca30 64 61 70 74 65 72 29 3a 0a 20 20 20 20 22 22 22  dapter):.    """
1ca40 20 55 6e 74 65 73 74 65 64 20 22 22 22 0a 20 20   Untested """.  
1ca50 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c 20    def run(self, 
1ca60 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20 20  handler):.      
1ca70 20 20 66 72 6f 6d 20 65 76 65 6e 74 6c 65 74 20    from eventlet 
1ca80 69 6d 70 6f 72 74 20 77 73 67 69 2c 20 6c 69 73  import wsgi, lis
1ca90 74 65 6e 0a 20 20 20 20 20 20 20 20 74 72 79 3a  ten.        try:
1caa0 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 73 67  .            wsg
1cab0 69 2e 73 65 72 76 65 72 28 6c 69 73 74 65 6e 28  i.server(listen(
1cac0 28 73 65 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66  (self.host, self
1cad0 2e 70 6f 72 74 29 29 2c 20 68 61 6e 64 6c 65 72  .port)), handler
1cae0 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1caf0 20 20 20 20 20 20 20 20 20 20 6c 6f 67 5f 6f 75            log_ou
1cb00 74 70 75 74 3d 28 6e 6f 74 20 73 65 6c 66 2e 71  tput=(not self.q
1cb10 75 69 65 74 29 29 0a 20 20 20 20 20 20 20 20 65  uiet)).        e
1cb20 78 63 65 70 74 20 54 79 70 65 45 72 72 6f 72 3a  xcept TypeError:
1cb30 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20 46  .            # F
1cb40 61 6c 6c 62 61 63 6b 2c 20 69 66 20 77 65 20 68  allback, if we h
1cb50 61 76 65 20 6f 6c 64 20 76 65 72 73 69 6f 6e 20  ave old version 
1cb60 6f 66 20 65 76 65 6e 74 6c 65 74 0a 20 20 20 20  of eventlet.    
1cb70 20 20 20 20 20 20 20 20 77 73 67 69 2e 73 65 72          wsgi.ser
1cb80 76 65 72 28 6c 69 73 74 65 6e 28 28 73 65 6c 66  ver(listen((self
1cb90 2e 68 6f 73 74 2c 20 73 65 6c 66 2e 70 6f 72 74  .host, self.port
1cba0 29 29 2c 20 68 61 6e 64 6c 65 72 29 0a 0a 0a 63  )), handler)...c
1cbb0 6c 61 73 73 20 52 6f 63 6b 65 74 53 65 72 76 65  lass RocketServe
1cbc0 72 28 53 65 72 76 65 72 41 64 61 70 74 65 72 29  r(ServerAdapter)
1cbd0 3a 0a 20 20 20 20 22 22 22 20 55 6e 74 65 73 74  :.    """ Untest
1cbe0 65 64 2e 20 22 22 22 0a 20 20 20 20 64 65 66 20  ed. """.    def 
1cbf0 72 75 6e 28 73 65 6c 66 2c 20 68 61 6e 64 6c 65  run(self, handle
1cc00 72 29 3a 0a 20 20 20 20 20 20 20 20 66 72 6f 6d  r):.        from
1cc10 20 72 6f 63 6b 65 74 20 69 6d 70 6f 72 74 20 52   rocket import R
1cc20 6f 63 6b 65 74 0a 20 20 20 20 20 20 20 20 73 65  ocket.        se
1cc30 72 76 65 72 20 3d 20 52 6f 63 6b 65 74 28 28 73  rver = Rocket((s
1cc40 65 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66 2e 70  elf.host, self.p
1cc50 6f 72 74 29 2c 20 27 77 73 67 69 27 2c 20 7b 20  ort), 'wsgi', { 
1cc60 27 77 73 67 69 5f 61 70 70 27 20 3a 20 68 61 6e  'wsgi_app' : han
1cc70 64 6c 65 72 20 7d 29 0a 20 20 20 20 20 20 20 20  dler }).        
1cc80 73 65 72 76 65 72 2e 73 74 61 72 74 28 29 0a 0a  server.start()..
1cc90 0a 63 6c 61 73 73 20 42 6a 6f 65 72 6e 53 65 72  .class BjoernSer
1cca0 76 65 72 28 53 65 72 76 65 72 41 64 61 70 74 65  ver(ServerAdapte
1ccb0 72 29 3a 0a 20 20 20 20 22 22 22 20 46 61 73 74  r):.    """ Fast
1ccc0 20 73 65 72 76 65 72 20 77 72 69 74 74 65 6e 20   server written 
1ccd0 69 6e 20 43 3a 20 68 74 74 70 73 3a 2f 2f 67 69  in C: https://gi
1cce0 74 68 75 62 2e 63 6f 6d 2f 6a 6f 6e 61 73 68 61  thub.com/jonasha
1ccf0 61 67 2f 62 6a 6f 65 72 6e 20 22 22 22 0a 20 20  ag/bjoern """.  
1cd00 20 20 64 65 66 20 72 75 6e 28 73 65 6c 66 2c 20    def run(self, 
1cd10 68 61 6e 64 6c 65 72 29 3a 0a 20 20 20 20 20 20  handler):.      
1cd20 20 20 66 72 6f 6d 20 62 6a 6f 65 72 6e 20 69 6d    from bjoern im
1cd30 70 6f 72 74 20 72 75 6e 0a 20 20 20 20 20 20 20  port run.       
1cd40 20 72 75 6e 28 68 61 6e 64 6c 65 72 2c 20 73 65   run(handler, se
1cd50 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66 2e 70 6f  lf.host, self.po
1cd60 72 74 29 0a 0a 0a 63 6c 61 73 73 20 41 75 74 6f  rt)...class Auto
1cd70 53 65 72 76 65 72 28 53 65 72 76 65 72 41 64 61  Server(ServerAda
1cd80 70 74 65 72 29 3a 0a 20 20 20 20 22 22 22 20 55  pter):.    """ U
1cd90 6e 74 65 73 74 65 64 2e 20 22 22 22 0a 20 20 20  ntested. """.   
1cda0 20 61 64 61 70 74 65 72 73 20 3d 20 5b 57 61 69   adapters = [Wai
1cdb0 74 72 65 73 73 53 65 72 76 65 72 2c 20 50 61 73  tressServer, Pas
1cdc0 74 65 53 65 72 76 65 72 2c 20 54 77 69 73 74 65  teServer, Twiste
1cdd0 64 53 65 72 76 65 72 2c 20 43 68 65 72 72 79 50  dServer, CherryP
1cde0 79 53 65 72 76 65 72 2c 20 57 53 47 49 52 65 66  yServer, WSGIRef
1cdf0 53 65 72 76 65 72 5d 0a 20 20 20 20 64 65 66 20  Server].    def 
1ce00 72 75 6e 28 73 65 6c 66 2c 20 68 61 6e 64 6c 65  run(self, handle
1ce10 72 29 3a 0a 20 20 20 20 20 20 20 20 66 6f 72 20  r):.        for 
1ce20 73 61 20 69 6e 20 73 65 6c 66 2e 61 64 61 70 74  sa in self.adapt
1ce30 65 72 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ers:.           
1ce40 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20   try:.          
1ce50 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 61 28        return sa(
1ce60 73 65 6c 66 2e 68 6f 73 74 2c 20 73 65 6c 66 2e  self.host, self.
1ce70 70 6f 72 74 2c 20 2a 2a 73 65 6c 66 2e 6f 70 74  port, **self.opt
1ce80 69 6f 6e 73 29 2e 72 75 6e 28 68 61 6e 64 6c 65  ions).run(handle
1ce90 72 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65  r).            e
1cea0 78 63 65 70 74 20 49 6d 70 6f 72 74 45 72 72 6f  xcept ImportErro
1ceb0 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
1cec0 20 20 20 70 61 73 73 0a 0a 73 65 72 76 65 72 5f     pass..server_
1ced0 6e 61 6d 65 73 20 3d 20 7b 0a 20 20 20 20 27 63  names = {.    'c
1cee0 67 69 27 3a 20 43 47 49 53 65 72 76 65 72 2c 0a  gi': CGIServer,.
1cef0 20 20 20 20 27 66 6c 75 70 27 3a 20 46 6c 75 70      'flup': Flup
1cf00 46 43 47 49 53 65 72 76 65 72 2c 0a 20 20 20 20  FCGIServer,.    
1cf10 27 77 73 67 69 72 65 66 27 3a 20 57 53 47 49 52  'wsgiref': WSGIR
1cf20 65 66 53 65 72 76 65 72 2c 0a 20 20 20 20 27 77  efServer,.    'w
1cf30 61 69 74 72 65 73 73 27 3a 20 57 61 69 74 72 65  aitress': Waitre
1cf40 73 73 53 65 72 76 65 72 2c 0a 20 20 20 20 27 63  ssServer,.    'c
1cf50 68 65 72 72 79 70 79 27 3a 20 43 68 65 72 72 79  herrypy': Cherry
1cf60 50 79 53 65 72 76 65 72 2c 0a 20 20 20 20 27 70  PyServer,.    'p
1cf70 61 73 74 65 27 3a 20 50 61 73 74 65 53 65 72 76  aste': PasteServ
1cf80 65 72 2c 0a 20 20 20 20 27 66 61 70 77 73 33 27  er,.    'fapws3'
1cf90 3a 20 46 61 70 77 73 53 65 72 76 65 72 2c 0a 20  : FapwsServer,. 
1cfa0 20 20 20 27 74 6f 72 6e 61 64 6f 27 3a 20 54 6f     'tornado': To
1cfb0 72 6e 61 64 6f 53 65 72 76 65 72 2c 0a 20 20 20  rnadoServer,.   
1cfc0 20 27 67 61 65 27 3a 20 41 70 70 45 6e 67 69 6e   'gae': AppEngin
1cfd0 65 53 65 72 76 65 72 2c 0a 20 20 20 20 27 74 77  eServer,.    'tw
1cfe0 69 73 74 65 64 27 3a 20 54 77 69 73 74 65 64 53  isted': TwistedS
1cff0 65 72 76 65 72 2c 0a 20 20 20 20 27 64 69 65 73  erver,.    'dies
1d000 65 6c 27 3a 20 44 69 65 73 65 6c 53 65 72 76 65  el': DieselServe
1d010 72 2c 0a 20 20 20 20 27 6d 65 69 6e 68 65 6c 64  r,.    'meinheld
1d020 27 3a 20 4d 65 69 6e 68 65 6c 64 53 65 72 76 65  ': MeinheldServe
1d030 72 2c 0a 20 20 20 20 27 67 75 6e 69 63 6f 72 6e  r,.    'gunicorn
1d040 27 3a 20 47 75 6e 69 63 6f 72 6e 53 65 72 76 65  ': GunicornServe
1d050 72 2c 0a 20 20 20 20 27 65 76 65 6e 74 6c 65 74  r,.    'eventlet
1d060 27 3a 20 45 76 65 6e 74 6c 65 74 53 65 72 76 65  ': EventletServe
1d070 72 2c 0a 20 20 20 20 27 67 65 76 65 6e 74 27 3a  r,.    'gevent':
1d080 20 47 65 76 65 6e 74 53 65 72 76 65 72 2c 0a 20   GeventServer,. 
1d090 20 20 20 27 67 65 76 65 6e 74 53 6f 63 6b 65 74     'geventSocket
1d0a0 49 4f 27 3a 47 65 76 65 6e 74 53 6f 63 6b 65 74  IO':GeventSocket
1d0b0 49 4f 53 65 72 76 65 72 2c 0a 20 20 20 20 27 72  IOServer,.    'r
1d0c0 6f 63 6b 65 74 27 3a 20 52 6f 63 6b 65 74 53 65  ocket': RocketSe
1d0d0 72 76 65 72 2c 0a 20 20 20 20 27 62 6a 6f 65 72  rver,.    'bjoer
1d0e0 6e 27 20 3a 20 42 6a 6f 65 72 6e 53 65 72 76 65  n' : BjoernServe
1d0f0 72 2c 0a 20 20 20 20 27 61 75 74 6f 27 3a 20 41  r,.    'auto': A
1d100 75 74 6f 53 65 72 76 65 72 2c 0a 7d 0a 0a 0a 0a  utoServer,.}....
1d110 0a 0a 0a 23 23 23 23 23 23 23 23 23 23 23 23 23  ...#############
1d120 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d130 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d140 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d150 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d160 23 23 0a 23 20 41 70 70 6c 69 63 61 74 69 6f 6e  ##.# Application
1d170 20 43 6f 6e 74 72 6f 6c 20 23 23 23 23 23 23 23   Control #######
1d180 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d190 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d1a0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d1b0 23 23 23 0a 23 23 23 23 23 23 23 23 23 23 23 23  ###.############
1d1c0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d1d0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d1e0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d1f0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1d200 23 23 23 0a 0a 0a 64 65 66 20 6c 6f 61 64 28 74  ###...def load(t
1d210 61 72 67 65 74 2c 20 2a 2a 6e 61 6d 65 73 70 61  arget, **namespa
1d220 63 65 29 3a 0a 20 20 20 20 22 22 22 20 49 6d 70  ce):.    """ Imp
1d230 6f 72 74 20 61 20 6d 6f 64 75 6c 65 20 6f 72 20  ort a module or 
1d240 66 65 74 63 68 20 61 6e 20 6f 62 6a 65 63 74 20  fetch an object 
1d250 66 72 6f 6d 20 61 20 6d 6f 64 75 6c 65 2e 0a 0a  from a module...
1d260 20 20 20 20 20 20 20 20 2a 20 60 60 70 61 63 6b          * ``pack
1d270 61 67 65 2e 6d 6f 64 75 6c 65 60 60 20 72 65 74  age.module`` ret
1d280 75 72 6e 73 20 60 6d 6f 64 75 6c 65 60 20 61 73  urns `module` as
1d290 20 61 20 6d 6f 64 75 6c 65 20 6f 62 6a 65 63 74   a module object
1d2a0 2e 0a 20 20 20 20 20 20 20 20 2a 20 60 60 70 61  ..        * ``pa
1d2b0 63 6b 2e 6d 6f 64 3a 6e 61 6d 65 60 60 20 72 65  ck.mod:name`` re
1d2c0 74 75 72 6e 73 20 74 68 65 20 6d 6f 64 75 6c 65  turns the module
1d2d0 20 76 61 72 69 61 62 6c 65 20 60 6e 61 6d 65 60   variable `name`
1d2e0 20 66 72 6f 6d 20 60 70 61 63 6b 2e 6d 6f 64 60   from `pack.mod`
1d2f0 2e 0a 20 20 20 20 20 20 20 20 2a 20 60 60 70 61  ..        * ``pa
1d300 63 6b 2e 6d 6f 64 3a 66 75 6e 63 28 29 60 60 20  ck.mod:func()`` 
1d310 63 61 6c 6c 73 20 60 70 61 63 6b 2e 6d 6f 64 2e  calls `pack.mod.
1d320 66 75 6e 63 28 29 60 20 61 6e 64 20 72 65 74 75  func()` and retu
1d330 72 6e 73 20 74 68 65 20 72 65 73 75 6c 74 2e 0a  rns the result..
1d340 0a 20 20 20 20 20 20 20 20 54 68 65 20 6c 61 73  .        The las
1d350 74 20 66 6f 72 6d 20 61 63 63 65 70 74 73 20 6e  t form accepts n
1d360 6f 74 20 6f 6e 6c 79 20 66 75 6e 63 74 69 6f 6e  ot only function
1d370 20 63 61 6c 6c 73 2c 20 62 75 74 20 61 6e 79 20   calls, but any 
1d380 74 79 70 65 20 6f 66 0a 20 20 20 20 20 20 20 20  type of.        
1d390 65 78 70 72 65 73 73 69 6f 6e 2e 20 4b 65 79 77  expression. Keyw
1d3a0 6f 72 64 20 61 72 67 75 6d 65 6e 74 73 20 70 61  ord arguments pa
1d3b0 73 73 65 64 20 74 6f 20 74 68 69 73 20 66 75 6e  ssed to this fun
1d3c0 63 74 69 6f 6e 20 61 72 65 20 61 76 61 69 6c 61  ction are availa
1d3d0 62 6c 65 20 61 73 0a 20 20 20 20 20 20 20 20 6c  ble as.        l
1d3e0 6f 63 61 6c 20 76 61 72 69 61 62 6c 65 73 2e 20  ocal variables. 
1d3f0 45 78 61 6d 70 6c 65 3a 20 60 60 69 6d 70 6f 72  Example: ``impor
1d400 74 5f 73 74 72 69 6e 67 28 27 72 65 3a 63 6f 6d  t_string('re:com
1d410 70 69 6c 65 28 78 29 27 2c 20 78 3d 27 5b 61 2d  pile(x)', x='[a-
1d420 7a 5d 27 29 60 60 0a 20 20 20 20 22 22 22 0a 20  z]')``.    """. 
1d430 20 20 20 6d 6f 64 75 6c 65 2c 20 74 61 72 67 65     module, targe
1d440 74 20 3d 20 74 61 72 67 65 74 2e 73 70 6c 69 74  t = target.split
1d450 28 22 3a 22 2c 20 31 29 20 69 66 20 27 3a 27 20  (":", 1) if ':' 
1d460 69 6e 20 74 61 72 67 65 74 20 65 6c 73 65 20 28  in target else (
1d470 74 61 72 67 65 74 2c 20 4e 6f 6e 65 29 0a 20 20  target, None).  
1d480 20 20 69 66 20 6d 6f 64 75 6c 65 20 6e 6f 74 20    if module not 
1d490 69 6e 20 73 79 73 2e 6d 6f 64 75 6c 65 73 3a 20  in sys.modules: 
1d4a0 5f 5f 69 6d 70 6f 72 74 5f 5f 28 6d 6f 64 75 6c  __import__(modul
1d4b0 65 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 74 61  e).    if not ta
1d4c0 72 67 65 74 3a 20 72 65 74 75 72 6e 20 73 79 73  rget: return sys
1d4d0 2e 6d 6f 64 75 6c 65 73 5b 6d 6f 64 75 6c 65 5d  .modules[module]
1d4e0 0a 20 20 20 20 69 66 20 74 61 72 67 65 74 2e 69  .    if target.i
1d4f0 73 61 6c 6e 75 6d 28 29 3a 20 72 65 74 75 72 6e  salnum(): return
1d500 20 67 65 74 61 74 74 72 28 73 79 73 2e 6d 6f 64   getattr(sys.mod
1d510 75 6c 65 73 5b 6d 6f 64 75 6c 65 5d 2c 20 74 61  ules[module], ta
1d520 72 67 65 74 29 0a 20 20 20 20 70 61 63 6b 61 67  rget).    packag
1d530 65 5f 6e 61 6d 65 20 3d 20 6d 6f 64 75 6c 65 2e  e_name = module.
1d540 73 70 6c 69 74 28 27 2e 27 29 5b 30 5d 0a 20 20  split('.')[0].  
1d550 20 20 6e 61 6d 65 73 70 61 63 65 5b 70 61 63 6b    namespace[pack
1d560 61 67 65 5f 6e 61 6d 65 5d 20 3d 20 73 79 73 2e  age_name] = sys.
1d570 6d 6f 64 75 6c 65 73 5b 70 61 63 6b 61 67 65 5f  modules[package_
1d580 6e 61 6d 65 5d 0a 20 20 20 20 72 65 74 75 72 6e  name].    return
1d590 20 65 76 61 6c 28 27 25 73 2e 25 73 27 20 25 20   eval('%s.%s' % 
1d5a0 28 6d 6f 64 75 6c 65 2c 20 74 61 72 67 65 74 29  (module, target)
1d5b0 2c 20 6e 61 6d 65 73 70 61 63 65 29 0a 0a 0a 64  , namespace)...d
1d5c0 65 66 20 6c 6f 61 64 5f 61 70 70 28 74 61 72 67  ef load_app(targ
1d5d0 65 74 29 3a 0a 20 20 20 20 22 22 22 20 4c 6f 61  et):.    """ Loa
1d5e0 64 20 61 20 62 6f 74 74 6c 65 20 61 70 70 6c 69  d a bottle appli
1d5f0 63 61 74 69 6f 6e 20 66 72 6f 6d 20 61 20 6d 6f  cation from a mo
1d600 64 75 6c 65 20 61 6e 64 20 6d 61 6b 65 20 73 75  dule and make su
1d610 72 65 20 74 68 61 74 20 74 68 65 20 69 6d 70 6f  re that the impo
1d620 72 74 0a 20 20 20 20 20 20 20 20 64 6f 65 73 20  rt.        does 
1d630 6e 6f 74 20 61 66 66 65 63 74 20 74 68 65 20 63  not affect the c
1d640 75 72 72 65 6e 74 20 64 65 66 61 75 6c 74 20 61  urrent default a
1d650 70 70 6c 69 63 61 74 69 6f 6e 2c 20 62 75 74 20  pplication, but 
1d660 72 65 74 75 72 6e 73 20 61 20 73 65 70 61 72 61  returns a separa
1d670 74 65 0a 20 20 20 20 20 20 20 20 61 70 70 6c 69  te.        appli
1d680 63 61 74 69 6f 6e 20 6f 62 6a 65 63 74 2e 20 53  cation object. S
1d690 65 65 20 3a 66 75 6e 63 3a 60 6c 6f 61 64 60 20  ee :func:`load` 
1d6a0 66 6f 72 20 74 68 65 20 74 61 72 67 65 74 20 70  for the target p
1d6b0 61 72 61 6d 65 74 65 72 2e 20 22 22 22 0a 20 20  arameter. """.  
1d6c0 20 20 67 6c 6f 62 61 6c 20 4e 4f 52 55 4e 3b 20    global NORUN; 
1d6d0 4e 4f 52 55 4e 2c 20 6e 72 5f 6f 6c 64 20 3d 20  NORUN, nr_old = 
1d6e0 54 72 75 65 2c 20 4e 4f 52 55 4e 0a 20 20 20 20  True, NORUN.    
1d6f0 74 72 79 3a 0a 20 20 20 20 20 20 20 20 74 6d 70  try:.        tmp
1d700 20 3d 20 64 65 66 61 75 6c 74 5f 61 70 70 2e 70   = default_app.p
1d710 75 73 68 28 29 20 23 20 43 72 65 61 74 65 20 61  ush() # Create a
1d720 20 6e 65 77 20 22 64 65 66 61 75 6c 74 20 61 70   new "default ap
1d730 70 6c 69 63 61 74 69 6f 6e 22 0a 20 20 20 20 20  plication".     
1d740 20 20 20 72 76 20 3d 20 6c 6f 61 64 28 74 61 72     rv = load(tar
1d750 67 65 74 29 20 23 20 49 6d 70 6f 72 74 20 74 68  get) # Import th
1d760 65 20 74 61 72 67 65 74 20 6d 6f 64 75 6c 65 0a  e target module.
1d770 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 72          return r
1d780 76 20 69 66 20 63 61 6c 6c 61 62 6c 65 28 72 76  v if callable(rv
1d790 29 20 65 6c 73 65 20 74 6d 70 0a 20 20 20 20 66  ) else tmp.    f
1d7a0 69 6e 61 6c 6c 79 3a 0a 20 20 20 20 20 20 20 20  inally:.        
1d7b0 64 65 66 61 75 6c 74 5f 61 70 70 2e 72 65 6d 6f  default_app.remo
1d7c0 76 65 28 74 6d 70 29 20 23 20 52 65 6d 6f 76 65  ve(tmp) # Remove
1d7d0 20 74 68 65 20 74 65 6d 70 6f 72 61 72 79 20 61   the temporary a
1d7e0 64 64 65 64 20 64 65 66 61 75 6c 74 20 61 70 70  dded default app
1d7f0 6c 69 63 61 74 69 6f 6e 0a 20 20 20 20 20 20 20  lication.       
1d800 20 4e 4f 52 55 4e 20 3d 20 6e 72 5f 6f 6c 64 0a   NORUN = nr_old.
1d810 0a 5f 64 65 62 75 67 20 3d 20 64 65 62 75 67 0a  ._debug = debug.
1d820 64 65 66 20 72 75 6e 28 61 70 70 3d 4e 6f 6e 65  def run(app=None
1d830 2c 20 73 65 72 76 65 72 3d 27 77 73 67 69 72 65  , server='wsgire
1d840 66 27 2c 20 68 6f 73 74 3d 27 31 32 37 2e 30 2e  f', host='127.0.
1d850 30 2e 31 27 2c 20 70 6f 72 74 3d 38 30 38 30 2c  0.1', port=8080,
1d860 0a 20 20 20 20 20 20 20 20 69 6e 74 65 72 76 61  .        interva
1d870 6c 3d 31 2c 20 72 65 6c 6f 61 64 65 72 3d 46 61  l=1, reloader=Fa
1d880 6c 73 65 2c 20 71 75 69 65 74 3d 46 61 6c 73 65  lse, quiet=False
1d890 2c 20 70 6c 75 67 69 6e 73 3d 4e 6f 6e 65 2c 0a  , plugins=None,.
1d8a0 20 20 20 20 20 20 20 20 64 65 62 75 67 3d 4e 6f          debug=No
1d8b0 6e 65 2c 20 2a 2a 6b 61 72 67 73 29 3a 0a 20 20  ne, **kargs):.  
1d8c0 20 20 22 22 22 20 53 74 61 72 74 20 61 20 73 65    """ Start a se
1d8d0 72 76 65 72 20 69 6e 73 74 61 6e 63 65 2e 20 54  rver instance. T
1d8e0 68 69 73 20 6d 65 74 68 6f 64 20 62 6c 6f 63 6b  his method block
1d8f0 73 20 75 6e 74 69 6c 20 74 68 65 20 73 65 72 76  s until the serv
1d900 65 72 20 74 65 72 6d 69 6e 61 74 65 73 2e 0a 0a  er terminates...
1d910 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20 61          :param a
1d920 70 70 3a 20 57 53 47 49 20 61 70 70 6c 69 63 61  pp: WSGI applica
1d930 74 69 6f 6e 20 6f 72 20 74 61 72 67 65 74 20 73  tion or target s
1d940 74 72 69 6e 67 20 73 75 70 70 6f 72 74 65 64 20  tring supported 
1d950 62 79 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  by.             
1d960 20 20 3a 66 75 6e 63 3a 60 6c 6f 61 64 5f 61 70    :func:`load_ap
1d970 70 60 2e 20 28 64 65 66 61 75 6c 74 3a 20 3a 66  p`. (default: :f
1d980 75 6e 63 3a 60 64 65 66 61 75 6c 74 5f 61 70 70  unc:`default_app
1d990 60 29 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61  `).        :para
1d9a0 6d 20 73 65 72 76 65 72 3a 20 53 65 72 76 65 72  m server: Server
1d9b0 20 61 64 61 70 74 65 72 20 74 6f 20 75 73 65 2e   adapter to use.
1d9c0 20 53 65 65 20 3a 64 61 74 61 3a 60 73 65 72 76   See :data:`serv
1d9d0 65 72 5f 6e 61 6d 65 73 60 20 6b 65 79 73 0a 20  er_names` keys. 
1d9e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
1d9f0 72 20 76 61 6c 69 64 20 6e 61 6d 65 73 20 6f 72  r valid names or
1da00 20 70 61 73 73 20 61 20 3a 63 6c 61 73 73 3a 60   pass a :class:`
1da10 53 65 72 76 65 72 41 64 61 70 74 65 72 60 20 73  ServerAdapter` s
1da20 75 62 63 6c 61 73 73 2e 0a 20 20 20 20 20 20 20  ubclass..       
1da30 20 20 20 20 20 20 20 20 28 64 65 66 61 75 6c 74          (default
1da40 3a 20 60 77 73 67 69 72 65 66 60 29 0a 20 20 20  : `wsgiref`).   
1da50 20 20 20 20 20 3a 70 61 72 61 6d 20 68 6f 73 74       :param host
1da60 3a 20 53 65 72 76 65 72 20 61 64 64 72 65 73 73  : Server address
1da70 20 74 6f 20 62 69 6e 64 20 74 6f 2e 20 50 61 73   to bind to. Pas
1da80 73 20 60 60 30 2e 30 2e 30 2e 30 60 60 20 74 6f  s ``0.0.0.0`` to
1da90 20 6c 69 73 74 65 6e 73 20 6f 6e 0a 20 20 20 20   listens on.    
1daa0 20 20 20 20 20 20 20 20 20 20 20 61 6c 6c 20 69             all i
1dab0 6e 74 65 72 66 61 63 65 73 20 69 6e 63 6c 75 64  nterfaces includ
1dac0 69 6e 67 20 74 68 65 20 65 78 74 65 72 6e 61 6c  ing the external
1dad0 20 6f 6e 65 2e 20 28 64 65 66 61 75 6c 74 3a 20   one. (default: 
1dae0 31 32 37 2e 30 2e 30 2e 31 29 0a 20 20 20 20 20  127.0.0.1).     
1daf0 20 20 20 3a 70 61 72 61 6d 20 70 6f 72 74 3a 20     :param port: 
1db00 53 65 72 76 65 72 20 70 6f 72 74 20 74 6f 20 62  Server port to b
1db10 69 6e 64 20 74 6f 2e 20 56 61 6c 75 65 73 20 62  ind to. Values b
1db20 65 6c 6f 77 20 31 30 32 34 20 72 65 71 75 69 72  elow 1024 requir
1db30 65 20 72 6f 6f 74 0a 20 20 20 20 20 20 20 20 20  e root.         
1db40 20 20 20 20 20 20 70 72 69 76 69 6c 65 67 65 73        privileges
1db50 2e 20 28 64 65 66 61 75 6c 74 3a 20 38 30 38 30  . (default: 8080
1db60 29 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d  ).        :param
1db70 20 72 65 6c 6f 61 64 65 72 3a 20 53 74 61 72 74   reloader: Start
1db80 20 61 75 74 6f 2d 72 65 6c 6f 61 64 69 6e 67 20   auto-reloading 
1db90 73 65 72 76 65 72 3f 20 28 64 65 66 61 75 6c 74  server? (default
1dba0 3a 20 46 61 6c 73 65 29 0a 20 20 20 20 20 20 20  : False).       
1dbb0 20 3a 70 61 72 61 6d 20 69 6e 74 65 72 76 61 6c   :param interval
1dbc0 3a 20 41 75 74 6f 2d 72 65 6c 6f 61 64 65 72 20  : Auto-reloader 
1dbd0 69 6e 74 65 72 76 61 6c 20 69 6e 20 73 65 63 6f  interval in seco
1dbe0 6e 64 73 20 28 64 65 66 61 75 6c 74 3a 20 31 29  nds (default: 1)
1dbf0 0a 20 20 20 20 20 20 20 20 3a 70 61 72 61 6d 20  .        :param 
1dc00 71 75 69 65 74 3a 20 53 75 70 70 72 65 73 73 20  quiet: Suppress 
1dc10 6f 75 74 70 75 74 20 74 6f 20 73 74 64 6f 75 74  output to stdout
1dc20 20 61 6e 64 20 73 74 64 65 72 72 3f 20 28 64 65   and stderr? (de
1dc30 66 61 75 6c 74 3a 20 46 61 6c 73 65 29 0a 20 20  fault: False).  
1dc40 20 20 20 20 20 20 3a 70 61 72 61 6d 20 6f 70 74        :param opt
1dc50 69 6f 6e 73 3a 20 4f 70 74 69 6f 6e 73 20 70 61  ions: Options pa
1dc60 73 73 65 64 20 74 6f 20 74 68 65 20 73 65 72 76  ssed to the serv
1dc70 65 72 20 61 64 61 70 74 65 72 2e 0a 20 20 20 20  er adapter..    
1dc80 20 22 22 22 0a 20 20 20 20 69 66 20 4e 4f 52 55   """.    if NORU
1dc90 4e 3a 20 72 65 74 75 72 6e 0a 20 20 20 20 69 66  N: return.    if
1dca0 20 72 65 6c 6f 61 64 65 72 20 61 6e 64 20 6e 6f   reloader and no
1dcb0 74 20 6f 73 2e 65 6e 76 69 72 6f 6e 2e 67 65 74  t os.environ.get
1dcc0 28 27 42 4f 54 54 4c 45 5f 43 48 49 4c 44 27 29  ('BOTTLE_CHILD')
1dcd0 3a 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20  :.        try:. 
1dce0 20 20 20 20 20 20 20 20 20 20 20 6c 6f 63 6b 66             lockf
1dcf0 69 6c 65 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20  ile = None.     
1dd00 20 20 20 20 20 20 20 66 64 2c 20 6c 6f 63 6b 66         fd, lockf
1dd10 69 6c 65 20 3d 20 74 65 6d 70 66 69 6c 65 2e 6d  ile = tempfile.m
1dd20 6b 73 74 65 6d 70 28 70 72 65 66 69 78 3d 27 62  kstemp(prefix='b
1dd30 6f 74 74 6c 65 2e 27 2c 20 73 75 66 66 69 78 3d  ottle.', suffix=
1dd40 27 2e 6c 6f 63 6b 27 29 0a 20 20 20 20 20 20 20  '.lock').       
1dd50 20 20 20 20 20 6f 73 2e 63 6c 6f 73 65 28 66 64       os.close(fd
1dd60 29 20 23 20 57 65 20 6f 6e 6c 79 20 6e 65 65 64  ) # We only need
1dd70 20 74 68 69 73 20 66 69 6c 65 20 74 6f 20 65 78   this file to ex
1dd80 69 73 74 2e 20 57 65 20 6e 65 76 65 72 20 77 72  ist. We never wr
1dd90 69 74 65 20 74 6f 20 69 74 0a 20 20 20 20 20 20  ite to it.      
1dda0 20 20 20 20 20 20 77 68 69 6c 65 20 6f 73 2e 70        while os.p
1ddb0 61 74 68 2e 65 78 69 73 74 73 28 6c 6f 63 6b 66  ath.exists(lockf
1ddc0 69 6c 65 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ile):.          
1ddd0 20 20 20 20 20 20 61 72 67 73 20 3d 20 5b 73 79        args = [sy
1dde0 73 2e 65 78 65 63 75 74 61 62 6c 65 5d 20 2b 20  s.executable] + 
1ddf0 73 79 73 2e 61 72 67 76 0a 20 20 20 20 20 20 20  sys.argv.       
1de00 20 20 20 20 20 20 20 20 20 65 6e 76 69 72 6f 6e           environ
1de10 20 3d 20 6f 73 2e 65 6e 76 69 72 6f 6e 2e 63 6f   = os.environ.co
1de20 70 79 28 29 0a 20 20 20 20 20 20 20 20 20 20 20  py().           
1de30 20 20 20 20 20 65 6e 76 69 72 6f 6e 5b 27 42 4f       environ['BO
1de40 54 54 4c 45 5f 43 48 49 4c 44 27 5d 20 3d 20 27  TTLE_CHILD'] = '
1de50 74 72 75 65 27 0a 20 20 20 20 20 20 20 20 20 20  true'.          
1de60 20 20 20 20 20 20 65 6e 76 69 72 6f 6e 5b 27 42        environ['B
1de70 4f 54 54 4c 45 5f 4c 4f 43 4b 46 49 4c 45 27 5d  OTTLE_LOCKFILE']
1de80 20 3d 20 6c 6f 63 6b 66 69 6c 65 0a 20 20 20 20   = lockfile.    
1de90 20 20 20 20 20 20 20 20 20 20 20 20 70 20 3d 20              p = 
1dea0 73 75 62 70 72 6f 63 65 73 73 2e 50 6f 70 65 6e  subprocess.Popen
1deb0 28 61 72 67 73 2c 20 65 6e 76 3d 65 6e 76 69 72  (args, env=envir
1dec0 6f 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  on).            
1ded0 20 20 20 20 77 68 69 6c 65 20 70 2e 70 6f 6c 6c      while p.poll
1dee0 28 29 20 69 73 20 4e 6f 6e 65 3a 20 23 20 42 75  () is None: # Bu
1def0 73 79 20 77 61 69 74 2e 2e 2e 0a 20 20 20 20 20  sy wait....     
1df00 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6f                 o
1df10 73 2e 75 74 69 6d 65 28 6c 6f 63 6b 66 69 6c 65  s.utime(lockfile
1df20 2c 20 4e 6f 6e 65 29 20 23 20 49 20 61 6d 20 61  , None) # I am a
1df30 6c 69 76 65 21 0a 20 20 20 20 20 20 20 20 20 20  live!.          
1df40 20 20 20 20 20 20 20 20 20 20 74 69 6d 65 2e 73            time.s
1df50 6c 65 65 70 28 69 6e 74 65 72 76 61 6c 29 0a 20  leep(interval). 
1df60 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
1df70 66 20 70 2e 70 6f 6c 6c 28 29 20 21 3d 20 33 3a  f p.poll() != 3:
1df80 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1df90 20 20 20 20 20 69 66 20 6f 73 2e 70 61 74 68 2e       if os.path.
1dfa0 65 78 69 73 74 73 28 6c 6f 63 6b 66 69 6c 65 29  exists(lockfile)
1dfb0 3a 20 6f 73 2e 75 6e 6c 69 6e 6b 28 6c 6f 63 6b  : os.unlink(lock
1dfc0 66 69 6c 65 29 0a 20 20 20 20 20 20 20 20 20 20  file).          
1dfd0 20 20 20 20 20 20 20 20 20 20 73 79 73 2e 65 78            sys.ex
1dfe0 69 74 28 70 2e 70 6f 6c 6c 28 29 29 0a 20 20 20  it(p.poll()).   
1dff0 20 20 20 20 20 65 78 63 65 70 74 20 4b 65 79 62       except Keyb
1e000 6f 61 72 64 49 6e 74 65 72 72 75 70 74 3a 0a 20  oardInterrupt:. 
1e010 20 20 20 20 20 20 20 20 20 20 20 70 61 73 73 0a             pass.
1e020 20 20 20 20 20 20 20 20 66 69 6e 61 6c 6c 79 3a          finally:
1e030 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
1e040 6f 73 2e 70 61 74 68 2e 65 78 69 73 74 73 28 6c  os.path.exists(l
1e050 6f 63 6b 66 69 6c 65 29 3a 0a 20 20 20 20 20 20  ockfile):.      
1e060 20 20 20 20 20 20 20 20 20 20 6f 73 2e 75 6e 6c            os.unl
1e070 69 6e 6b 28 6c 6f 63 6b 66 69 6c 65 29 0a 20 20  ink(lockfile).  
1e080 20 20 20 20 20 20 72 65 74 75 72 6e 0a 0a 20 20        return..  
1e090 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 69    try:.        i
1e0a0 66 20 64 65 62 75 67 20 69 73 20 6e 6f 74 20 4e  f debug is not N
1e0b0 6f 6e 65 3a 20 5f 64 65 62 75 67 28 64 65 62 75  one: _debug(debu
1e0c0 67 29 0a 20 20 20 20 20 20 20 20 61 70 70 20 3d  g).        app =
1e0d0 20 61 70 70 20 6f 72 20 64 65 66 61 75 6c 74 5f   app or default_
1e0e0 61 70 70 28 29 0a 20 20 20 20 20 20 20 20 69 66  app().        if
1e0f0 20 69 73 69 6e 73 74 61 6e 63 65 28 61 70 70 2c   isinstance(app,
1e100 20 62 61 73 65 73 74 72 69 6e 67 29 3a 0a 20 20   basestring):.  
1e110 20 20 20 20 20 20 20 20 20 20 61 70 70 20 3d 20            app = 
1e120 6c 6f 61 64 5f 61 70 70 28 61 70 70 29 0a 20 20  load_app(app).  
1e130 20 20 20 20 20 20 69 66 20 6e 6f 74 20 63 61 6c        if not cal
1e140 6c 61 62 6c 65 28 61 70 70 29 3a 0a 20 20 20 20  lable(app):.    
1e150 20 20 20 20 20 20 20 20 72 61 69 73 65 20 56 61          raise Va
1e160 6c 75 65 45 72 72 6f 72 28 22 41 70 70 6c 69 63  lueError("Applic
1e170 61 74 69 6f 6e 20 69 73 20 6e 6f 74 20 63 61 6c  ation is not cal
1e180 6c 61 62 6c 65 3a 20 25 72 22 20 25 20 61 70 70  lable: %r" % app
1e190 29 0a 0a 20 20 20 20 20 20 20 20 66 6f 72 20 70  )..        for p
1e1a0 6c 75 67 69 6e 20 69 6e 20 70 6c 75 67 69 6e 73  lugin in plugins
1e1b0 20 6f 72 20 5b 5d 3a 0a 20 20 20 20 20 20 20 20   or []:.        
1e1c0 20 20 20 20 61 70 70 2e 69 6e 73 74 61 6c 6c 28      app.install(
1e1d0 70 6c 75 67 69 6e 29 0a 0a 20 20 20 20 20 20 20  plugin)..       
1e1e0 20 69 66 20 73 65 72 76 65 72 20 69 6e 20 73 65   if server in se
1e1f0 72 76 65 72 5f 6e 61 6d 65 73 3a 0a 20 20 20 20  rver_names:.    
1e200 20 20 20 20 20 20 20 20 73 65 72 76 65 72 20 3d          server =
1e210 20 73 65 72 76 65 72 5f 6e 61 6d 65 73 2e 67 65   server_names.ge
1e220 74 28 73 65 72 76 65 72 29 0a 20 20 20 20 20 20  t(server).      
1e230 20 20 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28    if isinstance(
1e240 73 65 72 76 65 72 2c 20 62 61 73 65 73 74 72 69  server, basestri
1e250 6e 67 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ng):.           
1e260 20 73 65 72 76 65 72 20 3d 20 6c 6f 61 64 28 73   server = load(s
1e270 65 72 76 65 72 29 0a 20 20 20 20 20 20 20 20 69  erver).        i
1e280 66 20 69 73 69 6e 73 74 61 6e 63 65 28 73 65 72  f isinstance(ser
1e290 76 65 72 2c 20 74 79 70 65 29 3a 0a 20 20 20 20  ver, type):.    
1e2a0 20 20 20 20 20 20 20 20 73 65 72 76 65 72 20 3d          server =
1e2b0 20 73 65 72 76 65 72 28 68 6f 73 74 3d 68 6f 73   server(host=hos
1e2c0 74 2c 20 70 6f 72 74 3d 70 6f 72 74 2c 20 2a 2a  t, port=port, **
1e2d0 6b 61 72 67 73 29 0a 20 20 20 20 20 20 20 20 69  kargs).        i
1e2e0 66 20 6e 6f 74 20 69 73 69 6e 73 74 61 6e 63 65  f not isinstance
1e2f0 28 73 65 72 76 65 72 2c 20 53 65 72 76 65 72 41  (server, ServerA
1e300 64 61 70 74 65 72 29 3a 0a 20 20 20 20 20 20 20  dapter):.       
1e310 20 20 20 20 20 72 61 69 73 65 20 56 61 6c 75 65       raise Value
1e320 45 72 72 6f 72 28 22 55 6e 6b 6e 6f 77 6e 20 6f  Error("Unknown o
1e330 72 20 75 6e 73 75 70 70 6f 72 74 65 64 20 73 65  r unsupported se
1e340 72 76 65 72 3a 20 25 72 22 20 25 20 73 65 72 76  rver: %r" % serv
1e350 65 72 29 0a 0a 20 20 20 20 20 20 20 20 73 65 72  er)..        ser
1e360 76 65 72 2e 71 75 69 65 74 20 3d 20 73 65 72 76  ver.quiet = serv
1e370 65 72 2e 71 75 69 65 74 20 6f 72 20 71 75 69 65  er.quiet or quie
1e380 74 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74  t.        if not
1e390 20 73 65 72 76 65 72 2e 71 75 69 65 74 3a 0a 20   server.quiet:. 
1e3a0 20 20 20 20 20 20 20 20 20 20 20 5f 73 74 64 65             _stde
1e3b0 72 72 28 22 42 6f 74 74 6c 65 20 76 25 73 20 73  rr("Bottle v%s s
1e3c0 65 72 76 65 72 20 73 74 61 72 74 69 6e 67 20 75  erver starting u
1e3d0 70 20 28 75 73 69 6e 67 20 25 73 29 2e 2e 2e 5c  p (using %s)...\
1e3e0 6e 22 20 25 20 28 5f 5f 76 65 72 73 69 6f 6e 5f  n" % (__version_
1e3f0 5f 2c 20 72 65 70 72 28 73 65 72 76 65 72 29 29  _, repr(server))
1e400 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 5f 73  ).            _s
1e410 74 64 65 72 72 28 22 4c 69 73 74 65 6e 69 6e 67  tderr("Listening
1e420 20 6f 6e 20 68 74 74 70 3a 2f 2f 25 73 3a 25 64   on http://%s:%d
1e430 2f 5c 6e 22 20 25 20 28 73 65 72 76 65 72 2e 68  /\n" % (server.h
1e440 6f 73 74 2c 20 73 65 72 76 65 72 2e 70 6f 72 74  ost, server.port
1e450 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 5f  )).            _
1e460 73 74 64 65 72 72 28 22 48 69 74 20 43 74 72 6c  stderr("Hit Ctrl
1e470 2d 43 20 74 6f 20 71 75 69 74 2e 5c 6e 5c 6e 22  -C to quit.\n\n"
1e480 29 0a 0a 20 20 20 20 20 20 20 20 69 66 20 72 65  )..        if re
1e490 6c 6f 61 64 65 72 3a 0a 20 20 20 20 20 20 20 20  loader:.        
1e4a0 20 20 20 20 6c 6f 63 6b 66 69 6c 65 20 3d 20 6f      lockfile = o
1e4b0 73 2e 65 6e 76 69 72 6f 6e 2e 67 65 74 28 27 42  s.environ.get('B
1e4c0 4f 54 54 4c 45 5f 4c 4f 43 4b 46 49 4c 45 27 29  OTTLE_LOCKFILE')
1e4d0 0a 20 20 20 20 20 20 20 20 20 20 20 20 62 67 63  .            bgc
1e4e0 68 65 63 6b 20 3d 20 46 69 6c 65 43 68 65 63 6b  heck = FileCheck
1e4f0 65 72 54 68 72 65 61 64 28 6c 6f 63 6b 66 69 6c  erThread(lockfil
1e500 65 2c 20 69 6e 74 65 72 76 61 6c 29 0a 20 20 20  e, interval).   
1e510 20 20 20 20 20 20 20 20 20 77 69 74 68 20 62 67           with bg
1e520 63 68 65 63 6b 3a 0a 20 20 20 20 20 20 20 20 20  check:.         
1e530 20 20 20 20 20 20 20 73 65 72 76 65 72 2e 72 75         server.ru
1e540 6e 28 61 70 70 29 0a 20 20 20 20 20 20 20 20 20  n(app).         
1e550 20 20 20 69 66 20 62 67 63 68 65 63 6b 2e 73 74     if bgcheck.st
1e560 61 74 75 73 20 3d 3d 20 27 72 65 6c 6f 61 64 27  atus == 'reload'
1e570 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
1e580 20 20 73 79 73 2e 65 78 69 74 28 33 29 0a 20 20    sys.exit(3).  
1e590 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
1e5a0 20 20 20 20 20 20 20 20 73 65 72 76 65 72 2e 72          server.r
1e5b0 75 6e 28 61 70 70 29 0a 20 20 20 20 65 78 63 65  un(app).    exce
1e5c0 70 74 20 4b 65 79 62 6f 61 72 64 49 6e 74 65 72  pt KeyboardInter
1e5d0 72 75 70 74 3a 0a 20 20 20 20 20 20 20 20 70 61  rupt:.        pa
1e5e0 73 73 0a 20 20 20 20 65 78 63 65 70 74 20 28 53  ss.    except (S
1e5f0 79 73 74 65 6d 45 78 69 74 2c 20 4d 65 6d 6f 72  ystemExit, Memor
1e600 79 45 72 72 6f 72 29 3a 0a 20 20 20 20 20 20 20  yError):.       
1e610 20 72 61 69 73 65 0a 20 20 20 20 65 78 63 65 70   raise.    excep
1e620 74 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f  t:.        if no
1e630 74 20 72 65 6c 6f 61 64 65 72 3a 20 72 61 69 73  t reloader: rais
1e640 65 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74  e.        if not
1e650 20 67 65 74 61 74 74 72 28 73 65 72 76 65 72 2c   getattr(server,
1e660 20 27 71 75 69 65 74 27 2c 20 71 75 69 65 74 29   'quiet', quiet)
1e670 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72  :.            pr
1e680 69 6e 74 5f 65 78 63 28 29 0a 20 20 20 20 20 20  int_exc().      
1e690 20 20 74 69 6d 65 2e 73 6c 65 65 70 28 69 6e 74    time.sleep(int
1e6a0 65 72 76 61 6c 29 0a 20 20 20 20 20 20 20 20 73  erval).        s
1e6b0 79 73 2e 65 78 69 74 28 33 29 0a 0a 0a 0a 63 6c  ys.exit(3)....cl
1e6c0 61 73 73 20 46 69 6c 65 43 68 65 63 6b 65 72 54  ass FileCheckerT
1e6d0 68 72 65 61 64 28 74 68 72 65 61 64 69 6e 67 2e  hread(threading.
1e6e0 54 68 72 65 61 64 29 3a 0a 20 20 20 20 27 27 27  Thread):.    '''
1e6f0 20 49 6e 74 65 72 72 75 70 74 20 6d 61 69 6e 2d   Interrupt main-
1e700 74 68 72 65 61 64 20 61 73 20 73 6f 6f 6e 20 61  thread as soon a
1e710 73 20 61 20 63 68 61 6e 67 65 64 20 6d 6f 64 75  s a changed modu
1e720 6c 65 20 66 69 6c 65 20 69 73 20 64 65 74 65 63  le file is detec
1e730 74 65 64 2c 0a 20 20 20 20 20 20 20 20 74 68 65  ted,.        the
1e740 20 6c 6f 63 6b 66 69 6c 65 20 67 65 74 73 20 64   lockfile gets d
1e750 65 6c 65 74 65 64 20 6f 72 20 67 65 74 73 20 74  eleted or gets t
1e760 6f 20 6f 6c 64 2e 20 27 27 27 0a 0a 20 20 20 20  o old. '''..    
1e770 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c  def __init__(sel
1e780 66 2c 20 6c 6f 63 6b 66 69 6c 65 2c 20 69 6e 74  f, lockfile, int
1e790 65 72 76 61 6c 29 3a 0a 20 20 20 20 20 20 20 20  erval):.        
1e7a0 74 68 72 65 61 64 69 6e 67 2e 54 68 72 65 61 64  threading.Thread
1e7b0 2e 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66 29 0a  .__init__(self).
1e7c0 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 6f 63          self.loc
1e7d0 6b 66 69 6c 65 2c 20 73 65 6c 66 2e 69 6e 74 65  kfile, self.inte
1e7e0 72 76 61 6c 20 3d 20 6c 6f 63 6b 66 69 6c 65 2c  rval = lockfile,
1e7f0 20 69 6e 74 65 72 76 61 6c 0a 20 20 20 20 20 20   interval.      
1e800 20 20 23 3a 20 49 73 20 6f 6e 65 20 6f 66 20 27    #: Is one of '
1e810 72 65 6c 6f 61 64 27 2c 20 27 65 72 72 6f 72 27  reload', 'error'
1e820 20 6f 72 20 27 65 78 69 74 27 0a 20 20 20 20 20   or 'exit'.     
1e830 20 20 20 73 65 6c 66 2e 73 74 61 74 75 73 20 3d     self.status =
1e840 20 4e 6f 6e 65 0a 0a 20 20 20 20 64 65 66 20 72   None..    def r
1e850 75 6e 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20  un(self):.      
1e860 20 20 65 78 69 73 74 73 20 3d 20 6f 73 2e 70 61    exists = os.pa
1e870 74 68 2e 65 78 69 73 74 73 0a 20 20 20 20 20 20  th.exists.      
1e880 20 20 6d 74 69 6d 65 20 3d 20 6c 61 6d 62 64 61    mtime = lambda
1e890 20 70 61 74 68 3a 20 6f 73 2e 73 74 61 74 28 70   path: os.stat(p
1e8a0 61 74 68 29 2e 73 74 5f 6d 74 69 6d 65 0a 20 20  ath).st_mtime.  
1e8b0 20 20 20 20 20 20 66 69 6c 65 73 20 3d 20 64 69        files = di
1e8c0 63 74 28 29 0a 0a 20 20 20 20 20 20 20 20 66 6f  ct()..        fo
1e8d0 72 20 6d 6f 64 75 6c 65 20 69 6e 20 6c 69 73 74  r module in list
1e8e0 28 73 79 73 2e 6d 6f 64 75 6c 65 73 2e 76 61 6c  (sys.modules.val
1e8f0 75 65 73 28 29 29 3a 0a 20 20 20 20 20 20 20 20  ues()):.        
1e900 20 20 20 20 70 61 74 68 20 3d 20 67 65 74 61 74      path = getat
1e910 74 72 28 6d 6f 64 75 6c 65 2c 20 27 5f 5f 66 69  tr(module, '__fi
1e920 6c 65 5f 5f 27 2c 20 27 27 29 0a 20 20 20 20 20  le__', '').     
1e930 20 20 20 20 20 20 20 69 66 20 70 61 74 68 5b 2d         if path[-
1e940 34 3a 5d 20 69 6e 20 28 27 2e 70 79 6f 27 2c 20  4:] in ('.pyo', 
1e950 27 2e 70 79 63 27 29 3a 20 70 61 74 68 20 3d 20  '.pyc'): path = 
1e960 70 61 74 68 5b 3a 2d 31 5d 0a 20 20 20 20 20 20  path[:-1].      
1e970 20 20 20 20 20 20 69 66 20 70 61 74 68 20 61 6e        if path an
1e980 64 20 65 78 69 73 74 73 28 70 61 74 68 29 3a 20  d exists(path): 
1e990 66 69 6c 65 73 5b 70 61 74 68 5d 20 3d 20 6d 74  files[path] = mt
1e9a0 69 6d 65 28 70 61 74 68 29 0a 0a 20 20 20 20 20  ime(path)..     
1e9b0 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 73 65 6c     while not sel
1e9c0 66 2e 73 74 61 74 75 73 3a 0a 20 20 20 20 20 20  f.status:.      
1e9d0 20 20 20 20 20 20 69 66 20 6e 6f 74 20 65 78 69        if not exi
1e9e0 73 74 73 28 73 65 6c 66 2e 6c 6f 63 6b 66 69 6c  sts(self.lockfil
1e9f0 65 29 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  e)\.            
1ea00 6f 72 20 6d 74 69 6d 65 28 73 65 6c 66 2e 6c 6f  or mtime(self.lo
1ea10 63 6b 66 69 6c 65 29 20 3c 20 74 69 6d 65 2e 74  ckfile) < time.t
1ea20 69 6d 65 28 29 20 2d 20 73 65 6c 66 2e 69 6e 74  ime() - self.int
1ea30 65 72 76 61 6c 20 2d 20 35 3a 0a 20 20 20 20 20  erval - 5:.     
1ea40 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
1ea50 73 74 61 74 75 73 20 3d 20 27 65 72 72 6f 72 27  status = 'error'
1ea60 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1ea70 20 74 68 72 65 61 64 2e 69 6e 74 65 72 72 75 70   thread.interrup
1ea80 74 5f 6d 61 69 6e 28 29 0a 20 20 20 20 20 20 20  t_main().       
1ea90 20 20 20 20 20 66 6f 72 20 70 61 74 68 2c 20 6c       for path, l
1eaa0 6d 74 69 6d 65 20 69 6e 20 6c 69 73 74 28 66 69  mtime in list(fi
1eab0 6c 65 73 2e 69 74 65 6d 73 28 29 29 3a 0a 20 20  les.items()):.  
1eac0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
1ead0 20 6e 6f 74 20 65 78 69 73 74 73 28 70 61 74 68   not exists(path
1eae0 29 20 6f 72 20 6d 74 69 6d 65 28 70 61 74 68 29  ) or mtime(path)
1eaf0 20 3e 20 6c 6d 74 69 6d 65 3a 0a 20 20 20 20 20   > lmtime:.     
1eb00 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
1eb10 65 6c 66 2e 73 74 61 74 75 73 20 3d 20 27 72 65  elf.status = 're
1eb20 6c 6f 61 64 27 0a 20 20 20 20 20 20 20 20 20 20  load'.          
1eb30 20 20 20 20 20 20 20 20 20 20 74 68 72 65 61 64            thread
1eb40 2e 69 6e 74 65 72 72 75 70 74 5f 6d 61 69 6e 28  .interrupt_main(
1eb50 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
1eb60 20 20 20 20 20 20 62 72 65 61 6b 0a 20 20 20 20        break.    
1eb70 20 20 20 20 20 20 20 20 74 69 6d 65 2e 73 6c 65          time.sle
1eb80 65 70 28 73 65 6c 66 2e 69 6e 74 65 72 76 61 6c  ep(self.interval
1eb90 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 65 6e 74  )..    def __ent
1eba0 65 72 5f 5f 28 73 65 6c 66 29 3a 0a 20 20 20 20  er__(self):.    
1ebb0 20 20 20 20 73 65 6c 66 2e 73 74 61 72 74 28 29      self.start()
1ebc0 0a 0a 20 20 20 20 64 65 66 20 5f 5f 65 78 69 74  ..    def __exit
1ebd0 5f 5f 28 73 65 6c 66 2c 20 65 78 63 5f 74 79 70  __(self, exc_typ
1ebe0 65 2c 20 65 78 63 5f 76 61 6c 2c 20 65 78 63 5f  e, exc_val, exc_
1ebf0 74 62 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20  tb):.        if 
1ec00 6e 6f 74 20 73 65 6c 66 2e 73 74 61 74 75 73 3a  not self.status:
1ec10 20 73 65 6c 66 2e 73 74 61 74 75 73 20 3d 20 27   self.status = '
1ec20 65 78 69 74 27 20 23 20 73 69 6c 65 6e 74 20 65  exit' # silent e
1ec30 78 69 74 0a 20 20 20 20 20 20 20 20 73 65 6c 66  xit.        self
1ec40 2e 6a 6f 69 6e 28 29 0a 20 20 20 20 20 20 20 20  .join().        
1ec50 72 65 74 75 72 6e 20 65 78 63 5f 74 79 70 65 20  return exc_type 
1ec60 69 73 20 6e 6f 74 20 4e 6f 6e 65 20 61 6e 64 20  is not None and 
1ec70 69 73 73 75 62 63 6c 61 73 73 28 65 78 63 5f 74  issubclass(exc_t
1ec80 79 70 65 2c 20 4b 65 79 62 6f 61 72 64 49 6e 74  ype, KeyboardInt
1ec90 65 72 72 75 70 74 29 0a 0a 0a 0a 0a 0a 23 23 23  errupt)......###
1eca0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ecb0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ecc0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ecd0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ece0 23 23 23 23 23 23 23 23 23 23 23 23 0a 23 20 54  ############.# T
1ecf0 65 6d 70 6c 61 74 65 20 41 64 61 70 74 65 72 73  emplate Adapters
1ed00 20 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23   ###############
1ed10 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed20 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed30 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 23 23  #############.##
1ed40 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed50 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed60 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed70 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
1ed80 23 23 23 23 23 23 23 23 23 23 23 23 23 0a 0a 0a  #############...
1ed90 63 6c 61 73 73 20 54 65 6d 70 6c 61 74 65 45 72  class TemplateEr
1eda0 72 6f 72 28 48 54 54 50 45 72 72 6f 72 29 3a 0a  ror(HTTPError):.
1edb0 20 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f      def __init__
1edc0 28 73 65 6c 66 2c 20 6d 65 73 73 61 67 65 29 3a  (self, message):
1edd0 0a 20 20 20 20 20 20 20 20 48 54 54 50 45 72 72  .        HTTPErr
1ede0 6f 72 2e 5f 5f 69 6e 69 74 5f 5f 28 73 65 6c 66  or.__init__(self
1edf0 2c 20 35 30 30 2c 20 6d 65 73 73 61 67 65 29 0a  , 500, message).
1ee00 0a 0a 63 6c 61 73 73 20 42 61 73 65 54 65 6d 70  ..class BaseTemp
1ee10 6c 61 74 65 28 6f 62 6a 65 63 74 29 3a 0a 20 20  late(object):.  
1ee20 20 20 22 22 22 20 42 61 73 65 20 63 6c 61 73 73    """ Base class
1ee30 20 61 6e 64 20 6d 69 6e 69 6d 61 6c 20 41 50 49   and minimal API
1ee40 20 66 6f 72 20 74 65 6d 70 6c 61 74 65 20 61 64   for template ad
1ee50 61 70 74 65 72 73 20 22 22 22 0a 20 20 20 20 65  apters """.    e
1ee60 78 74 65 6e 73 69 6f 6e 73 20 3d 20 5b 27 74 70  xtensions = ['tp
1ee70 6c 27 2c 27 68 74 6d 6c 27 2c 27 74 68 74 6d 6c  l','html','thtml
1ee80 27 2c 27 73 74 70 6c 27 5d 0a 20 20 20 20 73 65  ','stpl'].    se
1ee90 74 74 69 6e 67 73 20 3d 20 7b 7d 20 23 75 73 65  ttings = {} #use
1eea0 64 20 69 6e 20 70 72 65 70 61 72 65 28 29 0a 20  d in prepare(). 
1eeb0 20 20 20 64 65 66 61 75 6c 74 73 20 3d 20 7b 7d     defaults = {}
1eec0 20 23 75 73 65 64 20 69 6e 20 72 65 6e 64 65 72   #used in render
1eed0 28 29 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e  ()..    def __in
1eee0 69 74 5f 5f 28 73 65 6c 66 2c 20 73 6f 75 72 63  it__(self, sourc
1eef0 65 3d 4e 6f 6e 65 2c 20 6e 61 6d 65 3d 4e 6f 6e  e=None, name=Non
1ef00 65 2c 20 6c 6f 6f 6b 75 70 3d 5b 5d 2c 20 65 6e  e, lookup=[], en
1ef10 63 6f 64 69 6e 67 3d 27 75 74 66 38 27 2c 20 2a  coding='utf8', *
1ef20 2a 73 65 74 74 69 6e 67 73 29 3a 0a 20 20 20 20  *settings):.    
1ef30 20 20 20 20 22 22 22 20 43 72 65 61 74 65 20 61      """ Create a
1ef40 20 6e 65 77 20 74 65 6d 70 6c 61 74 65 2e 0a 20   new template.. 
1ef50 20 20 20 20 20 20 20 49 66 20 74 68 65 20 73 6f         If the so
1ef60 75 72 63 65 20 70 61 72 61 6d 65 74 65 72 20 28  urce parameter (
1ef70 73 74 72 20 6f 72 20 62 75 66 66 65 72 29 20 69  str or buffer) i
1ef80 73 20 6d 69 73 73 69 6e 67 2c 20 74 68 65 20 6e  s missing, the n
1ef90 61 6d 65 20 61 72 67 75 6d 65 6e 74 0a 20 20 20  ame argument.   
1efa0 20 20 20 20 20 69 73 20 75 73 65 64 20 74 6f 20       is used to 
1efb0 67 75 65 73 73 20 61 20 74 65 6d 70 6c 61 74 65  guess a template
1efc0 20 66 69 6c 65 6e 61 6d 65 2e 20 53 75 62 63 6c   filename. Subcl
1efd0 61 73 73 65 73 20 63 61 6e 20 61 73 73 75 6d 65  asses can assume
1efe0 20 74 68 61 74 0a 20 20 20 20 20 20 20 20 73 65   that.        se
1eff0 6c 66 2e 73 6f 75 72 63 65 20 61 6e 64 2f 6f 72  lf.source and/or
1f000 20 73 65 6c 66 2e 66 69 6c 65 6e 61 6d 65 20 61   self.filename a
1f010 72 65 20 73 65 74 2e 20 42 6f 74 68 20 61 72 65  re set. Both are
1f020 20 73 74 72 69 6e 67 73 2e 0a 20 20 20 20 20 20   strings..      
1f030 20 20 54 68 65 20 6c 6f 6f 6b 75 70 2c 20 65 6e    The lookup, en
1f040 63 6f 64 69 6e 67 20 61 6e 64 20 73 65 74 74 69  coding and setti
1f050 6e 67 73 20 70 61 72 61 6d 65 74 65 72 73 20 61  ngs parameters a
1f060 72 65 20 73 74 6f 72 65 64 20 61 73 20 69 6e 73  re stored as ins
1f070 74 61 6e 63 65 0a 20 20 20 20 20 20 20 20 76 61  tance.        va
1f080 72 69 61 62 6c 65 73 2e 0a 20 20 20 20 20 20 20  riables..       
1f090 20 54 68 65 20 6c 6f 6f 6b 75 70 20 70 61 72 61   The lookup para
1f0a0 6d 65 74 65 72 20 73 74 6f 72 65 73 20 61 20 6c  meter stores a l
1f0b0 69 73 74 20 63 6f 6e 74 61 69 6e 69 6e 67 20 64  ist containing d
1f0c0 69 72 65 63 74 6f 72 79 20 70 61 74 68 73 2e 0a  irectory paths..
1f0d0 20 20 20 20 20 20 20 20 54 68 65 20 65 6e 63 6f          The enco
1f0e0 64 69 6e 67 20 70 61 72 61 6d 65 74 65 72 20 73  ding parameter s
1f0f0 68 6f 75 6c 64 20 62 65 20 75 73 65 64 20 74 6f  hould be used to
1f100 20 64 65 63 6f 64 65 20 62 79 74 65 20 73 74 72   decode byte str
1f110 69 6e 67 73 20 6f 72 20 66 69 6c 65 73 2e 0a 20  ings or files.. 
1f120 20 20 20 20 20 20 20 54 68 65 20 73 65 74 74 69         The setti
1f130 6e 67 73 20 70 61 72 61 6d 65 74 65 72 20 63 6f  ngs parameter co
1f140 6e 74 61 69 6e 73 20 61 20 64 69 63 74 20 66 6f  ntains a dict fo
1f150 72 20 65 6e 67 69 6e 65 2d 73 70 65 63 69 66 69  r engine-specifi
1f160 63 20 73 65 74 74 69 6e 67 73 2e 0a 20 20 20 20  c settings..    
1f170 20 20 20 20 22 22 22 0a 20 20 20 20 20 20 20 20      """.        
1f180 73 65 6c 66 2e 6e 61 6d 65 20 3d 20 6e 61 6d 65  self.name = name
1f190 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 6f  .        self.so
1f1a0 75 72 63 65 20 3d 20 73 6f 75 72 63 65 2e 72 65  urce = source.re
1f1b0 61 64 28 29 20 69 66 20 68 61 73 61 74 74 72 28  ad() if hasattr(
1f1c0 73 6f 75 72 63 65 2c 20 27 72 65 61 64 27 29 20  source, 'read') 
1f1d0 65 6c 73 65 20 73 6f 75 72 63 65 0a 20 20 20 20  else source.    
1f1e0 20 20 20 20 73 65 6c 66 2e 66 69 6c 65 6e 61 6d      self.filenam
1f1f0 65 20 3d 20 73 6f 75 72 63 65 2e 66 69 6c 65 6e  e = source.filen
1f200 61 6d 65 20 69 66 20 68 61 73 61 74 74 72 28 73  ame if hasattr(s
1f210 6f 75 72 63 65 2c 20 27 66 69 6c 65 6e 61 6d 65  ource, 'filename
1f220 27 29 20 65 6c 73 65 20 4e 6f 6e 65 0a 20 20 20  ') else None.   
1f230 20 20 20 20 20 73 65 6c 66 2e 6c 6f 6f 6b 75 70       self.lookup
1f240 20 3d 20 5b 6f 73 2e 70 61 74 68 2e 61 62 73 70   = [os.path.absp
1f250 61 74 68 28 78 29 20 66 6f 72 20 78 20 69 6e 20  ath(x) for x in 
1f260 6c 6f 6f 6b 75 70 5d 0a 20 20 20 20 20 20 20 20  lookup].        
1f270 73 65 6c 66 2e 65 6e 63 6f 64 69 6e 67 20 3d 20  self.encoding = 
1f280 65 6e 63 6f 64 69 6e 67 0a 20 20 20 20 20 20 20  encoding.       
1f290 20 73 65 6c 66 2e 73 65 74 74 69 6e 67 73 20 3d   self.settings =
1f2a0 20 73 65 6c 66 2e 73 65 74 74 69 6e 67 73 2e 63   self.settings.c
1f2b0 6f 70 79 28 29 20 23 20 43 6f 70 79 20 66 72 6f  opy() # Copy fro
1f2c0 6d 20 63 6c 61 73 73 20 76 61 72 69 61 62 6c 65  m class variable
1f2d0 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 65  .        self.se
1f2e0 74 74 69 6e 67 73 2e 75 70 64 61 74 65 28 73 65  ttings.update(se
1f2f0 74 74 69 6e 67 73 29 20 23 20 41 70 70 6c 79 0a  ttings) # Apply.
1f300 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73          if not s
1f310 65 6c 66 2e 73 6f 75 72 63 65 20 61 6e 64 20 73  elf.source and s
1f320 65 6c 66 2e 6e 61 6d 65 3a 0a 20 20 20 20 20 20  elf.name:.      
1f330 20 20 20 20 20 20 73 65 6c 66 2e 66 69 6c 65 6e        self.filen
1f340 61 6d 65 20 3d 20 73 65 6c 66 2e 73 65 61 72 63  ame = self.searc
1f350 68 28 73 65 6c 66 2e 6e 61 6d 65 2c 20 73 65 6c  h(self.name, sel
1f360 66 2e 6c 6f 6f 6b 75 70 29 0a 20 20 20 20 20 20  f.lookup).      
1f370 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73 65 6c        if not sel
1f380 66 2e 66 69 6c 65 6e 61 6d 65 3a 0a 20 20 20 20  f.filename:.    
1f390 20 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73              rais
1f3a0 65 20 54 65 6d 70 6c 61 74 65 45 72 72 6f 72 28  e TemplateError(
1f3b0 27 54 65 6d 70 6c 61 74 65 20 25 73 20 6e 6f 74  'Template %s not
1f3c0 20 66 6f 75 6e 64 2e 27 20 25 20 72 65 70 72 28   found.' % repr(
1f3d0 6e 61 6d 65 29 29 0a 20 20 20 20 20 20 20 20 69  name)).        i
1f3e0 66 20 6e 6f 74 20 73 65 6c 66 2e 73 6f 75 72 63  f not self.sourc
1f3f0 65 20 61 6e 64 20 6e 6f 74 20 73 65 6c 66 2e 66  e and not self.f
1f400 69 6c 65 6e 61 6d 65 3a 0a 20 20 20 20 20 20 20  ilename:.       
1f410 20 20 20 20 20 72 61 69 73 65 20 54 65 6d 70 6c       raise Templ
1f420 61 74 65 45 72 72 6f 72 28 27 4e 6f 20 74 65 6d  ateError('No tem
1f430 70 6c 61 74 65 20 73 70 65 63 69 66 69 65 64 2e  plate specified.
1f440 27 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  ').        self.
1f450 70 72 65 70 61 72 65 28 2a 2a 73 65 6c 66 2e 73  prepare(**self.s
1f460 65 74 74 69 6e 67 73 29 0a 0a 20 20 20 20 40 63  ettings)..    @c
1f470 6c 61 73 73 6d 65 74 68 6f 64 0a 20 20 20 20 64  lassmethod.    d
1f480 65 66 20 73 65 61 72 63 68 28 63 6c 73 2c 20 6e  ef search(cls, n
1f490 61 6d 65 2c 20 6c 6f 6f 6b 75 70 3d 5b 5d 29 3a  ame, lookup=[]):
1f4a0 0a 20 20 20 20 20 20 20 20 22 22 22 20 53 65 61  .        """ Sea
1f4b0 72 63 68 20 6e 61 6d 65 20 69 6e 20 61 6c 6c 20  rch name in all 
1f4c0 64 69 72 65 63 74 6f 72 69 65 73 20 73 70 65 63  directories spec
1f4d0 69 66 69 65 64 20 69 6e 20 6c 6f 6f 6b 75 70 2e  ified in lookup.
1f4e0 0a 20 20 20 20 20 20 20 20 46 69 72 73 74 20 77  .        First w
1f4f0 69 74 68 6f 75 74 2c 20 74 68 65 6e 20 77 69 74  ithout, then wit
1f500 68 20 63 6f 6d 6d 6f 6e 20 65 78 74 65 6e 73 69  h common extensi
1f510 6f 6e 73 2e 20 52 65 74 75 72 6e 20 66 69 72 73  ons. Return firs
1f520 74 20 68 69 74 2e 20 22 22 22 0a 20 20 20 20 20  t hit. """.     
1f530 20 20 20 69 66 20 6e 6f 74 20 6c 6f 6f 6b 75 70     if not lookup
1f540 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 65  :.            de
1f550 70 72 28 27 54 68 65 20 74 65 6d 70 6c 61 74 65  pr('The template
1f560 20 6c 6f 6f 6b 75 70 20 70 61 74 68 20 6c 69 73   lookup path lis
1f570 74 20 73 68 6f 75 6c 64 20 6e 6f 74 20 62 65 20  t should not be 
1f580 65 6d 70 74 79 2e 27 29 20 23 30 2e 31 32 0a 20  empty.') #0.12. 
1f590 20 20 20 20 20 20 20 20 20 20 20 6c 6f 6f 6b 75             looku
1f5a0 70 20 3d 20 5b 27 2e 27 5d 0a 0a 20 20 20 20 20  p = ['.']..     
1f5b0 20 20 20 69 66 20 6f 73 2e 70 61 74 68 2e 69 73     if os.path.is
1f5c0 61 62 73 28 6e 61 6d 65 29 20 61 6e 64 20 6f 73  abs(name) and os
1f5d0 2e 70 61 74 68 2e 69 73 66 69 6c 65 28 6e 61 6d  .path.isfile(nam
1f5e0 65 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  e):.            
1f5f0 64 65 70 72 28 27 41 62 73 6f 6c 75 74 65 20 74  depr('Absolute t
1f600 65 6d 70 6c 61 74 65 20 70 61 74 68 20 6e 61 6d  emplate path nam
1f610 65 73 20 61 72 65 20 64 65 70 72 65 63 61 74 65  es are deprecate
1f620 64 2e 27 29 20 23 30 2e 31 32 0a 20 20 20 20 20  d.') #0.12.     
1f630 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6f 73         return os
1f640 2e 70 61 74 68 2e 61 62 73 70 61 74 68 28 6e 61  .path.abspath(na
1f650 6d 65 29 0a 0a 20 20 20 20 20 20 20 20 66 6f 72  me)..        for
1f660 20 73 70 61 74 68 20 69 6e 20 6c 6f 6f 6b 75 70   spath in lookup
1f670 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 70  :.            sp
1f680 61 74 68 20 3d 20 6f 73 2e 70 61 74 68 2e 61 62  ath = os.path.ab
1f690 73 70 61 74 68 28 73 70 61 74 68 29 20 2b 20 6f  spath(spath) + o
1f6a0 73 2e 73 65 70 0a 20 20 20 20 20 20 20 20 20 20  s.sep.          
1f6b0 20 20 66 6e 61 6d 65 20 3d 20 6f 73 2e 70 61 74    fname = os.pat
1f6c0 68 2e 61 62 73 70 61 74 68 28 6f 73 2e 70 61 74  h.abspath(os.pat
1f6d0 68 2e 6a 6f 69 6e 28 73 70 61 74 68 2c 20 6e 61  h.join(spath, na
1f6e0 6d 65 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  me)).           
1f6f0 20 69 66 20 6e 6f 74 20 66 6e 61 6d 65 2e 73 74   if not fname.st
1f700 61 72 74 73 77 69 74 68 28 73 70 61 74 68 29 3a  artswith(spath):
1f710 20 63 6f 6e 74 69 6e 75 65 0a 20 20 20 20 20 20   continue.      
1f720 20 20 20 20 20 20 69 66 20 6f 73 2e 70 61 74 68        if os.path
1f730 2e 69 73 66 69 6c 65 28 66 6e 61 6d 65 29 3a 20  .isfile(fname): 
1f740 72 65 74 75 72 6e 20 66 6e 61 6d 65 0a 20 20 20  return fname.   
1f750 20 20 20 20 20 20 20 20 20 66 6f 72 20 65 78 74           for ext
1f760 20 69 6e 20 63 6c 73 2e 65 78 74 65 6e 73 69 6f   in cls.extensio
1f770 6e 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ns:.            
1f780 20 20 20 20 69 66 20 6f 73 2e 70 61 74 68 2e 69      if os.path.i
1f790 73 66 69 6c 65 28 27 25 73 2e 25 73 27 20 25 20  sfile('%s.%s' % 
1f7a0 28 66 6e 61 6d 65 2c 20 65 78 74 29 29 3a 0a 20  (fname, ext)):. 
1f7b0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f7c0 20 20 20 72 65 74 75 72 6e 20 27 25 73 2e 25 73     return '%s.%s
1f7d0 27 20 25 20 28 66 6e 61 6d 65 2c 20 65 78 74 29  ' % (fname, ext)
1f7e0 0a 0a 20 20 20 20 40 63 6c 61 73 73 6d 65 74 68  ..    @classmeth
1f7f0 6f 64 0a 20 20 20 20 64 65 66 20 67 6c 6f 62 61  od.    def globa
1f800 6c 5f 63 6f 6e 66 69 67 28 63 6c 73 2c 20 6b 65  l_config(cls, ke
1f810 79 2c 20 2a 61 72 67 73 29 3a 0a 20 20 20 20 20  y, *args):.     
1f820 20 20 20 27 27 27 20 54 68 69 73 20 72 65 61 64     ''' This read
1f830 73 20 6f 72 20 73 65 74 73 20 74 68 65 20 67 6c  s or sets the gl
1f840 6f 62 61 6c 20 73 65 74 74 69 6e 67 73 20 73 74  obal settings st
1f850 6f 72 65 64 20 69 6e 20 63 6c 61 73 73 2e 73 65  ored in class.se
1f860 74 74 69 6e 67 73 2e 20 27 27 27 0a 20 20 20 20  ttings. '''.    
1f870 20 20 20 20 69 66 20 61 72 67 73 3a 0a 20 20 20      if args:.   
1f880 20 20 20 20 20 20 20 20 20 63 6c 73 2e 73 65 74           cls.set
1f890 74 69 6e 67 73 20 3d 20 63 6c 73 2e 73 65 74 74  tings = cls.sett
1f8a0 69 6e 67 73 2e 63 6f 70 79 28 29 20 23 20 4d 61  ings.copy() # Ma
1f8b0 6b 65 20 73 65 74 74 69 6e 67 73 20 6c 6f 63 61  ke settings loca
1f8c0 6c 20 74 6f 20 63 6c 61 73 73 0a 20 20 20 20 20  l to class.     
1f8d0 20 20 20 20 20 20 20 63 6c 73 2e 73 65 74 74 69         cls.setti
1f8e0 6e 67 73 5b 6b 65 79 5d 20 3d 20 61 72 67 73 5b  ngs[key] = args[
1f8f0 30 5d 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a  0].        else:
1f900 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
1f910 75 72 6e 20 63 6c 73 2e 73 65 74 74 69 6e 67 73  urn cls.settings
1f920 5b 6b 65 79 5d 0a 0a 20 20 20 20 64 65 66 20 70  [key]..    def p
1f930 72 65 70 61 72 65 28 73 65 6c 66 2c 20 2a 2a 6f  repare(self, **o
1f940 70 74 69 6f 6e 73 29 3a 0a 20 20 20 20 20 20 20  ptions):.       
1f950 20 22 22 22 20 52 75 6e 20 70 72 65 70 61 72 61   """ Run prepara
1f960 74 69 6f 6e 73 20 28 70 61 72 73 69 6e 67 2c 20  tions (parsing, 
1f970 63 61 63 68 69 6e 67 2c 20 2e 2e 2e 29 2e 0a 20  caching, ...).. 
1f980 20 20 20 20 20 20 20 49 74 20 73 68 6f 75 6c 64         It should
1f990 20 62 65 20 70 6f 73 73 69 62 6c 65 20 74 6f 20   be possible to 
1f9a0 63 61 6c 6c 20 74 68 69 73 20 61 67 61 69 6e 20  call this again 
1f9b0 74 6f 20 72 65 66 72 65 73 68 20 61 20 74 65 6d  to refresh a tem
1f9c0 70 6c 61 74 65 20 6f 72 20 74 6f 0a 20 20 20 20  plate or to.    
1f9d0 20 20 20 20 75 70 64 61 74 65 20 73 65 74 74 69      update setti
1f9e0 6e 67 73 2e 0a 20 20 20 20 20 20 20 20 22 22 22  ngs..        """
1f9f0 0a 20 20 20 20 20 20 20 20 72 61 69 73 65 20 4e  .        raise N
1fa00 6f 74 49 6d 70 6c 65 6d 65 6e 74 65 64 45 72 72  otImplementedErr
1fa10 6f 72 0a 0a 20 20 20 20 64 65 66 20 72 65 6e 64  or..    def rend
1fa20 65 72 28 73 65 6c 66 2c 20 2a 61 72 67 73 2c 20  er(self, *args, 
1fa30 2a 2a 6b 77 61 72 67 73 29 3a 0a 20 20 20 20 20  **kwargs):.     
1fa40 20 20 20 22 22 22 20 52 65 6e 64 65 72 20 74 68     """ Render th
1fa50 65 20 74 65 6d 70 6c 61 74 65 20 77 69 74 68 20  e template with 
1fa60 74 68 65 20 73 70 65 63 69 66 69 65 64 20 6c 6f  the specified lo
1fa70 63 61 6c 20 76 61 72 69 61 62 6c 65 73 20 61 6e  cal variables an
1fa80 64 20 72 65 74 75 72 6e 0a 20 20 20 20 20 20 20  d return.       
1fa90 20 61 20 73 69 6e 67 6c 65 20 62 79 74 65 20 6f   a single byte o
1faa0 72 20 75 6e 69 63 6f 64 65 20 73 74 72 69 6e 67  r unicode string
1fab0 2e 20 49 66 20 69 74 20 69 73 20 61 20 62 79 74  . If it is a byt
1fac0 65 20 73 74 72 69 6e 67 2c 20 74 68 65 20 65 6e  e string, the en
1fad0 63 6f 64 69 6e 67 0a 20 20 20 20 20 20 20 20 6d  coding.        m
1fae0 75 73 74 20 6d 61 74 63 68 20 73 65 6c 66 2e 65  ust match self.e
1faf0 6e 63 6f 64 69 6e 67 2e 20 54 68 69 73 20 6d 65  ncoding. This me
1fb00 74 68 6f 64 20 6d 75 73 74 20 62 65 20 74 68 72  thod must be thr
1fb10 65 61 64 2d 73 61 66 65 21 0a 20 20 20 20 20 20  ead-safe!.      
1fb20 20 20 4c 6f 63 61 6c 20 76 61 72 69 61 62 6c 65    Local variable
1fb30 73 20 6d 61 79 20 62 65 20 70 72 6f 76 69 64 65  s may be provide
1fb40 64 20 69 6e 20 64 69 63 74 69 6f 6e 61 72 69 65  d in dictionarie
1fb50 73 20 28 61 72 67 73 29 0a 20 20 20 20 20 20 20  s (args).       
1fb60 20 6f 72 20 64 69 72 65 63 74 6c 79 2c 20 61 73   or directly, as
1fb70 20 6b 65 79 77 6f 72 64 73 20 28 6b 77 61 72 67   keywords (kwarg
1fb80 73 29 2e 0a 20 20 20 20 20 20 20 20 22 22 22 0a  s)..        """.
1fb90 20 20 20 20 20 20 20 20 72 61 69 73 65 20 4e 6f          raise No
1fba0 74 49 6d 70 6c 65 6d 65 6e 74 65 64 45 72 72 6f  tImplementedErro
1fbb0 72 0a 0a 0a 63 6c 61 73 73 20 4d 61 6b 6f 54 65  r...class MakoTe
1fbc0 6d 70 6c 61 74 65 28 42 61 73 65 54 65 6d 70 6c  mplate(BaseTempl
1fbd0 61 74 65 29 3a 0a 20 20 20 20 64 65 66 20 70 72  ate):.    def pr
1fbe0 65 70 61 72 65 28 73 65 6c 66 2c 20 2a 2a 6f 70  epare(self, **op
1fbf0 74 69 6f 6e 73 29 3a 0a 20 20 20 20 20 20 20 20  tions):.        
1fc00 66 72 6f 6d 20 6d 61 6b 6f 2e 74 65 6d 70 6c 61  from mako.templa
1fc10 74 65 20 69 6d 70 6f 72 74 20 54 65 6d 70 6c 61  te import Templa
1fc20 74 65 0a 20 20 20 20 20 20 20 20 66 72 6f 6d 20  te.        from 
1fc30 6d 61 6b 6f 2e 6c 6f 6f 6b 75 70 20 69 6d 70 6f  mako.lookup impo
1fc40 72 74 20 54 65 6d 70 6c 61 74 65 4c 6f 6f 6b 75  rt TemplateLooku
1fc50 70 0a 20 20 20 20 20 20 20 20 6f 70 74 69 6f 6e  p.        option
1fc60 73 2e 75 70 64 61 74 65 28 7b 27 69 6e 70 75 74  s.update({'input
1fc70 5f 65 6e 63 6f 64 69 6e 67 27 3a 73 65 6c 66 2e  _encoding':self.
1fc80 65 6e 63 6f 64 69 6e 67 7d 29 0a 20 20 20 20 20  encoding}).     
1fc90 20 20 20 6f 70 74 69 6f 6e 73 2e 73 65 74 64 65     options.setde
1fca0 66 61 75 6c 74 28 27 66 6f 72 6d 61 74 5f 65 78  fault('format_ex
1fcb0 63 65 70 74 69 6f 6e 73 27 2c 20 62 6f 6f 6c 28  ceptions', bool(
1fcc0 44 45 42 55 47 29 29 0a 20 20 20 20 20 20 20 20  DEBUG)).        
1fcd0 6c 6f 6f 6b 75 70 20 3d 20 54 65 6d 70 6c 61 74  lookup = Templat
1fce0 65 4c 6f 6f 6b 75 70 28 64 69 72 65 63 74 6f 72  eLookup(director
1fcf0 69 65 73 3d 73 65 6c 66 2e 6c 6f 6f 6b 75 70 2c  ies=self.lookup,
1fd00 20 2a 2a 6f 70 74 69 6f 6e 73 29 0a 20 20 20 20   **options).    
1fd10 20 20 20 20 69 66 20 73 65 6c 66 2e 73 6f 75 72      if self.sour
1fd20 63 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ce:.            
1fd30 73 65 6c 66 2e 74 70 6c 20 3d 20 54 65 6d 70 6c  self.tpl = Templ
1fd40 61 74 65 28 73 65 6c 66 2e 73 6f 75 72 63 65 2c  ate(self.source,
1fd50 20 6c 6f 6f 6b 75 70 3d 6c 6f 6f 6b 75 70 2c 20   lookup=lookup, 
1fd60 2a 2a 6f 70 74 69 6f 6e 73 29 0a 20 20 20 20 20  **options).     
1fd70 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20     else:.       
1fd80 20 20 20 20 20 73 65 6c 66 2e 74 70 6c 20 3d 20       self.tpl = 
1fd90 54 65 6d 70 6c 61 74 65 28 75 72 69 3d 73 65 6c  Template(uri=sel
1fda0 66 2e 6e 61 6d 65 2c 20 66 69 6c 65 6e 61 6d 65  f.name, filename
1fdb0 3d 73 65 6c 66 2e 66 69 6c 65 6e 61 6d 65 2c 20  =self.filename, 
1fdc0 6c 6f 6f 6b 75 70 3d 6c 6f 6f 6b 75 70 2c 20 2a  lookup=lookup, *
1fdd0 2a 6f 70 74 69 6f 6e 73 29 0a 0a 20 20 20 20 64  *options)..    d
1fde0 65 66 20 72 65 6e 64 65 72 28 73 65 6c 66 2c 20  ef render(self, 
1fdf0 2a 61 72 67 73 2c 20 2a 2a 6b 77 61 72 67 73 29  *args, **kwargs)
1fe00 3a 0a 20 20 20 20 20 20 20 20 66 6f 72 20 64 69  :.        for di
1fe10 63 74 61 72 67 20 69 6e 20 61 72 67 73 3a 20 6b  ctarg in args: k
1fe20 77 61 72 67 73 2e 75 70 64 61 74 65 28 64 69 63  wargs.update(dic
1fe30 74 61 72 67 29 0a 20 20 20 20 20 20 20 20 5f 64  targ).        _d
1fe40 65 66 61 75 6c 74 73 20 3d 20 73 65 6c 66 2e 64  efaults = self.d
1fe50 65 66 61 75 6c 74 73 2e 63 6f 70 79 28 29 0a 20  efaults.copy(). 
1fe60 20 20 20 20 20 20 20 5f 64 65 66 61 75 6c 74 73         _defaults
1fe70 2e 75 70 64 61 74 65 28 6b 77 61 72 67 73 29 0a  .update(kwargs).
1fe80 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73          return s
1fe90 65 6c 66 2e 74 70 6c 2e 72 65 6e 64 65 72 28 2a  elf.tpl.render(*
1fea0 2a 5f 64 65 66 61 75 6c 74 73 29 0a 0a 0a 63 6c  *_defaults)...cl
1feb0 61 73 73 20 43 68 65 65 74 61 68 54 65 6d 70 6c  ass CheetahTempl
1fec0 61 74 65 28 42 61 73 65 54 65 6d 70 6c 61 74 65  ate(BaseTemplate
1fed0 29 3a 0a 20 20 20 20 64 65 66 20 70 72 65 70 61  ):.    def prepa
1fee0 72 65 28 73 65 6c 66 2c 20 2a 2a 6f 70 74 69 6f  re(self, **optio
1fef0 6e 73 29 3a 0a 20 20 20 20 20 20 20 20 66 72 6f  ns):.        fro
1ff00 6d 20 43 68 65 65 74 61 68 2e 54 65 6d 70 6c 61  m Cheetah.Templa
1ff10 74 65 20 69 6d 70 6f 72 74 20 54 65 6d 70 6c 61  te import Templa
1ff20 74 65 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  te.        self.
1ff30 63 6f 6e 74 65 78 74 20 3d 20 74 68 72 65 61 64  context = thread
1ff40 69 6e 67 2e 6c 6f 63 61 6c 28 29 0a 20 20 20 20  ing.local().    
1ff50 20 20 20 20 73 65 6c 66 2e 63 6f 6e 74 65 78 74      self.context
1ff60 2e 76 61 72 73 20 3d 20 7b 7d 0a 20 20 20 20 20  .vars = {}.     
1ff70 20 20 20 6f 70 74 69 6f 6e 73 5b 27 73 65 61 72     options['sear
1ff80 63 68 4c 69 73 74 27 5d 20 3d 20 5b 73 65 6c 66  chList'] = [self
1ff90 2e 63 6f 6e 74 65 78 74 2e 76 61 72 73 5d 0a 20  .context.vars]. 
1ffa0 20 20 20 20 20 20 20 69 66 20 73 65 6c 66 2e 73         if self.s
1ffb0 6f 75 72 63 65 3a 0a 20 20 20 20 20 20 20 20 20  ource:.         
1ffc0 20 20 20 73 65 6c 66 2e 74 70 6c 20 3d 20 54 65     self.tpl = Te
1ffd0 6d 70 6c 61 74 65 28 73 6f 75 72 63 65 3d 73 65  mplate(source=se
1ffe0 6c 66 2e 73 6f 75 72 63 65 2c 20 2a 2a 6f 70 74  lf.source, **opt
1fff0 69 6f 6e 73 29 0a 20 20 20 20 20 20 20 20 65 6c  ions).        el
20000 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
20010 73 65 6c 66 2e 74 70 6c 20 3d 20 54 65 6d 70 6c  self.tpl = Templ
20020 61 74 65 28 66 69 6c 65 3d 73 65 6c 66 2e 66 69  ate(file=self.fi
20030 6c 65 6e 61 6d 65 2c 20 2a 2a 6f 70 74 69 6f 6e  lename, **option
20040 73 29 0a 0a 20 20 20 20 64 65 66 20 72 65 6e 64  s)..    def rend
20050 65 72 28 73 65 6c 66 2c 20 2a 61 72 67 73 2c 20  er(self, *args, 
20060 2a 2a 6b 77 61 72 67 73 29 3a 0a 20 20 20 20 20  **kwargs):.     
20070 20 20 20 66 6f 72 20 64 69 63 74 61 72 67 20 69     for dictarg i
20080 6e 20 61 72 67 73 3a 20 6b 77 61 72 67 73 2e 75  n args: kwargs.u
20090 70 64 61 74 65 28 64 69 63 74 61 72 67 29 0a 20  pdate(dictarg). 
200a0 20 20 20 20 20 20 20 73 65 6c 66 2e 63 6f 6e 74         self.cont
200b0 65 78 74 2e 76 61 72 73 2e 75 70 64 61 74 65 28  ext.vars.update(
200c0 73 65 6c 66 2e 64 65 66 61 75 6c 74 73 29 0a 20  self.defaults). 
200d0 20 20 20 20 20 20 20 73 65 6c 66 2e 63 6f 6e 74         self.cont
200e0 65 78 74 2e 76 61 72 73 2e 75 70 64 61 74 65 28  ext.vars.update(
200f0 6b 77 61 72 67 73 29 0a 20 20 20 20 20 20 20 20  kwargs).        
20100 6f 75 74 20 3d 20 73 74 72 28 73 65 6c 66 2e 74  out = str(self.t
20110 70 6c 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  pl).        self
20120 2e 63 6f 6e 74 65 78 74 2e 76 61 72 73 2e 63 6c  .context.vars.cl
20130 65 61 72 28 29 0a 20 20 20 20 20 20 20 20 72 65  ear().        re
20140 74 75 72 6e 20 6f 75 74 0a 0a 0a 63 6c 61 73 73  turn out...class
20150 20 4a 69 6e 6a 61 32 54 65 6d 70 6c 61 74 65 28   Jinja2Template(
20160 42 61 73 65 54 65 6d 70 6c 61 74 65 29 3a 0a 20  BaseTemplate):. 
20170 20 20 20 64 65 66 20 70 72 65 70 61 72 65 28 73     def prepare(s
20180 65 6c 66 2c 20 66 69 6c 74 65 72 73 3d 4e 6f 6e  elf, filters=Non
20190 65 2c 20 74 65 73 74 73 3d 4e 6f 6e 65 2c 20 67  e, tests=None, g
201a0 6c 6f 62 61 6c 73 3d 7b 7d 2c 20 2a 2a 6b 77 61  lobals={}, **kwa
201b0 72 67 73 29 3a 0a 20 20 20 20 20 20 20 20 66 72  rgs):.        fr
201c0 6f 6d 20 6a 69 6e 6a 61 32 20 69 6d 70 6f 72 74  om jinja2 import
201d0 20 45 6e 76 69 72 6f 6e 6d 65 6e 74 2c 20 46 75   Environment, Fu
201e0 6e 63 74 69 6f 6e 4c 6f 61 64 65 72 0a 20 20 20  nctionLoader.   
201f0 20 20 20 20 20 69 66 20 27 70 72 65 66 69 78 27       if 'prefix'
20200 20 69 6e 20 6b 77 61 72 67 73 3a 20 23 20 54 4f   in kwargs: # TO
20210 44 4f 3a 20 74 6f 20 62 65 20 72 65 6d 6f 76 65  DO: to be remove
20220 64 20 61 66 74 65 72 20 61 20 77 68 69 6c 65 0a  d after a while.
20230 20 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73              rais
20240 65 20 52 75 6e 74 69 6d 65 45 72 72 6f 72 28 27  e RuntimeError('
20250 54 68 65 20 6b 65 79 77 6f 72 64 20 61 72 67 75  The keyword argu
20260 6d 65 6e 74 20 60 70 72 65 66 69 78 60 20 68 61  ment `prefix` ha
20270 73 20 62 65 65 6e 20 72 65 6d 6f 76 65 64 2e 20  s been removed. 
20280 27 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  '.              
20290 20 20 27 55 73 65 20 74 68 65 20 66 75 6c 6c 20    'Use the full 
202a0 6a 69 6e 6a 61 32 20 65 6e 76 69 72 6f 6e 6d 65  jinja2 environme
202b0 6e 74 20 6e 61 6d 65 20 6c 69 6e 65 5f 73 74 61  nt name line_sta
202c0 74 65 6d 65 6e 74 5f 70 72 65 66 69 78 20 69 6e  tement_prefix in
202d0 73 74 65 61 64 2e 27 29 0a 20 20 20 20 20 20 20  stead.').       
202e0 20 73 65 6c 66 2e 65 6e 76 20 3d 20 45 6e 76 69   self.env = Envi
202f0 72 6f 6e 6d 65 6e 74 28 6c 6f 61 64 65 72 3d 46  ronment(loader=F
20300 75 6e 63 74 69 6f 6e 4c 6f 61 64 65 72 28 73 65  unctionLoader(se
20310 6c 66 2e 6c 6f 61 64 65 72 29 2c 20 2a 2a 6b 77  lf.loader), **kw
20320 61 72 67 73 29 0a 20 20 20 20 20 20 20 20 69 66  args).        if
20330 20 66 69 6c 74 65 72 73 3a 20 73 65 6c 66 2e 65   filters: self.e
20340 6e 76 2e 66 69 6c 74 65 72 73 2e 75 70 64 61 74  nv.filters.updat
20350 65 28 66 69 6c 74 65 72 73 29 0a 20 20 20 20 20  e(filters).     
20360 20 20 20 69 66 20 74 65 73 74 73 3a 20 73 65 6c     if tests: sel
20370 66 2e 65 6e 76 2e 74 65 73 74 73 2e 75 70 64 61  f.env.tests.upda
20380 74 65 28 74 65 73 74 73 29 0a 20 20 20 20 20 20  te(tests).      
20390 20 20 69 66 20 67 6c 6f 62 61 6c 73 3a 20 73 65    if globals: se
203a0 6c 66 2e 65 6e 76 2e 67 6c 6f 62 61 6c 73 2e 75  lf.env.globals.u
203b0 70 64 61 74 65 28 67 6c 6f 62 61 6c 73 29 0a 20  pdate(globals). 
203c0 20 20 20 20 20 20 20 69 66 20 73 65 6c 66 2e 73         if self.s
203d0 6f 75 72 63 65 3a 0a 20 20 20 20 20 20 20 20 20  ource:.         
203e0 20 20 20 73 65 6c 66 2e 74 70 6c 20 3d 20 73 65     self.tpl = se
203f0 6c 66 2e 65 6e 76 2e 66 72 6f 6d 5f 73 74 72 69  lf.env.from_stri
20400 6e 67 28 73 65 6c 66 2e 73 6f 75 72 63 65 29 0a  ng(self.source).
20410 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
20420 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 74            self.t
20430 70 6c 20 3d 20 73 65 6c 66 2e 65 6e 76 2e 67 65  pl = self.env.ge
20440 74 5f 74 65 6d 70 6c 61 74 65 28 73 65 6c 66 2e  t_template(self.
20450 66 69 6c 65 6e 61 6d 65 29 0a 0a 20 20 20 20 64  filename)..    d
20460 65 66 20 72 65 6e 64 65 72 28 73 65 6c 66 2c 20  ef render(self, 
20470 2a 61 72 67 73 2c 20 2a 2a 6b 77 61 72 67 73 29  *args, **kwargs)
20480 3a 0a 20 20 20 20 20 20 20 20 66 6f 72 20 64 69  :.        for di
20490 63 74 61 72 67 20 69 6e 20 61 72 67 73 3a 20 6b  ctarg in args: k
204a0 77 61 72 67 73 2e 75 70 64 61 74 65 28 64 69 63  wargs.update(dic
204b0 74 61 72 67 29 0a 20 20 20 20 20 20 20 20 5f 64  targ).        _d
204c0 65 66 61 75 6c 74 73 20 3d 20 73 65 6c 66 2e 64  efaults = self.d
204d0 65 66 61 75 6c 74 73 2e 63 6f 70 79 28 29 0a 20  efaults.copy(). 
204e0 20 20 20 20 20 20 20 5f 64 65 66 61 75 6c 74 73         _defaults
204f0 2e 75 70 64 61 74 65 28 6b 77 61 72 67 73 29 0a  .update(kwargs).
20500 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73          return s
20510 65 6c 66 2e 74 70 6c 2e 72 65 6e 64 65 72 28 2a  elf.tpl.render(*
20520 2a 5f 64 65 66 61 75 6c 74 73 29 0a 0a 20 20 20  *_defaults)..   
20530 20 64 65 66 20 6c 6f 61 64 65 72 28 73 65 6c 66   def loader(self
20540 2c 20 6e 61 6d 65 29 3a 0a 20 20 20 20 20 20 20  , name):.       
20550 20 66 6e 61 6d 65 20 3d 20 73 65 6c 66 2e 73 65   fname = self.se
20560 61 72 63 68 28 6e 61 6d 65 2c 20 73 65 6c 66 2e  arch(name, self.
20570 6c 6f 6f 6b 75 70 29 0a 20 20 20 20 20 20 20 20  lookup).        
20580 69 66 20 6e 6f 74 20 66 6e 61 6d 65 3a 20 72 65  if not fname: re
20590 74 75 72 6e 0a 20 20 20 20 20 20 20 20 77 69 74  turn.        wit
205a0 68 20 6f 70 65 6e 28 66 6e 61 6d 65 2c 20 22 72  h open(fname, "r
205b0 62 22 29 20 61 73 20 66 3a 0a 20 20 20 20 20 20  b") as f:.      
205c0 20 20 20 20 20 20 72 65 74 75 72 6e 20 66 2e 72        return f.r
205d0 65 61 64 28 29 2e 64 65 63 6f 64 65 28 73 65 6c  ead().decode(sel
205e0 66 2e 65 6e 63 6f 64 69 6e 67 29 0a 0a 0a 63 6c  f.encoding)...cl
205f0 61 73 73 20 53 69 6d 70 6c 65 54 65 6d 70 6c 61  ass SimpleTempla
20600 74 65 28 42 61 73 65 54 65 6d 70 6c 61 74 65 29  te(BaseTemplate)
20610 3a 0a 0a 20 20 20 20 64 65 66 20 70 72 65 70 61  :..    def prepa
20620 72 65 28 73 65 6c 66 2c 20 65 73 63 61 70 65 5f  re(self, escape_
20630 66 75 6e 63 3d 68 74 6d 6c 5f 65 73 63 61 70 65  func=html_escape
20640 2c 20 6e 6f 65 73 63 61 70 65 3d 46 61 6c 73 65  , noescape=False
20650 2c 20 73 79 6e 74 61 78 3d 4e 6f 6e 65 2c 20 2a  , syntax=None, *
20660 2a 6b 61 29 3a 0a 20 20 20 20 20 20 20 20 73 65  *ka):.        se
20670 6c 66 2e 63 61 63 68 65 20 3d 20 7b 7d 0a 20 20  lf.cache = {}.  
20680 20 20 20 20 20 20 65 6e 63 20 3d 20 73 65 6c 66        enc = self
20690 2e 65 6e 63 6f 64 69 6e 67 0a 20 20 20 20 20 20  .encoding.      
206a0 20 20 73 65 6c 66 2e 5f 73 74 72 20 3d 20 6c 61    self._str = la
206b0 6d 62 64 61 20 78 3a 20 74 6f 75 6e 69 28 78 2c  mbda x: touni(x,
206c0 20 65 6e 63 29 0a 20 20 20 20 20 20 20 20 73 65   enc).        se
206d0 6c 66 2e 5f 65 73 63 61 70 65 20 3d 20 6c 61 6d  lf._escape = lam
206e0 62 64 61 20 78 3a 20 65 73 63 61 70 65 5f 66 75  bda x: escape_fu
206f0 6e 63 28 74 6f 75 6e 69 28 78 2c 20 65 6e 63 29  nc(touni(x, enc)
20700 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73  ).        self.s
20710 79 6e 74 61 78 20 3d 20 73 79 6e 74 61 78 0a 20  yntax = syntax. 
20720 20 20 20 20 20 20 20 69 66 20 6e 6f 65 73 63 61         if noesca
20730 70 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  pe:.            
20740 73 65 6c 66 2e 5f 73 74 72 2c 20 73 65 6c 66 2e  self._str, self.
20750 5f 65 73 63 61 70 65 20 3d 20 73 65 6c 66 2e 5f  _escape = self._
20760 65 73 63 61 70 65 2c 20 73 65 6c 66 2e 5f 73 74  escape, self._st
20770 72 0a 0a 20 20 20 20 40 63 61 63 68 65 64 5f 70  r..    @cached_p
20780 72 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20  roperty.    def 
20790 63 6f 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20  co(self):.      
207a0 20 20 72 65 74 75 72 6e 20 63 6f 6d 70 69 6c 65    return compile
207b0 28 73 65 6c 66 2e 63 6f 64 65 2c 20 73 65 6c 66  (self.code, self
207c0 2e 66 69 6c 65 6e 61 6d 65 20 6f 72 20 27 3c 73  .filename or '<s
207d0 74 72 69 6e 67 3e 27 2c 20 27 65 78 65 63 27 29  tring>', 'exec')
207e0 0a 0a 20 20 20 20 40 63 61 63 68 65 64 5f 70 72  ..    @cached_pr
207f0 6f 70 65 72 74 79 0a 20 20 20 20 64 65 66 20 63  operty.    def c
20800 6f 64 65 28 73 65 6c 66 29 3a 0a 20 20 20 20 20  ode(self):.     
20810 20 20 20 73 6f 75 72 63 65 20 3d 20 73 65 6c 66     source = self
20820 2e 73 6f 75 72 63 65 0a 20 20 20 20 20 20 20 20  .source.        
20830 69 66 20 6e 6f 74 20 73 6f 75 72 63 65 3a 0a 20  if not source:. 
20840 20 20 20 20 20 20 20 20 20 20 20 77 69 74 68 20             with 
20850 6f 70 65 6e 28 73 65 6c 66 2e 66 69 6c 65 6e 61  open(self.filena
20860 6d 65 2c 20 27 72 62 27 29 20 61 73 20 66 3a 0a  me, 'rb') as f:.
20870 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
20880 73 6f 75 72 63 65 20 3d 20 66 2e 72 65 61 64 28  source = f.read(
20890 29 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20  ).        try:. 
208a0 20 20 20 20 20 20 20 20 20 20 20 73 6f 75 72 63             sourc
208b0 65 2c 20 65 6e 63 6f 64 69 6e 67 20 3d 20 74 6f  e, encoding = to
208c0 75 6e 69 28 73 6f 75 72 63 65 29 2c 20 27 75 74  uni(source), 'ut
208d0 66 38 27 0a 20 20 20 20 20 20 20 20 65 78 63 65  f8'.        exce
208e0 70 74 20 55 6e 69 63 6f 64 65 45 72 72 6f 72 3a  pt UnicodeError:
208f0 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 65 70  .            dep
20900 72 28 27 54 65 6d 70 6c 61 74 65 20 65 6e 63 6f  r('Template enco
20910 64 69 6e 67 73 20 6f 74 68 65 72 20 74 68 61 6e  dings other than
20920 20 75 74 66 38 20 61 72 65 20 6e 6f 20 6c 6f 6e   utf8 are no lon
20930 67 65 72 20 73 75 70 70 6f 72 74 65 64 2e 27 29  ger supported.')
20940 20 23 30 2e 31 31 0a 20 20 20 20 20 20 20 20 20   #0.11.         
20950 20 20 20 73 6f 75 72 63 65 2c 20 65 6e 63 6f 64     source, encod
20960 69 6e 67 20 3d 20 74 6f 75 6e 69 28 73 6f 75 72  ing = touni(sour
20970 63 65 2c 20 27 6c 61 74 69 6e 31 27 29 2c 20 27  ce, 'latin1'), '
20980 6c 61 74 69 6e 31 27 0a 20 20 20 20 20 20 20 20  latin1'.        
20990 70 61 72 73 65 72 20 3d 20 53 74 70 6c 50 61 72  parser = StplPar
209a0 73 65 72 28 73 6f 75 72 63 65 2c 20 65 6e 63 6f  ser(source, enco
209b0 64 69 6e 67 3d 65 6e 63 6f 64 69 6e 67 2c 20 73  ding=encoding, s
209c0 79 6e 74 61 78 3d 73 65 6c 66 2e 73 79 6e 74 61  yntax=self.synta
209d0 78 29 0a 20 20 20 20 20 20 20 20 63 6f 64 65 20  x).        code 
209e0 3d 20 70 61 72 73 65 72 2e 74 72 61 6e 73 6c 61  = parser.transla
209f0 74 65 28 29 0a 20 20 20 20 20 20 20 20 73 65 6c  te().        sel
20a00 66 2e 65 6e 63 6f 64 69 6e 67 20 3d 20 70 61 72  f.encoding = par
20a10 73 65 72 2e 65 6e 63 6f 64 69 6e 67 0a 20 20 20  ser.encoding.   
20a20 20 20 20 20 20 72 65 74 75 72 6e 20 63 6f 64 65       return code
20a30 0a 0a 20 20 20 20 64 65 66 20 5f 72 65 62 61 73  ..    def _rebas
20a40 65 28 73 65 6c 66 2c 20 5f 65 6e 76 2c 20 5f 6e  e(self, _env, _n
20a50 61 6d 65 3d 4e 6f 6e 65 2c 20 2a 2a 6b 77 61 72  ame=None, **kwar
20a60 67 73 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20  gs):.        if 
20a70 5f 6e 61 6d 65 20 69 73 20 4e 6f 6e 65 3a 0a 20  _name is None:. 
20a80 20 20 20 20 20 20 20 20 20 20 20 64 65 70 72 28             depr(
20a90 27 52 65 62 61 73 65 20 66 75 6e 63 74 69 6f 6e  'Rebase function
20aa0 20 63 61 6c 6c 65 64 20 77 69 74 68 6f 75 74 20   called without 
20ab0 61 72 67 75 6d 65 6e 74 73 2e 27 0a 20 20 20 20  arguments.'.    
20ac0 20 20 20 20 20 20 20 20 20 20 20 20 20 27 20 59               ' Y
20ad0 6f 75 20 77 65 72 65 20 70 72 6f 62 61 62 6c 79  ou were probably
20ae0 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 7b 7b 62   looking for {{b
20af0 61 73 65 7d 7d 3f 27 2c 20 54 72 75 65 29 20 23  ase}}?', True) #
20b00 30 2e 31 32 0a 20 20 20 20 20 20 20 20 5f 65 6e  0.12.        _en
20b10 76 5b 27 5f 72 65 62 61 73 65 27 5d 20 3d 20 28  v['_rebase'] = (
20b20 5f 6e 61 6d 65 2c 20 6b 77 61 72 67 73 29 0a 0a  _name, kwargs)..
20b30 20 20 20 20 64 65 66 20 5f 69 6e 63 6c 75 64 65      def _include
20b40 28 73 65 6c 66 2c 20 5f 65 6e 76 2c 20 5f 6e 61  (self, _env, _na
20b50 6d 65 3d 4e 6f 6e 65 2c 20 2a 2a 6b 77 61 72 67  me=None, **kwarg
20b60 73 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 5f  s):.        if _
20b70 6e 61 6d 65 20 69 73 20 4e 6f 6e 65 3a 0a 20 20  name is None:.  
20b80 20 20 20 20 20 20 20 20 20 20 64 65 70 72 28 27            depr('
20b90 52 65 62 61 73 65 20 66 75 6e 63 74 69 6f 6e 20  Rebase function 
20ba0 63 61 6c 6c 65 64 20 77 69 74 68 6f 75 74 20 61  called without a
20bb0 72 67 75 6d 65 6e 74 73 2e 27 0a 20 20 20 20 20  rguments.'.     
20bc0 20 20 20 20 20 20 20 20 20 20 20 20 27 20 59 6f              ' Yo
20bd0 75 20 77 65 72 65 20 70 72 6f 62 61 62 6c 79 20  u were probably 
20be0 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 7b 7b 62 61  looking for {{ba
20bf0 73 65 7d 7d 3f 27 2c 20 54 72 75 65 29 20 23 30  se}}?', True) #0
20c00 2e 31 32 0a 20 20 20 20 20 20 20 20 65 6e 76 20  .12.        env 
20c10 3d 20 5f 65 6e 76 2e 63 6f 70 79 28 29 0a 20 20  = _env.copy().  
20c20 20 20 20 20 20 20 65 6e 76 2e 75 70 64 61 74 65        env.update
20c30 28 6b 77 61 72 67 73 29 0a 20 20 20 20 20 20 20  (kwargs).       
20c40 20 69 66 20 5f 6e 61 6d 65 20 6e 6f 74 20 69 6e   if _name not in
20c50 20 73 65 6c 66 2e 63 61 63 68 65 3a 0a 20 20 20   self.cache:.   
20c60 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 63 61           self.ca
20c70 63 68 65 5b 5f 6e 61 6d 65 5d 20 3d 20 73 65 6c  che[_name] = sel
20c80 66 2e 5f 5f 63 6c 61 73 73 5f 5f 28 6e 61 6d 65  f.__class__(name
20c90 3d 5f 6e 61 6d 65 2c 20 6c 6f 6f 6b 75 70 3d 73  =_name, lookup=s
20ca0 65 6c 66 2e 6c 6f 6f 6b 75 70 29 0a 20 20 20 20  elf.lookup).    
20cb0 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e      return self.
20cc0 63 61 63 68 65 5b 5f 6e 61 6d 65 5d 2e 65 78 65  cache[_name].exe
20cd0 63 75 74 65 28 65 6e 76 5b 27 5f 73 74 64 6f 75  cute(env['_stdou
20ce0 74 27 5d 2c 20 65 6e 76 29 0a 0a 20 20 20 20 64  t'], env)..    d
20cf0 65 66 20 65 78 65 63 75 74 65 28 73 65 6c 66 2c  ef execute(self,
20d00 20 5f 73 74 64 6f 75 74 2c 20 6b 77 61 72 67 73   _stdout, kwargs
20d10 29 3a 0a 20 20 20 20 20 20 20 20 65 6e 76 20 3d  ):.        env =
20d20 20 73 65 6c 66 2e 64 65 66 61 75 6c 74 73 2e 63   self.defaults.c
20d30 6f 70 79 28 29 0a 20 20 20 20 20 20 20 20 65 6e  opy().        en
20d40 76 2e 75 70 64 61 74 65 28 6b 77 61 72 67 73 29  v.update(kwargs)
20d50 0a 20 20 20 20 20 20 20 20 65 6e 76 2e 75 70 64  .        env.upd
20d60 61 74 65 28 7b 27 5f 73 74 64 6f 75 74 27 3a 20  ate({'_stdout': 
20d70 5f 73 74 64 6f 75 74 2c 20 27 5f 70 72 69 6e 74  _stdout, '_print
20d80 6c 69 73 74 27 3a 20 5f 73 74 64 6f 75 74 2e 65  list': _stdout.e
20d90 78 74 65 6e 64 2c 0a 20 20 20 20 20 20 20 20 20  xtend,.         
20da0 20 20 20 27 69 6e 63 6c 75 64 65 27 3a 20 66 75     'include': fu
20db0 6e 63 74 6f 6f 6c 73 2e 70 61 72 74 69 61 6c 28  nctools.partial(
20dc0 73 65 6c 66 2e 5f 69 6e 63 6c 75 64 65 2c 20 65  self._include, e
20dd0 6e 76 29 2c 0a 20 20 20 20 20 20 20 20 20 20 20  nv),.           
20de0 20 27 72 65 62 61 73 65 27 3a 20 66 75 6e 63 74   'rebase': funct
20df0 6f 6f 6c 73 2e 70 61 72 74 69 61 6c 28 73 65 6c  ools.partial(sel
20e00 66 2e 5f 72 65 62 61 73 65 2c 20 65 6e 76 29 2c  f._rebase, env),
20e10 20 27 5f 72 65 62 61 73 65 27 3a 20 4e 6f 6e 65   '_rebase': None
20e20 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 27 5f  ,.            '_
20e30 73 74 72 27 3a 20 73 65 6c 66 2e 5f 73 74 72 2c  str': self._str,
20e40 20 27 5f 65 73 63 61 70 65 27 3a 20 73 65 6c 66   '_escape': self
20e50 2e 5f 65 73 63 61 70 65 2c 20 27 67 65 74 27 3a  ._escape, 'get':
20e60 20 65 6e 76 2e 67 65 74 2c 0a 20 20 20 20 20 20   env.get,.      
20e70 20 20 20 20 20 20 27 73 65 74 64 65 66 61 75 6c        'setdefaul
20e80 74 27 3a 20 65 6e 76 2e 73 65 74 64 65 66 61 75  t': env.setdefau
20e90 6c 74 2c 20 27 64 65 66 69 6e 65 64 27 3a 20 65  lt, 'defined': e
20ea0 6e 76 2e 5f 5f 63 6f 6e 74 61 69 6e 73 5f 5f 20  nv.__contains__ 
20eb0 7d 29 0a 20 20 20 20 20 20 20 20 65 76 61 6c 28  }).        eval(
20ec0 73 65 6c 66 2e 63 6f 2c 20 65 6e 76 29 0a 20 20  self.co, env).  
20ed0 20 20 20 20 20 20 69 66 20 65 6e 76 2e 67 65 74        if env.get
20ee0 28 27 5f 72 65 62 61 73 65 27 29 3a 0a 20 20 20  ('_rebase'):.   
20ef0 20 20 20 20 20 20 20 20 20 73 75 62 74 70 6c 2c           subtpl,
20f00 20 72 61 72 67 73 20 3d 20 65 6e 76 2e 70 6f 70   rargs = env.pop
20f10 28 27 5f 72 65 62 61 73 65 27 29 0a 20 20 20 20  ('_rebase').    
20f20 20 20 20 20 20 20 20 20 72 61 72 67 73 5b 27 62          rargs['b
20f30 61 73 65 27 5d 20 3d 20 27 27 2e 6a 6f 69 6e 28  ase'] = ''.join(
20f40 5f 73 74 64 6f 75 74 29 20 23 63 6f 70 79 20 73  _stdout) #copy s
20f50 74 64 6f 75 74 0a 20 20 20 20 20 20 20 20 20 20  tdout.          
20f60 20 20 64 65 6c 20 5f 73 74 64 6f 75 74 5b 3a 5d    del _stdout[:]
20f70 20 23 20 63 6c 65 61 72 20 73 74 64 6f 75 74 0a   # clear stdout.
20f80 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
20f90 72 6e 20 73 65 6c 66 2e 5f 69 6e 63 6c 75 64 65  rn self._include
20fa0 28 65 6e 76 2c 20 73 75 62 74 70 6c 2c 20 2a 2a  (env, subtpl, **
20fb0 72 61 72 67 73 29 0a 20 20 20 20 20 20 20 20 72  rargs).        r
20fc0 65 74 75 72 6e 20 65 6e 76 0a 0a 20 20 20 20 64  eturn env..    d
20fd0 65 66 20 72 65 6e 64 65 72 28 73 65 6c 66 2c 20  ef render(self, 
20fe0 2a 61 72 67 73 2c 20 2a 2a 6b 77 61 72 67 73 29  *args, **kwargs)
20ff0 3a 0a 20 20 20 20 20 20 20 20 22 22 22 20 52 65  :.        """ Re
21000 6e 64 65 72 20 74 68 65 20 74 65 6d 70 6c 61 74  nder the templat
21010 65 20 75 73 69 6e 67 20 6b 65 79 77 6f 72 64 20  e using keyword 
21020 61 72 67 75 6d 65 6e 74 73 20 61 73 20 6c 6f 63  arguments as loc
21030 61 6c 20 76 61 72 69 61 62 6c 65 73 2e 20 22 22  al variables. ""
21040 22 0a 20 20 20 20 20 20 20 20 65 6e 76 20 3d 20  ".        env = 
21050 7b 7d 3b 20 73 74 64 6f 75 74 20 3d 20 5b 5d 0a  {}; stdout = [].
21060 20 20 20 20 20 20 20 20 66 6f 72 20 64 69 63 74          for dict
21070 61 72 67 20 69 6e 20 61 72 67 73 3a 20 65 6e 76  arg in args: env
21080 2e 75 70 64 61 74 65 28 64 69 63 74 61 72 67 29  .update(dictarg)
21090 0a 20 20 20 20 20 20 20 20 65 6e 76 2e 75 70 64  .        env.upd
210a0 61 74 65 28 6b 77 61 72 67 73 29 0a 20 20 20 20  ate(kwargs).    
210b0 20 20 20 20 73 65 6c 66 2e 65 78 65 63 75 74 65      self.execute
210c0 28 73 74 64 6f 75 74 2c 20 65 6e 76 29 0a 20 20  (stdout, env).  
210d0 20 20 20 20 20 20 72 65 74 75 72 6e 20 27 27 2e        return ''.
210e0 6a 6f 69 6e 28 73 74 64 6f 75 74 29 0a 0a 0a 63  join(stdout)...c
210f0 6c 61 73 73 20 53 74 70 6c 53 79 6e 74 61 78 45  lass StplSyntaxE
21100 72 72 6f 72 28 54 65 6d 70 6c 61 74 65 45 72 72  rror(TemplateErr
21110 6f 72 29 3a 20 70 61 73 73 0a 0a 0a 63 6c 61 73  or): pass...clas
21120 73 20 53 74 70 6c 50 61 72 73 65 72 28 6f 62 6a  s StplParser(obj
21130 65 63 74 29 3a 0a 20 20 20 20 27 27 27 20 50 61  ect):.    ''' Pa
21140 72 73 65 72 20 66 6f 72 20 73 74 70 6c 20 74 65  rser for stpl te
21150 6d 70 6c 61 74 65 73 2e 20 27 27 27 0a 20 20 20  mplates. '''.   
21160 20 5f 72 65 5f 63 61 63 68 65 20 3d 20 7b 7d 20   _re_cache = {} 
21170 23 3a 20 43 61 63 68 65 20 66 6f 72 20 63 6f 6d  #: Cache for com
21180 70 69 6c 65 64 20 72 65 20 70 61 74 74 65 72 6e  piled re pattern
21190 73 0a 20 20 20 20 23 20 54 68 69 73 20 68 75 67  s.    # This hug
211a0 65 20 70 69 6c 65 20 6f 66 20 76 6f 6f 64 6f 6f  e pile of voodoo
211b0 20 6d 61 67 69 63 20 73 70 6c 69 74 73 20 70 79   magic splits py
211c0 74 68 6f 6e 20 63 6f 64 65 20 69 6e 74 6f 20 38  thon code into 8
211d0 20 64 69 66 66 65 72 65 6e 74 20 74 6f 6b 65 6e   different token
211e0 73 2e 0a 20 20 20 20 23 20 31 3a 20 41 6c 6c 20  s..    # 1: All 
211f0 6b 69 6e 64 73 20 6f 66 20 70 79 74 68 6f 6e 20  kinds of python 
21200 73 74 72 69 6e 67 73 20 28 74 72 75 73 74 20 6d  strings (trust m
21210 65 2c 20 69 74 20 77 6f 72 6b 73 29 0a 20 20 20  e, it works).   
21220 20 5f 72 65 5f 74 6f 6b 20 3d 20 27 28 28 3f 6d   _re_tok = '((?m
21230 29 5b 75 72 62 55 52 42 5d 3f 28 3f 3a 5c 27 5c  )[urbURB]?(?:\'\
21240 27 28 3f 21 5c 27 29 7c 22 22 28 3f 21 22 29 7c  '(?!\')|""(?!")|
21250 5c 27 7b 36 7d 7c 22 7b 36 7d 27 20 5c 0a 20 20  \'{6}|"{6}' \.  
21260 20 20 20 20 20 20 20 20 20 20 20 20 20 27 7c 5c               '|\
21270 27 28 3f 3a 5b 5e 5c 5c 5c 5c 5c 27 5d 7c 5c 5c  '(?:[^\\\\\']|\\
21280 5c 5c 2e 29 2b 3f 5c 27 7c 22 28 3f 3a 5b 5e 5c  \\.)+?\'|"(?:[^\
21290 5c 5c 5c 22 5d 7c 5c 5c 5c 5c 2e 29 2b 3f 22 27  \\\"]|\\\\.)+?"'
212a0 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   \.             
212b0 20 20 27 7c 5c 27 7b 33 7d 28 3f 3a 5b 5e 5c 5c    '|\'{3}(?:[^\\
212c0 5c 5c 5d 7c 5c 5c 5c 5c 2e 7c 5c 5c 6e 29 2b 3f  \\]|\\\\.|\\n)+?
212d0 5c 27 7b 33 7d 27 20 5c 0a 20 20 20 20 20 20 20  \'{3}' \.       
212e0 20 20 20 20 20 20 20 20 27 7c 22 7b 33 7d 28 3f          '|"{3}(?
212f0 3a 5b 5e 5c 5c 5c 5c 5d 7c 5c 5c 5c 5c 2e 7c 5c  :[^\\\\]|\\\\.|\
21300 5c 6e 29 2b 3f 22 7b 33 7d 29 29 27 0a 20 20 20  \n)+?"{3}))'.   
21310 20 5f 72 65 5f 69 6e 6c 20 3d 20 5f 72 65 5f 74   _re_inl = _re_t
21320 6f 6b 2e 72 65 70 6c 61 63 65 28 27 7c 5c 5c 6e  ok.replace('|\\n
21330 27 2c 27 27 29 20 23 20 57 65 20 72 65 2d 75 73  ','') # We re-us
21340 65 20 74 68 69 73 20 73 74 72 69 6e 67 20 70 61  e this string pa
21350 74 74 65 72 6e 20 6c 61 74 65 72 0a 20 20 20 20  ttern later.    
21360 23 20 32 3a 20 43 6f 6d 6d 65 6e 74 73 20 28 75  # 2: Comments (u
21370 6e 74 69 6c 20 65 6e 64 20 6f 66 20 6c 69 6e 65  ntil end of line
21380 2c 20 62 75 74 20 6e 6f 74 20 74 68 65 20 6e 65  , but not the ne
21390 77 6c 69 6e 65 20 69 74 73 65 6c 66 29 0a 20 20  wline itself).  
213a0 20 20 5f 72 65 5f 74 6f 6b 20 2b 3d 20 27 7c 28    _re_tok += '|(
213b0 23 2e 2a 29 27 0a 20 20 20 20 23 20 33 2c 34 3a  #.*)'.    # 3,4:
213c0 20 4f 70 65 6e 20 61 6e 64 20 63 6c 6f 73 65 20   Open and close 
213d0 67 72 6f 75 70 69 6e 67 20 74 6f 6b 65 6e 73 0a  grouping tokens.
213e0 20 20 20 20 5f 72 65 5f 74 6f 6b 20 2b 3d 20 27      _re_tok += '
213f0 7c 28 5b 5c 5b 5c 7b 5c 28 5d 29 27 0a 20 20 20  |([\[\{\(])'.   
21400 20 5f 72 65 5f 74 6f 6b 20 2b 3d 20 27 7c 28 5b   _re_tok += '|([
21410 5c 5d 5c 7d 5c 29 5d 29 27 0a 20 20 20 20 23 20  \]\}\)])'.    # 
21420 35 2c 36 3a 20 4b 65 79 77 6f 72 64 73 20 74 68  5,6: Keywords th
21430 61 74 20 73 74 61 72 74 20 6f 72 20 63 6f 6e 74  at start or cont
21440 69 6e 75 65 20 61 20 70 79 74 68 6f 6e 20 62 6c  inue a python bl
21450 6f 63 6b 20 28 6f 6e 6c 79 20 73 74 61 72 74 20  ock (only start 
21460 6f 66 20 6c 69 6e 65 29 0a 20 20 20 20 5f 72 65  of line).    _re
21470 5f 74 6f 6b 20 2b 3d 20 27 7c 5e 28 5b 20 5c 5c  _tok += '|^([ \\
21480 74 5d 2a 28 3f 3a 69 66 7c 66 6f 72 7c 77 68 69  t]*(?:if|for|whi
21490 6c 65 7c 77 69 74 68 7c 74 72 79 7c 64 65 66 7c  le|with|try|def|
214a0 63 6c 61 73 73 29 5c 5c 62 29 27 20 5c 0a 20 20  class)\\b)' \.  
214b0 20 20 20 20 20 20 20 20 20 20 20 20 20 27 7c 5e               '|^
214c0 28 5b 20 5c 5c 74 5d 2a 28 3f 3a 65 6c 69 66 7c  ([ \\t]*(?:elif|
214d0 65 6c 73 65 7c 65 78 63 65 70 74 7c 66 69 6e 61  else|except|fina
214e0 6c 6c 79 29 5c 5c 62 29 27 0a 20 20 20 20 23 20  lly)\\b)'.    # 
214f0 37 3a 20 4f 75 72 20 73 70 65 63 69 61 6c 20 27  7: Our special '
21500 65 6e 64 27 20 6b 65 79 77 6f 72 64 20 28 62 75  end' keyword (bu
21510 74 20 6f 6e 6c 79 20 69 66 20 69 74 20 73 74 61  t only if it sta
21520 6e 64 73 20 61 6c 6f 6e 65 29 0a 20 20 20 20 5f  nds alone).    _
21530 72 65 5f 74 6f 6b 20 2b 3d 20 27 7c 28 28 3f 3a  re_tok += '|((?:
21540 5e 7c 3b 29 5b 20 5c 5c 74 5d 2a 65 6e 64 5b 20  ^|;)[ \\t]*end[ 
21550 5c 5c 74 5d 2a 28 3f 3d 28 3f 3a 25 28 62 6c 6f  \\t]*(?=(?:%(blo
21560 63 6b 5f 63 6c 6f 73 65 29 73 5b 20 5c 5c 74 5d  ck_close)s[ \\t]
21570 2a 29 3f 5c 5c 72 3f 24 7c 3b 7c 23 29 29 27 0a  *)?\\r?$|;|#))'.
21580 20 20 20 20 23 20 38 3a 20 41 20 63 75 73 74 6f      # 8: A custo
21590 6d 69 7a 61 62 6c 65 20 65 6e 64 2d 6f 66 2d 63  mizable end-of-c
215a0 6f 64 65 2d 62 6c 6f 63 6b 20 74 65 6d 70 6c 61  ode-block templa
215b0 74 65 20 74 6f 6b 65 6e 20 28 6f 6e 6c 79 20 65  te token (only e
215c0 6e 64 20 6f 66 20 6c 69 6e 65 29 0a 20 20 20 20  nd of line).    
215d0 5f 72 65 5f 74 6f 6b 20 2b 3d 20 27 7c 28 25 28  _re_tok += '|(%(
215e0 62 6c 6f 63 6b 5f 63 6c 6f 73 65 29 73 5b 20 5c  block_close)s[ \
215f0 5c 74 5d 2a 28 3f 3d 5c 5c 72 3f 24 29 29 27 0a  \t]*(?=\\r?$))'.
21600 20 20 20 20 23 20 39 3a 20 41 6e 64 20 66 69 6e      # 9: And fin
21610 61 6c 6c 79 2c 20 61 20 73 69 6e 67 6c 65 20 6e  ally, a single n
21620 65 77 6c 69 6e 65 2e 20 54 68 65 20 31 30 74 68  ewline. The 10th
21630 20 74 6f 6b 65 6e 20 69 73 20 27 65 76 65 72 79   token is 'every
21640 74 68 69 6e 67 20 65 6c 73 65 27 0a 20 20 20 20  thing else'.    
21650 5f 72 65 5f 74 6f 6b 20 2b 3d 20 27 7c 28 5c 5c  _re_tok += '|(\\
21660 72 3f 5c 5c 6e 29 27 0a 0a 20 20 20 20 23 20 4d  r?\\n)'..    # M
21670 61 74 63 68 20 74 68 65 20 73 74 61 72 74 20 74  atch the start t
21680 6f 6b 65 6e 73 20 6f 66 20 63 6f 64 65 20 61 72  okens of code ar
21690 65 61 73 20 69 6e 20 61 20 74 65 6d 70 6c 61 74  eas in a templat
216a0 65 0a 20 20 20 20 5f 72 65 5f 73 70 6c 69 74 20  e.    _re_split 
216b0 3d 20 27 28 3f 6d 29 5e 5b 20 5c 74 5d 2a 28 5c  = '(?m)^[ \t]*(\
216c0 5c 5c 5c 3f 29 28 28 25 28 6c 69 6e 65 5f 73 74  \\\?)((%(line_st
216d0 61 72 74 29 73 29 7c 28 25 28 62 6c 6f 63 6b 5f  art)s)|(%(block_
216e0 73 74 61 72 74 29 73 29 29 28 25 25 3f 29 27 0a  start)s))(%%?)'.
216f0 20 20 20 20 23 20 4d 61 74 63 68 20 69 6e 6c 69      # Match inli
21700 6e 65 20 73 74 61 74 65 6d 65 6e 74 73 20 28 6d  ne statements (m
21710 61 79 20 63 6f 6e 74 61 69 6e 20 70 79 74 68 6f  ay contain pytho
21720 6e 20 73 74 72 69 6e 67 73 29 0a 20 20 20 20 5f  n strings).    _
21730 72 65 5f 69 6e 6c 20 3d 20 27 25 25 28 69 6e 6c  re_inl = '%%(inl
21740 69 6e 65 5f 73 74 61 72 74 29 73 28 28 3f 3a 25  ine_start)s((?:%
21750 73 7c 5b 5e 5c 27 22 5c 6e 5d 2a 3f 29 2b 29 25  s|[^\'"\n]*?)+)%
21760 25 28 69 6e 6c 69 6e 65 5f 65 6e 64 29 73 27 20  %(inline_end)s' 
21770 25 20 5f 72 65 5f 69 6e 6c 0a 0a 20 20 20 20 64  % _re_inl..    d
21780 65 66 61 75 6c 74 5f 73 79 6e 74 61 78 20 3d 20  efault_syntax = 
21790 27 3c 25 20 25 3e 20 25 20 7b 7b 20 7d 7d 27 0a  '<% %> % {{ }}'.
217a0 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f  .    def __init_
217b0 5f 28 73 65 6c 66 2c 20 73 6f 75 72 63 65 2c 20  _(self, source, 
217c0 73 79 6e 74 61 78 3d 4e 6f 6e 65 2c 20 65 6e 63  syntax=None, enc
217d0 6f 64 69 6e 67 3d 27 75 74 66 38 27 29 3a 0a 20  oding='utf8'):. 
217e0 20 20 20 20 20 20 20 73 65 6c 66 2e 73 6f 75 72         self.sour
217f0 63 65 2c 20 73 65 6c 66 2e 65 6e 63 6f 64 69 6e  ce, self.encodin
21800 67 20 3d 20 74 6f 75 6e 69 28 73 6f 75 72 63 65  g = touni(source
21810 2c 20 65 6e 63 6f 64 69 6e 67 29 2c 20 65 6e 63  , encoding), enc
21820 6f 64 69 6e 67 0a 20 20 20 20 20 20 20 20 73 65  oding.        se
21830 6c 66 2e 73 65 74 5f 73 79 6e 74 61 78 28 73 79  lf.set_syntax(sy
21840 6e 74 61 78 20 6f 72 20 73 65 6c 66 2e 64 65 66  ntax or self.def
21850 61 75 6c 74 5f 73 79 6e 74 61 78 29 0a 20 20 20  ault_syntax).   
21860 20 20 20 20 20 73 65 6c 66 2e 63 6f 64 65 5f 62       self.code_b
21870 75 66 66 65 72 2c 20 73 65 6c 66 2e 74 65 78 74  uffer, self.text
21880 5f 62 75 66 66 65 72 20 3d 20 5b 5d 2c 20 5b 5d  _buffer = [], []
21890 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 69  .        self.li
218a0 6e 65 6e 6f 2c 20 73 65 6c 66 2e 6f 66 66 73 65  neno, self.offse
218b0 74 20 3d 20 31 2c 20 30 0a 20 20 20 20 20 20 20  t = 1, 0.       
218c0 20 73 65 6c 66 2e 69 6e 64 65 6e 74 2c 20 73 65   self.indent, se
218d0 6c 66 2e 69 6e 64 65 6e 74 5f 6d 6f 64 20 3d 20  lf.indent_mod = 
218e0 30 2c 20 30 0a 20 20 20 20 20 20 20 20 73 65 6c  0, 0.        sel
218f0 66 2e 70 61 72 65 6e 5f 64 65 70 74 68 20 3d 20  f.paren_depth = 
21900 30 0a 0a 20 20 20 20 64 65 66 20 67 65 74 5f 73  0..    def get_s
21910 79 6e 74 61 78 28 73 65 6c 66 29 3a 0a 20 20 20  yntax(self):.   
21920 20 20 20 20 20 27 27 27 20 54 6f 6b 65 6e 73 20       ''' Tokens 
21930 61 73 20 61 20 73 70 61 63 65 20 73 65 70 61 72  as a space separ
21940 61 74 65 64 20 73 74 72 69 6e 67 20 28 64 65 66  ated string (def
21950 61 75 6c 74 3a 20 3c 25 20 25 3e 20 25 20 7b 7b  ault: <% %> % {{
21960 20 7d 7d 29 20 27 27 27 0a 20 20 20 20 20 20 20   }}) '''.       
21970 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f 73 79   return self._sy
21980 6e 74 61 78 0a 0a 20 20 20 20 64 65 66 20 73 65  ntax..    def se
21990 74 5f 73 79 6e 74 61 78 28 73 65 6c 66 2c 20 73  t_syntax(self, s
219a0 79 6e 74 61 78 29 3a 0a 20 20 20 20 20 20 20 20  yntax):.        
219b0 73 65 6c 66 2e 5f 73 79 6e 74 61 78 20 3d 20 73  self._syntax = s
219c0 79 6e 74 61 78 0a 20 20 20 20 20 20 20 20 73 65  yntax.        se
219d0 6c 66 2e 5f 74 6f 6b 65 6e 73 20 3d 20 73 79 6e  lf._tokens = syn
219e0 74 61 78 2e 73 70 6c 69 74 28 29 0a 20 20 20 20  tax.split().    
219f0 20 20 20 20 69 66 20 6e 6f 74 20 73 79 6e 74 61      if not synta
21a00 78 20 69 6e 20 73 65 6c 66 2e 5f 72 65 5f 63 61  x in self._re_ca
21a10 63 68 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  che:.           
21a20 20 6e 61 6d 65 73 20 3d 20 27 62 6c 6f 63 6b 5f   names = 'block_
21a30 73 74 61 72 74 20 62 6c 6f 63 6b 5f 63 6c 6f 73  start block_clos
21a40 65 20 6c 69 6e 65 5f 73 74 61 72 74 20 69 6e 6c  e line_start inl
21a50 69 6e 65 5f 73 74 61 72 74 20 69 6e 6c 69 6e 65  ine_start inline
21a60 5f 65 6e 64 27 0a 20 20 20 20 20 20 20 20 20 20  _end'.          
21a70 20 20 65 74 6f 6b 65 6e 73 20 3d 20 6d 61 70 28    etokens = map(
21a80 72 65 2e 65 73 63 61 70 65 2c 20 73 65 6c 66 2e  re.escape, self.
21a90 5f 74 6f 6b 65 6e 73 29 0a 20 20 20 20 20 20 20  _tokens).       
21aa0 20 20 20 20 20 70 61 74 74 65 72 6e 5f 76 61 72       pattern_var
21ab0 73 20 3d 20 64 69 63 74 28 7a 69 70 28 6e 61 6d  s = dict(zip(nam
21ac0 65 73 2e 73 70 6c 69 74 28 29 2c 20 65 74 6f 6b  es.split(), etok
21ad0 65 6e 73 29 29 0a 20 20 20 20 20 20 20 20 20 20  ens)).          
21ae0 20 20 70 61 74 74 65 72 6e 73 20 3d 20 28 73 65    patterns = (se
21af0 6c 66 2e 5f 72 65 5f 73 70 6c 69 74 2c 20 73 65  lf._re_split, se
21b00 6c 66 2e 5f 72 65 5f 74 6f 6b 2c 20 73 65 6c 66  lf._re_tok, self
21b10 2e 5f 72 65 5f 69 6e 6c 29 0a 20 20 20 20 20 20  ._re_inl).      
21b20 20 20 20 20 20 20 70 61 74 74 65 72 6e 73 20 3d        patterns =
21b30 20 5b 72 65 2e 63 6f 6d 70 69 6c 65 28 70 25 70   [re.compile(p%p
21b40 61 74 74 65 72 6e 5f 76 61 72 73 29 20 66 6f 72  attern_vars) for
21b50 20 70 20 69 6e 20 70 61 74 74 65 72 6e 73 5d 0a   p in patterns].
21b60 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
21b70 2e 5f 72 65 5f 63 61 63 68 65 5b 73 79 6e 74 61  ._re_cache[synta
21b80 78 5d 20 3d 20 70 61 74 74 65 72 6e 73 0a 20 20  x] = patterns.  
21b90 20 20 20 20 20 20 73 65 6c 66 2e 72 65 5f 73 70        self.re_sp
21ba0 6c 69 74 2c 20 73 65 6c 66 2e 72 65 5f 74 6f 6b  lit, self.re_tok
21bb0 2c 20 73 65 6c 66 2e 72 65 5f 69 6e 6c 20 3d 20  , self.re_inl = 
21bc0 73 65 6c 66 2e 5f 72 65 5f 63 61 63 68 65 5b 73  self._re_cache[s
21bd0 79 6e 74 61 78 5d 0a 0a 20 20 20 20 73 79 6e 74  yntax]..    synt
21be0 61 78 20 3d 20 70 72 6f 70 65 72 74 79 28 67 65  ax = property(ge
21bf0 74 5f 73 79 6e 74 61 78 2c 20 73 65 74 5f 73 79  t_syntax, set_sy
21c00 6e 74 61 78 29 0a 0a 20 20 20 20 64 65 66 20 74  ntax)..    def t
21c10 72 61 6e 73 6c 61 74 65 28 73 65 6c 66 29 3a 0a  ranslate(self):.
21c20 20 20 20 20 20 20 20 20 69 66 20 73 65 6c 66 2e          if self.
21c30 6f 66 66 73 65 74 3a 20 72 61 69 73 65 20 52 75  offset: raise Ru
21c40 6e 74 69 6d 65 45 72 72 6f 72 28 27 50 61 72 73  ntimeError('Pars
21c50 65 72 20 69 73 20 61 20 6f 6e 65 20 74 69 6d 65  er is a one time
21c60 20 69 6e 73 74 61 6e 63 65 2e 27 29 0a 20 20 20   instance.').   
21c70 20 20 20 20 20 77 68 69 6c 65 20 54 72 75 65 3a       while True:
21c80 0a 20 20 20 20 20 20 20 20 20 20 20 20 6d 20 3d  .            m =
21c90 20 73 65 6c 66 2e 72 65 5f 73 70 6c 69 74 2e 73   self.re_split.s
21ca0 65 61 72 63 68 28 73 65 6c 66 2e 73 6f 75 72 63  earch(self.sourc
21cb0 65 5b 73 65 6c 66 2e 6f 66 66 73 65 74 3a 5d 29  e[self.offset:])
21cc0 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
21cd0 6d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  m:.             
21ce0 20 20 20 74 65 78 74 20 3d 20 73 65 6c 66 2e 73     text = self.s
21cf0 6f 75 72 63 65 5b 73 65 6c 66 2e 6f 66 66 73 65  ource[self.offse
21d00 74 3a 73 65 6c 66 2e 6f 66 66 73 65 74 2b 6d 2e  t:self.offset+m.
21d10 73 74 61 72 74 28 29 5d 0a 20 20 20 20 20 20 20  start()].       
21d20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 74 65           self.te
21d30 78 74 5f 62 75 66 66 65 72 2e 61 70 70 65 6e 64  xt_buffer.append
21d40 28 74 65 78 74 29 0a 20 20 20 20 20 20 20 20 20  (text).         
21d50 20 20 20 20 20 20 20 73 65 6c 66 2e 6f 66 66 73         self.offs
21d60 65 74 20 2b 3d 20 6d 2e 65 6e 64 28 29 0a 20 20  et += m.end().  
21d70 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
21d80 20 6d 2e 67 72 6f 75 70 28 31 29 3a 20 23 20 4e   m.group(1): # N
21d90 65 77 20 65 73 63 61 70 65 20 73 79 6e 74 61 78  ew escape syntax
21da0 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
21db0 20 20 20 20 20 6c 69 6e 65 2c 20 73 65 70 2c 20       line, sep, 
21dc0 5f 20 3d 20 73 65 6c 66 2e 73 6f 75 72 63 65 5b  _ = self.source[
21dd0 73 65 6c 66 2e 6f 66 66 73 65 74 3a 5d 2e 70 61  self.offset:].pa
21de0 72 74 69 74 69 6f 6e 28 27 5c 6e 27 29 0a 20 20  rtition('\n').  
21df0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21e00 20 20 73 65 6c 66 2e 74 65 78 74 5f 62 75 66 66    self.text_buff
21e10 65 72 2e 61 70 70 65 6e 64 28 6d 2e 67 72 6f 75  er.append(m.grou
21e20 70 28 32 29 2b 6d 2e 67 72 6f 75 70 28 35 29 2b  p(2)+m.group(5)+
21e30 6c 69 6e 65 2b 73 65 70 29 0a 20 20 20 20 20 20  line+sep).      
21e40 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
21e50 6c 66 2e 6f 66 66 73 65 74 20 2b 3d 20 6c 65 6e  lf.offset += len
21e60 28 6c 69 6e 65 2b 73 65 70 29 2b 31 0a 20 20 20  (line+sep)+1.   
21e70 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21e80 20 63 6f 6e 74 69 6e 75 65 0a 20 20 20 20 20 20   continue.      
21e90 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 6d            elif m
21ea0 2e 67 72 6f 75 70 28 35 29 3a 20 23 20 4f 6c 64  .group(5): # Old
21eb0 20 65 73 63 61 70 65 20 73 79 6e 74 61 78 0a 20   escape syntax. 
21ec0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21ed0 20 20 20 64 65 70 72 28 27 45 73 63 61 70 65 20     depr('Escape 
21ee0 63 6f 64 65 20 6c 69 6e 65 73 20 77 69 74 68 20  code lines with 
21ef0 61 20 62 61 63 6b 73 6c 61 73 68 2e 27 29 20 23  a backslash.') #
21f00 30 2e 31 32 0a 20 20 20 20 20 20 20 20 20 20 20  0.12.           
21f10 20 20 20 20 20 20 20 20 20 6c 69 6e 65 2c 20 73           line, s
21f20 65 70 2c 20 5f 20 3d 20 73 65 6c 66 2e 73 6f 75  ep, _ = self.sou
21f30 72 63 65 5b 73 65 6c 66 2e 6f 66 66 73 65 74 3a  rce[self.offset:
21f40 5d 2e 70 61 72 74 69 74 69 6f 6e 28 27 5c 6e 27  ].partition('\n'
21f50 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
21f60 20 20 20 20 20 20 73 65 6c 66 2e 74 65 78 74 5f        self.text_
21f70 62 75 66 66 65 72 2e 61 70 70 65 6e 64 28 6d 2e  buffer.append(m.
21f80 67 72 6f 75 70 28 32 29 2b 6c 69 6e 65 2b 73 65  group(2)+line+se
21f90 70 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  p).             
21fa0 20 20 20 20 20 20 20 73 65 6c 66 2e 6f 66 66 73         self.offs
21fb0 65 74 20 2b 3d 20 6c 65 6e 28 6c 69 6e 65 2b 73  et += len(line+s
21fc0 65 70 29 2b 31 0a 20 20 20 20 20 20 20 20 20 20  ep)+1.          
21fd0 20 20 20 20 20 20 20 20 20 20 63 6f 6e 74 69 6e            contin
21fe0 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ue.             
21ff0 20 20 20 73 65 6c 66 2e 66 6c 75 73 68 5f 74 65     self.flush_te
22000 78 74 28 29 0a 20 20 20 20 20 20 20 20 20 20 20  xt().           
22010 20 20 20 20 20 73 65 6c 66 2e 72 65 61 64 5f 63       self.read_c
22020 6f 64 65 28 6d 75 6c 74 69 6c 69 6e 65 3d 62 6f  ode(multiline=bo
22030 6f 6c 28 6d 2e 67 72 6f 75 70 28 34 29 29 29 0a  ol(m.group(4))).
22040 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
22050 3a 20 62 72 65 61 6b 0a 20 20 20 20 20 20 20 20  : break.        
22060 73 65 6c 66 2e 74 65 78 74 5f 62 75 66 66 65 72  self.text_buffer
22070 2e 61 70 70 65 6e 64 28 73 65 6c 66 2e 73 6f 75  .append(self.sou
22080 72 63 65 5b 73 65 6c 66 2e 6f 66 66 73 65 74 3a  rce[self.offset:
22090 5d 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  ]).        self.
220a0 66 6c 75 73 68 5f 74 65 78 74 28 29 0a 20 20 20  flush_text().   
220b0 20 20 20 20 20 72 65 74 75 72 6e 20 27 27 2e 6a       return ''.j
220c0 6f 69 6e 28 73 65 6c 66 2e 63 6f 64 65 5f 62 75  oin(self.code_bu
220d0 66 66 65 72 29 0a 0a 20 20 20 20 64 65 66 20 72  ffer)..    def r
220e0 65 61 64 5f 63 6f 64 65 28 73 65 6c 66 2c 20 6d  ead_code(self, m
220f0 75 6c 74 69 6c 69 6e 65 29 3a 0a 20 20 20 20 20  ultiline):.     
22100 20 20 20 63 6f 64 65 5f 6c 69 6e 65 2c 20 63 6f     code_line, co
22110 6d 6d 65 6e 74 20 3d 20 27 27 2c 20 27 27 0a 20  mment = '', ''. 
22120 20 20 20 20 20 20 20 77 68 69 6c 65 20 54 72 75         while Tru
22130 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6d  e:.            m
22140 20 3d 20 73 65 6c 66 2e 72 65 5f 74 6f 6b 2e 73   = self.re_tok.s
22150 65 61 72 63 68 28 73 65 6c 66 2e 73 6f 75 72 63  earch(self.sourc
22160 65 5b 73 65 6c 66 2e 6f 66 66 73 65 74 3a 5d 29  e[self.offset:])
22170 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
22180 6e 6f 74 20 6d 3a 0a 20 20 20 20 20 20 20 20 20  not m:.         
22190 20 20 20 20 20 20 20 63 6f 64 65 5f 6c 69 6e 65         code_line
221a0 20 2b 3d 20 73 65 6c 66 2e 73 6f 75 72 63 65 5b   += self.source[
221b0 73 65 6c 66 2e 6f 66 66 73 65 74 3a 5d 0a 20 20  self.offset:].  
221c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
221d0 6c 66 2e 6f 66 66 73 65 74 20 3d 20 6c 65 6e 28  lf.offset = len(
221e0 73 65 6c 66 2e 73 6f 75 72 63 65 29 0a 20 20 20  self.source).   
221f0 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c               sel
22200 66 2e 77 72 69 74 65 5f 63 6f 64 65 28 63 6f 64  f.write_code(cod
22210 65 5f 6c 69 6e 65 2e 73 74 72 69 70 28 29 2c 20  e_line.strip(), 
22220 63 6f 6d 6d 65 6e 74 29 0a 20 20 20 20 20 20 20  comment).       
22230 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 0a           return.
22240 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 64 65              code
22250 5f 6c 69 6e 65 20 2b 3d 20 73 65 6c 66 2e 73 6f  _line += self.so
22260 75 72 63 65 5b 73 65 6c 66 2e 6f 66 66 73 65 74  urce[self.offset
22270 3a 73 65 6c 66 2e 6f 66 66 73 65 74 2b 6d 2e 73  :self.offset+m.s
22280 74 61 72 74 28 29 5d 0a 20 20 20 20 20 20 20 20  tart()].        
22290 20 20 20 20 73 65 6c 66 2e 6f 66 66 73 65 74 20      self.offset 
222a0 2b 3d 20 6d 2e 65 6e 64 28 29 0a 20 20 20 20 20  += m.end().     
222b0 20 20 20 20 20 20 20 5f 73 74 72 2c 20 5f 63 6f         _str, _co
222c0 6d 2c 20 5f 70 6f 2c 20 5f 70 63 2c 20 5f 62 6c  m, _po, _pc, _bl
222d0 6b 31 2c 20 5f 62 6c 6b 32 2c 20 5f 65 6e 64 2c  k1, _blk2, _end,
222e0 20 5f 63 65 6e 64 2c 20 5f 6e 6c 20 3d 20 6d 2e   _cend, _nl = m.
222f0 67 72 6f 75 70 73 28 29 0a 20 20 20 20 20 20 20  groups().       
22300 20 20 20 20 20 69 66 20 28 63 6f 64 65 5f 6c 69       if (code_li
22310 6e 65 20 6f 72 20 73 65 6c 66 2e 70 61 72 65 6e  ne or self.paren
22320 5f 64 65 70 74 68 20 3e 20 30 29 20 61 6e 64 20  _depth > 0) and 
22330 28 5f 62 6c 6b 31 20 6f 72 20 5f 62 6c 6b 32 29  (_blk1 or _blk2)
22340 3a 20 23 20 61 20 69 66 20 62 20 65 6c 73 65 20  : # a if b else 
22350 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c.              
22360 20 20 63 6f 64 65 5f 6c 69 6e 65 20 2b 3d 20 5f    code_line += _
22370 62 6c 6b 31 20 6f 72 20 5f 62 6c 6b 32 0a 20 20  blk1 or _blk2.  
22380 20 20 20 20 20 20 20 20 20 20 20 20 20 20 63 6f                co
22390 6e 74 69 6e 75 65 0a 20 20 20 20 20 20 20 20 20  ntinue.         
223a0 20 20 20 69 66 20 5f 73 74 72 3a 20 20 20 20 23     if _str:    #
223b0 20 50 79 74 68 6f 6e 20 73 74 72 69 6e 67 0a 20   Python string. 
223c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 63                 c
223d0 6f 64 65 5f 6c 69 6e 65 20 2b 3d 20 5f 73 74 72  ode_line += _str
223e0 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69  .            eli
223f0 66 20 5f 63 6f 6d 3a 20 20 23 20 50 79 74 68 6f  f _com:  # Pytho
22400 6e 20 63 6f 6d 6d 65 6e 74 20 28 75 70 20 74 6f  n comment (up to
22410 20 45 4f 4c 29 0a 20 20 20 20 20 20 20 20 20 20   EOL).          
22420 20 20 20 20 20 20 63 6f 6d 6d 65 6e 74 20 3d 20        comment = 
22430 5f 63 6f 6d 0a 20 20 20 20 20 20 20 20 20 20 20  _com.           
22440 20 20 20 20 20 69 66 20 6d 75 6c 74 69 6c 69 6e       if multilin
22450 65 20 61 6e 64 20 5f 63 6f 6d 2e 73 74 72 69 70  e and _com.strip
22460 28 29 2e 65 6e 64 73 77 69 74 68 28 73 65 6c 66  ().endswith(self
22470 2e 5f 74 6f 6b 65 6e 73 5b 31 5d 29 3a 0a 20 20  ._tokens[1]):.  
22480 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22490 20 20 6d 75 6c 74 69 6c 69 6e 65 20 3d 20 46 61    multiline = Fa
224a0 6c 73 65 20 23 20 41 6c 6c 6f 77 20 65 6e 64 2d  lse # Allow end-
224b0 6f 66 2d 62 6c 6f 63 6b 20 69 6e 20 63 6f 6d 6d  of-block in comm
224c0 65 6e 74 73 0a 20 20 20 20 20 20 20 20 20 20 20  ents.           
224d0 20 65 6c 69 66 20 5f 70 6f 3a 20 20 23 20 6f 70   elif _po:  # op
224e0 65 6e 20 70 61 72 65 6e 74 68 65 73 69 73 0a 20  en parenthesis. 
224f0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
22500 65 6c 66 2e 70 61 72 65 6e 5f 64 65 70 74 68 20  elf.paren_depth 
22510 2b 3d 20 31 0a 20 20 20 20 20 20 20 20 20 20 20  += 1.           
22520 20 20 20 20 20 63 6f 64 65 5f 6c 69 6e 65 20 2b       code_line +
22530 3d 20 5f 70 6f 0a 20 20 20 20 20 20 20 20 20 20  = _po.          
22540 20 20 65 6c 69 66 20 5f 70 63 3a 20 20 23 20 63    elif _pc:  # c
22550 6c 6f 73 65 20 70 61 72 65 6e 74 68 65 73 69 73  lose parenthesis
22560 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
22570 20 69 66 20 73 65 6c 66 2e 70 61 72 65 6e 5f 64   if self.paren_d
22580 65 70 74 68 20 3e 20 30 3a 0a 20 20 20 20 20 20  epth > 0:.      
22590 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
225a0 77 65 20 63 6f 75 6c 64 20 63 68 65 63 6b 20 66  we could check f
225b0 6f 72 20 6d 61 74 63 68 69 6e 67 20 70 61 72 65  or matching pare
225c0 6e 74 68 65 73 65 73 20 68 65 72 65 2c 20 62 75  ntheses here, bu
225d0 74 20 69 74 27 73 0a 20 20 20 20 20 20 20 20 20  t it's.         
225e0 20 20 20 20 20 20 20 20 20 20 20 23 20 65 61 73             # eas
225f0 69 65 72 20 74 6f 20 6c 65 61 76 65 20 74 68 61  ier to leave tha
22600 74 20 74 6f 20 70 79 74 68 6f 6e 20 2d 20 6a 75  t to python - ju
22610 73 74 20 63 68 65 63 6b 20 63 6f 75 6e 74 73 0a  st check counts.
22620 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22630 20 20 20 20 73 65 6c 66 2e 70 61 72 65 6e 5f 64      self.paren_d
22640 65 70 74 68 20 2d 3d 20 31 0a 20 20 20 20 20 20  epth -= 1.      
22650 20 20 20 20 20 20 20 20 20 20 63 6f 64 65 5f 6c            code_l
22660 69 6e 65 20 2b 3d 20 5f 70 63 0a 20 20 20 20 20  ine += _pc.     
22670 20 20 20 20 20 20 20 65 6c 69 66 20 5f 62 6c 6b         elif _blk
22680 31 3a 20 23 20 53 74 61 72 74 2d 62 6c 6f 63 6b  1: # Start-block
22690 20 6b 65 79 77 6f 72 64 20 28 69 66 2f 66 6f 72   keyword (if/for
226a0 2f 77 68 69 6c 65 2f 64 65 66 2f 74 72 79 2f 2e  /while/def/try/.
226b0 2e 2e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ..).            
226c0 20 20 20 20 63 6f 64 65 5f 6c 69 6e 65 2c 20 73      code_line, s
226d0 65 6c 66 2e 69 6e 64 65 6e 74 5f 6d 6f 64 20 3d  elf.indent_mod =
226e0 20 5f 62 6c 6b 31 2c 20 2d 31 0a 20 20 20 20 20   _blk1, -1.     
226f0 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
22700 69 6e 64 65 6e 74 20 2b 3d 20 31 0a 20 20 20 20  indent += 1.    
22710 20 20 20 20 20 20 20 20 65 6c 69 66 20 5f 62 6c          elif _bl
22720 6b 32 3a 20 23 20 43 6f 6e 74 69 6e 75 65 2d 62  k2: # Continue-b
22730 6c 6f 63 6b 20 6b 65 79 77 6f 72 64 20 28 65 6c  lock keyword (el
22740 73 65 2f 65 6c 69 66 2f 65 78 63 65 70 74 2f 2e  se/elif/except/.
22750 2e 2e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ..).            
22760 20 20 20 20 63 6f 64 65 5f 6c 69 6e 65 2c 20 73      code_line, s
22770 65 6c 66 2e 69 6e 64 65 6e 74 5f 6d 6f 64 20 3d  elf.indent_mod =
22780 20 5f 62 6c 6b 32 2c 20 2d 31 0a 20 20 20 20 20   _blk2, -1.     
22790 20 20 20 20 20 20 20 65 6c 69 66 20 5f 65 6e 64         elif _end
227a0 3a 20 20 23 20 54 68 65 20 6e 6f 6e 2d 73 74 61  :  # The non-sta
227b0 6e 64 61 72 64 20 27 65 6e 64 27 2d 6b 65 79 77  ndard 'end'-keyw
227c0 6f 72 64 20 28 65 6e 64 73 20 61 20 62 6c 6f 63  ord (ends a bloc
227d0 6b 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  k).             
227e0 20 20 20 73 65 6c 66 2e 69 6e 64 65 6e 74 20 2d     self.indent -
227f0 3d 20 31 0a 20 20 20 20 20 20 20 20 20 20 20 20  = 1.            
22800 65 6c 69 66 20 5f 63 65 6e 64 3a 20 23 20 54 68  elif _cend: # Th
22810 65 20 65 6e 64 2d 63 6f 64 65 2d 62 6c 6f 63 6b  e end-code-block
22820 20 74 65 6d 70 6c 61 74 65 20 74 6f 6b 65 6e 20   template token 
22830 28 75 73 75 61 6c 6c 79 20 27 25 3e 27 29 0a 20  (usually '%>'). 
22840 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
22850 66 20 6d 75 6c 74 69 6c 69 6e 65 3a 20 6d 75 6c  f multiline: mul
22860 74 69 6c 69 6e 65 20 3d 20 46 61 6c 73 65 0a 20  tiline = False. 
22870 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
22880 6c 73 65 3a 20 63 6f 64 65 5f 6c 69 6e 65 20 2b  lse: code_line +
22890 3d 20 5f 63 65 6e 64 0a 20 20 20 20 20 20 20 20  = _cend.        
228a0 20 20 20 20 65 6c 73 65 3a 20 23 20 5c 6e 0a 20      else: # \n. 
228b0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
228c0 65 6c 66 2e 77 72 69 74 65 5f 63 6f 64 65 28 63  elf.write_code(c
228d0 6f 64 65 5f 6c 69 6e 65 2e 73 74 72 69 70 28 29  ode_line.strip()
228e0 2c 20 63 6f 6d 6d 65 6e 74 29 0a 20 20 20 20 20  , comment).     
228f0 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
22900 6c 69 6e 65 6e 6f 20 2b 3d 20 31 0a 20 20 20 20  lineno += 1.    
22910 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 64 65              code
22920 5f 6c 69 6e 65 2c 20 63 6f 6d 6d 65 6e 74 2c 20  _line, comment, 
22930 73 65 6c 66 2e 69 6e 64 65 6e 74 5f 6d 6f 64 20  self.indent_mod 
22940 3d 20 27 27 2c 20 27 27 2c 20 30 0a 20 20 20 20  = '', '', 0.    
22950 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
22960 6f 74 20 6d 75 6c 74 69 6c 69 6e 65 3a 0a 20 20  ot multiline:.  
22970 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22980 20 20 62 72 65 61 6b 0a 0a 20 20 20 20 64 65 66    break..    def
22990 20 66 6c 75 73 68 5f 74 65 78 74 28 73 65 6c 66   flush_text(self
229a0 29 3a 0a 20 20 20 20 20 20 20 20 74 65 78 74 20  ):.        text 
229b0 3d 20 27 27 2e 6a 6f 69 6e 28 73 65 6c 66 2e 74  = ''.join(self.t
229c0 65 78 74 5f 62 75 66 66 65 72 29 0a 20 20 20 20  ext_buffer).    
229d0 20 20 20 20 64 65 6c 20 73 65 6c 66 2e 74 65 78      del self.tex
229e0 74 5f 62 75 66 66 65 72 5b 3a 5d 0a 20 20 20 20  t_buffer[:].    
229f0 20 20 20 20 69 66 20 6e 6f 74 20 74 65 78 74 3a      if not text:
22a00 20 72 65 74 75 72 6e 0a 20 20 20 20 20 20 20 20   return.        
22a10 70 61 72 74 73 2c 20 70 6f 73 2c 20 6e 6c 20 3d  parts, pos, nl =
22a20 20 5b 5d 2c 20 30 2c 20 27 5c 5c 5c 6e 27 2b 27   [], 0, '\\\n'+'
22a30 20 20 27 2a 73 65 6c 66 2e 69 6e 64 65 6e 74 0a    '*self.indent.
22a40 20 20 20 20 20 20 20 20 66 6f 72 20 6d 20 69 6e          for m in
22a50 20 73 65 6c 66 2e 72 65 5f 69 6e 6c 2e 66 69 6e   self.re_inl.fin
22a60 64 69 74 65 72 28 74 65 78 74 29 3a 0a 20 20 20  diter(text):.   
22a70 20 20 20 20 20 20 20 20 20 70 72 65 66 69 78 2c           prefix,
22a80 20 70 6f 73 20 3d 20 74 65 78 74 5b 70 6f 73 3a   pos = text[pos:
22a90 6d 2e 73 74 61 72 74 28 29 5d 2c 20 6d 2e 65 6e  m.start()], m.en
22aa0 64 28 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  d().            
22ab0 69 66 20 70 72 65 66 69 78 3a 0a 20 20 20 20 20  if prefix:.     
22ac0 20 20 20 20 20 20 20 20 20 20 20 70 61 72 74 73             parts
22ad0 2e 61 70 70 65 6e 64 28 6e 6c 2e 6a 6f 69 6e 28  .append(nl.join(
22ae0 6d 61 70 28 72 65 70 72 2c 20 70 72 65 66 69 78  map(repr, prefix
22af0 2e 73 70 6c 69 74 6c 69 6e 65 73 28 54 72 75 65  .splitlines(True
22b00 29 29 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  )))).           
22b10 20 69 66 20 70 72 65 66 69 78 2e 65 6e 64 73 77   if prefix.endsw
22b20 69 74 68 28 27 5c 6e 27 29 3a 20 70 61 72 74 73  ith('\n'): parts
22b30 5b 2d 31 5d 20 2b 3d 20 6e 6c 0a 20 20 20 20 20  [-1] += nl.     
22b40 20 20 20 20 20 20 20 70 61 72 74 73 2e 61 70 70         parts.app
22b50 65 6e 64 28 73 65 6c 66 2e 70 72 6f 63 65 73 73  end(self.process
22b60 5f 69 6e 6c 69 6e 65 28 6d 2e 67 72 6f 75 70 28  _inline(m.group(
22b70 31 29 2e 73 74 72 69 70 28 29 29 29 0a 20 20 20  1).strip())).   
22b80 20 20 20 20 20 69 66 20 70 6f 73 20 3c 20 6c 65       if pos < le
22b90 6e 28 74 65 78 74 29 3a 0a 20 20 20 20 20 20 20  n(text):.       
22ba0 20 20 20 20 20 70 72 65 66 69 78 20 3d 20 74 65       prefix = te
22bb0 78 74 5b 70 6f 73 3a 5d 0a 20 20 20 20 20 20 20  xt[pos:].       
22bc0 20 20 20 20 20 6c 69 6e 65 73 20 3d 20 70 72 65       lines = pre
22bd0 66 69 78 2e 73 70 6c 69 74 6c 69 6e 65 73 28 54  fix.splitlines(T
22be0 72 75 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  rue).           
22bf0 20 69 66 20 6c 69 6e 65 73 5b 2d 31 5d 2e 65 6e   if lines[-1].en
22c00 64 73 77 69 74 68 28 27 5c 5c 5c 5c 5c 6e 27 29  dswith('\\\\\n')
22c10 3a 20 6c 69 6e 65 73 5b 2d 31 5d 20 3d 20 6c 69  : lines[-1] = li
22c20 6e 65 73 5b 2d 31 5d 5b 3a 2d 33 5d 0a 20 20 20  nes[-1][:-3].   
22c30 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 6c 69           elif li
22c40 6e 65 73 5b 2d 31 5d 2e 65 6e 64 73 77 69 74 68  nes[-1].endswith
22c50 28 27 5c 5c 5c 5c 5c 72 5c 6e 27 29 3a 20 6c 69  ('\\\\\r\n'): li
22c60 6e 65 73 5b 2d 31 5d 20 3d 20 6c 69 6e 65 73 5b  nes[-1] = lines[
22c70 2d 31 5d 5b 3a 2d 34 5d 0a 20 20 20 20 20 20 20  -1][:-4].       
22c80 20 20 20 20 20 70 61 72 74 73 2e 61 70 70 65 6e       parts.appen
22c90 64 28 6e 6c 2e 6a 6f 69 6e 28 6d 61 70 28 72 65  d(nl.join(map(re
22ca0 70 72 2c 20 6c 69 6e 65 73 29 29 29 0a 20 20 20  pr, lines))).   
22cb0 20 20 20 20 20 63 6f 64 65 20 3d 20 27 5f 70 72       code = '_pr
22cc0 69 6e 74 6c 69 73 74 28 28 25 73 2c 29 29 27 20  intlist((%s,))' 
22cd0 25 20 27 2c 20 27 2e 6a 6f 69 6e 28 70 61 72 74  % ', '.join(part
22ce0 73 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  s).        self.
22cf0 6c 69 6e 65 6e 6f 20 2b 3d 20 63 6f 64 65 2e 63  lineno += code.c
22d00 6f 75 6e 74 28 27 5c 6e 27 29 2b 31 0a 20 20 20  ount('\n')+1.   
22d10 20 20 20 20 20 73 65 6c 66 2e 77 72 69 74 65 5f       self.write_
22d20 63 6f 64 65 28 63 6f 64 65 29 0a 0a 20 20 20 20  code(code)..    
22d30 64 65 66 20 70 72 6f 63 65 73 73 5f 69 6e 6c 69  def process_inli
22d40 6e 65 28 73 65 6c 66 2c 20 63 68 75 6e 6b 29 3a  ne(self, chunk):
22d50 0a 20 20 20 20 20 20 20 20 69 66 20 63 68 75 6e  .        if chun
22d60 6b 5b 30 5d 20 3d 3d 20 27 21 27 3a 20 72 65 74  k[0] == '!': ret
22d70 75 72 6e 20 27 5f 73 74 72 28 25 73 29 27 20 25  urn '_str(%s)' %
22d80 20 63 68 75 6e 6b 5b 31 3a 5d 0a 20 20 20 20 20   chunk[1:].     
22d90 20 20 20 72 65 74 75 72 6e 20 27 5f 65 73 63 61     return '_esca
22da0 70 65 28 25 73 29 27 20 25 20 63 68 75 6e 6b 0a  pe(%s)' % chunk.
22db0 0a 20 20 20 20 64 65 66 20 77 72 69 74 65 5f 63  .    def write_c
22dc0 6f 64 65 28 73 65 6c 66 2c 20 6c 69 6e 65 2c 20  ode(self, line, 
22dd0 63 6f 6d 6d 65 6e 74 3d 27 27 29 3a 0a 20 20 20  comment=''):.   
22de0 20 20 20 20 20 6c 69 6e 65 2c 20 63 6f 6d 6d 65       line, comme
22df0 6e 74 20 3d 20 73 65 6c 66 2e 66 69 78 5f 62 61  nt = self.fix_ba
22e00 63 6b 77 61 72 64 5f 63 6f 6d 70 61 74 69 62 69  ckward_compatibi
22e10 6c 69 74 79 28 6c 69 6e 65 2c 20 63 6f 6d 6d 65  lity(line, comme
22e20 6e 74 29 0a 20 20 20 20 20 20 20 20 63 6f 64 65  nt).        code
22e30 20 20 3d 20 27 20 20 27 20 2a 20 28 73 65 6c 66    = '  ' * (self
22e40 2e 69 6e 64 65 6e 74 2b 73 65 6c 66 2e 69 6e 64  .indent+self.ind
22e50 65 6e 74 5f 6d 6f 64 29 0a 20 20 20 20 20 20 20  ent_mod).       
22e60 20 63 6f 64 65 20 2b 3d 20 6c 69 6e 65 2e 6c 73   code += line.ls
22e70 74 72 69 70 28 29 20 2b 20 63 6f 6d 6d 65 6e 74  trip() + comment
22e80 20 2b 20 27 5c 6e 27 0a 20 20 20 20 20 20 20 20   + '\n'.        
22e90 73 65 6c 66 2e 63 6f 64 65 5f 62 75 66 66 65 72  self.code_buffer
22ea0 2e 61 70 70 65 6e 64 28 63 6f 64 65 29 0a 0a 20  .append(code).. 
22eb0 20 20 20 64 65 66 20 66 69 78 5f 62 61 63 6b 77     def fix_backw
22ec0 61 72 64 5f 63 6f 6d 70 61 74 69 62 69 6c 69 74  ard_compatibilit
22ed0 79 28 73 65 6c 66 2c 20 6c 69 6e 65 2c 20 63 6f  y(self, line, co
22ee0 6d 6d 65 6e 74 29 3a 0a 20 20 20 20 20 20 20 20  mment):.        
22ef0 70 61 72 74 73 20 3d 20 6c 69 6e 65 2e 73 74 72  parts = line.str
22f00 69 70 28 29 2e 73 70 6c 69 74 28 4e 6f 6e 65 2c  ip().split(None,
22f10 20 32 29 0a 20 20 20 20 20 20 20 20 69 66 20 70   2).        if p
22f20 61 72 74 73 20 61 6e 64 20 70 61 72 74 73 5b 30  arts and parts[0
22f30 5d 20 69 6e 20 28 27 69 6e 63 6c 75 64 65 27 2c  ] in ('include',
22f40 20 27 72 65 62 61 73 65 27 29 3a 0a 20 20 20 20   'rebase'):.    
22f50 20 20 20 20 20 20 20 20 64 65 70 72 28 27 54 68          depr('Th
22f60 65 20 69 6e 63 6c 75 64 65 20 61 6e 64 20 72 65  e include and re
22f70 62 61 73 65 20 6b 65 79 77 6f 72 64 73 20 61 72  base keywords ar
22f80 65 20 66 75 6e 63 74 69 6f 6e 73 20 6e 6f 77 2e  e functions now.
22f90 27 29 20 23 30 2e 31 32 0a 20 20 20 20 20 20 20  ') #0.12.       
22fa0 20 20 20 20 20 69 66 20 6c 65 6e 28 70 61 72 74       if len(part
22fb0 73 29 20 3d 3d 20 31 3a 20 20 20 72 65 74 75 72  s) == 1:   retur
22fc0 6e 20 22 5f 70 72 69 6e 74 6c 69 73 74 28 5b 62  n "_printlist([b
22fd0 61 73 65 5d 29 22 2c 20 63 6f 6d 6d 65 6e 74 0a  ase])", comment.
22fe0 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
22ff0 20 6c 65 6e 28 70 61 72 74 73 29 20 3d 3d 20 32   len(parts) == 2
23000 3a 20 72 65 74 75 72 6e 20 22 5f 3d 25 73 28 25  : return "_=%s(%
23010 72 29 22 20 25 20 74 75 70 6c 65 28 70 61 72 74  r)" % tuple(part
23020 73 29 2c 20 63 6f 6d 6d 65 6e 74 0a 20 20 20 20  s), comment.    
23030 20 20 20 20 20 20 20 20 65 6c 73 65 3a 20 20 20          else:   
23040 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
23050 74 75 72 6e 20 22 5f 3d 25 73 28 25 72 2c 20 25  turn "_=%s(%r, %
23060 73 29 22 20 25 20 74 75 70 6c 65 28 70 61 72 74  s)" % tuple(part
23070 73 29 2c 20 63 6f 6d 6d 65 6e 74 0a 20 20 20 20  s), comment.    
23080 20 20 20 20 69 66 20 73 65 6c 66 2e 6c 69 6e 65      if self.line
23090 6e 6f 20 3c 3d 20 32 20 61 6e 64 20 6e 6f 74 20  no <= 2 and not 
230a0 6c 69 6e 65 2e 73 74 72 69 70 28 29 20 61 6e 64  line.strip() and
230b0 20 27 63 6f 64 69 6e 67 27 20 69 6e 20 63 6f 6d   'coding' in com
230c0 6d 65 6e 74 3a 0a 20 20 20 20 20 20 20 20 20 20  ment:.          
230d0 20 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28 72    m = re.match(r
230e0 22 23 2e 2a 63 6f 64 69 6e 67 5b 3a 3d 5d 5c 73  "#.*coding[:=]\s
230f0 2a 28 5b 2d 5c 77 2e 5d 2b 29 22 2c 20 63 6f 6d  *([-\w.]+)", com
23100 6d 65 6e 74 29 0a 20 20 20 20 20 20 20 20 20 20  ment).          
23110 20 20 69 66 20 6d 3a 0a 20 20 20 20 20 20 20 20    if m:.        
23120 20 20 20 20 20 20 20 20 64 65 70 72 28 27 50 45          depr('PE
23130 50 32 36 33 20 65 6e 63 6f 64 69 6e 67 20 73 74  P263 encoding st
23140 72 69 6e 67 73 20 69 6e 20 74 65 6d 70 6c 61 74  rings in templat
23150 65 73 20 61 72 65 20 64 65 70 72 65 63 61 74 65  es are deprecate
23160 64 2e 27 29 20 23 30 2e 31 32 0a 20 20 20 20 20  d.') #0.12.     
23170 20 20 20 20 20 20 20 20 20 20 20 65 6e 63 20 3d             enc =
23180 20 6d 2e 67 72 6f 75 70 28 31 29 0a 20 20 20 20   m.group(1).    
23190 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
231a0 2e 73 6f 75 72 63 65 20 3d 20 73 65 6c 66 2e 73  .source = self.s
231b0 6f 75 72 63 65 2e 65 6e 63 6f 64 65 28 73 65 6c  ource.encode(sel
231c0 66 2e 65 6e 63 6f 64 69 6e 67 29 2e 64 65 63 6f  f.encoding).deco
231d0 64 65 28 65 6e 63 29 0a 20 20 20 20 20 20 20 20  de(enc).        
231e0 20 20 20 20 20 20 20 20 73 65 6c 66 2e 65 6e 63          self.enc
231f0 6f 64 69 6e 67 20 3d 20 65 6e 63 0a 20 20 20 20  oding = enc.    
23200 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
23210 72 6e 20 6c 69 6e 65 2c 20 63 6f 6d 6d 65 6e 74  rn line, comment
23220 2e 72 65 70 6c 61 63 65 28 27 63 6f 64 69 6e 67  .replace('coding
23230 27 2c 27 63 6f 64 69 6e 67 2a 27 29 0a 20 20 20  ','coding*').   
23240 20 20 20 20 20 72 65 74 75 72 6e 20 6c 69 6e 65       return line
23250 2c 20 63 6f 6d 6d 65 6e 74 0a 0a 0a 64 65 66 20  , comment...def 
23260 74 65 6d 70 6c 61 74 65 28 2a 61 72 67 73 2c 20  template(*args, 
23270 2a 2a 6b 77 61 72 67 73 29 3a 0a 20 20 20 20 27  **kwargs):.    '
23280 27 27 0a 20 20 20 20 47 65 74 20 61 20 72 65 6e  ''.    Get a ren
23290 64 65 72 65 64 20 74 65 6d 70 6c 61 74 65 20 61  dered template a
232a0 73 20 61 20 73 74 72 69 6e 67 20 69 74 65 72 61  s a string itera
232b0 74 6f 72 2e 0a 20 20 20 20 59 6f 75 20 63 61 6e  tor..    You can
232c0 20 75 73 65 20 61 20 6e 61 6d 65 2c 20 61 20 66   use a name, a f
232d0 69 6c 65 6e 61 6d 65 20 6f 72 20 61 20 74 65 6d  ilename or a tem
232e0 70 6c 61 74 65 20 73 74 72 69 6e 67 20 61 73 20  plate string as 
232f0 66 69 72 73 74 20 70 61 72 61 6d 65 74 65 72 2e  first parameter.
23300 0a 20 20 20 20 54 65 6d 70 6c 61 74 65 20 72 65  .    Template re
23310 6e 64 65 72 69 6e 67 20 61 72 67 75 6d 65 6e 74  ndering argument
23320 73 20 63 61 6e 20 62 65 20 70 61 73 73 65 64 20  s can be passed 
23330 61 73 20 64 69 63 74 69 6f 6e 61 72 69 65 73 0a  as dictionaries.
23340 20 20 20 20 6f 72 20 64 69 72 65 63 74 6c 79 20      or directly 
23350 28 61 73 20 6b 65 79 77 6f 72 64 20 61 72 67 75  (as keyword argu
23360 6d 65 6e 74 73 29 2e 0a 20 20 20 20 27 27 27 0a  ments)..    '''.
23370 20 20 20 20 74 70 6c 20 3d 20 61 72 67 73 5b 30      tpl = args[0
23380 5d 20 69 66 20 61 72 67 73 20 65 6c 73 65 20 4e  ] if args else N
23390 6f 6e 65 0a 20 20 20 20 61 64 61 70 74 65 72 20  one.    adapter 
233a0 3d 20 6b 77 61 72 67 73 2e 70 6f 70 28 27 74 65  = kwargs.pop('te
233b0 6d 70 6c 61 74 65 5f 61 64 61 70 74 65 72 27 2c  mplate_adapter',
233c0 20 53 69 6d 70 6c 65 54 65 6d 70 6c 61 74 65 29   SimpleTemplate)
233d0 0a 20 20 20 20 6c 6f 6f 6b 75 70 20 3d 20 6b 77  .    lookup = kw
233e0 61 72 67 73 2e 70 6f 70 28 27 74 65 6d 70 6c 61  args.pop('templa
233f0 74 65 5f 6c 6f 6f 6b 75 70 27 2c 20 54 45 4d 50  te_lookup', TEMP
23400 4c 41 54 45 5f 50 41 54 48 29 0a 20 20 20 20 74  LATE_PATH).    t
23410 70 6c 69 64 20 3d 20 28 69 64 28 6c 6f 6f 6b 75  plid = (id(looku
23420 70 29 2c 20 74 70 6c 29 0a 20 20 20 20 69 66 20  p), tpl).    if 
23430 74 70 6c 69 64 20 6e 6f 74 20 69 6e 20 54 45 4d  tplid not in TEM
23440 50 4c 41 54 45 53 20 6f 72 20 44 45 42 55 47 3a  PLATES or DEBUG:
23450 0a 20 20 20 20 20 20 20 20 73 65 74 74 69 6e 67  .        setting
23460 73 20 3d 20 6b 77 61 72 67 73 2e 70 6f 70 28 27  s = kwargs.pop('
23470 74 65 6d 70 6c 61 74 65 5f 73 65 74 74 69 6e 67  template_setting
23480 73 27 2c 20 7b 7d 29 0a 20 20 20 20 20 20 20 20  s', {}).        
23490 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 74 70  if isinstance(tp
234a0 6c 2c 20 61 64 61 70 74 65 72 29 3a 0a 20 20 20  l, adapter):.   
234b0 20 20 20 20 20 20 20 20 20 54 45 4d 50 4c 41 54           TEMPLAT
234c0 45 53 5b 74 70 6c 69 64 5d 20 3d 20 74 70 6c 0a  ES[tplid] = tpl.
234d0 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
234e0 65 74 74 69 6e 67 73 3a 20 54 45 4d 50 4c 41 54  ettings: TEMPLAT
234f0 45 53 5b 74 70 6c 69 64 5d 2e 70 72 65 70 61 72  ES[tplid].prepar
23500 65 28 2a 2a 73 65 74 74 69 6e 67 73 29 0a 20 20  e(**settings).  
23510 20 20 20 20 20 20 65 6c 69 66 20 22 5c 6e 22 20        elif "\n" 
23520 69 6e 20 74 70 6c 20 6f 72 20 22 7b 22 20 69 6e  in tpl or "{" in
23530 20 74 70 6c 20 6f 72 20 22 25 22 20 69 6e 20 74   tpl or "%" in t
23540 70 6c 20 6f 72 20 27 24 27 20 69 6e 20 74 70 6c  pl or '$' in tpl
23550 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 54 45  :.            TE
23560 4d 50 4c 41 54 45 53 5b 74 70 6c 69 64 5d 20 3d  MPLATES[tplid] =
23570 20 61 64 61 70 74 65 72 28 73 6f 75 72 63 65 3d   adapter(source=
23580 74 70 6c 2c 20 6c 6f 6f 6b 75 70 3d 6c 6f 6f 6b  tpl, lookup=look
23590 75 70 2c 20 2a 2a 73 65 74 74 69 6e 67 73 29 0a  up, **settings).
235a0 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
235b0 20 20 20 20 20 20 20 20 20 20 54 45 4d 50 4c 41            TEMPLA
235c0 54 45 53 5b 74 70 6c 69 64 5d 20 3d 20 61 64 61  TES[tplid] = ada
235d0 70 74 65 72 28 6e 61 6d 65 3d 74 70 6c 2c 20 6c  pter(name=tpl, l
235e0 6f 6f 6b 75 70 3d 6c 6f 6f 6b 75 70 2c 20 2a 2a  ookup=lookup, **
235f0 73 65 74 74 69 6e 67 73 29 0a 20 20 20 20 69 66  settings).    if
23600 20 6e 6f 74 20 54 45 4d 50 4c 41 54 45 53 5b 74   not TEMPLATES[t
23610 70 6c 69 64 5d 3a 0a 20 20 20 20 20 20 20 20 61  plid]:.        a
23620 62 6f 72 74 28 35 30 30 2c 20 27 54 65 6d 70 6c  bort(500, 'Templ
23630 61 74 65 20 28 25 73 29 20 6e 6f 74 20 66 6f 75  ate (%s) not fou
23640 6e 64 27 20 25 20 74 70 6c 29 0a 20 20 20 20 66  nd' % tpl).    f
23650 6f 72 20 64 69 63 74 61 72 67 20 69 6e 20 61 72  or dictarg in ar
23660 67 73 5b 31 3a 5d 3a 20 6b 77 61 72 67 73 2e 75  gs[1:]: kwargs.u
23670 70 64 61 74 65 28 64 69 63 74 61 72 67 29 0a 20  pdate(dictarg). 
23680 20 20 20 72 65 74 75 72 6e 20 54 45 4d 50 4c 41     return TEMPLA
23690 54 45 53 5b 74 70 6c 69 64 5d 2e 72 65 6e 64 65  TES[tplid].rende
236a0 72 28 6b 77 61 72 67 73 29 0a 0a 6d 61 6b 6f 5f  r(kwargs)..mako_
236b0 74 65 6d 70 6c 61 74 65 20 3d 20 66 75 6e 63 74  template = funct
236c0 6f 6f 6c 73 2e 70 61 72 74 69 61 6c 28 74 65 6d  ools.partial(tem
236d0 70 6c 61 74 65 2c 20 74 65 6d 70 6c 61 74 65 5f  plate, template_
236e0 61 64 61 70 74 65 72 3d 4d 61 6b 6f 54 65 6d 70  adapter=MakoTemp
236f0 6c 61 74 65 29 0a 63 68 65 65 74 61 68 5f 74 65  late).cheetah_te
23700 6d 70 6c 61 74 65 20 3d 20 66 75 6e 63 74 6f 6f  mplate = functoo
23710 6c 73 2e 70 61 72 74 69 61 6c 28 74 65 6d 70 6c  ls.partial(templ
23720 61 74 65 2c 20 74 65 6d 70 6c 61 74 65 5f 61 64  ate, template_ad
23730 61 70 74 65 72 3d 43 68 65 65 74 61 68 54 65 6d  apter=CheetahTem
23740 70 6c 61 74 65 29 0a 6a 69 6e 6a 61 32 5f 74 65  plate).jinja2_te
23750 6d 70 6c 61 74 65 20 3d 20 66 75 6e 63 74 6f 6f  mplate = functoo
23760 6c 73 2e 70 61 72 74 69 61 6c 28 74 65 6d 70 6c  ls.partial(templ
23770 61 74 65 2c 20 74 65 6d 70 6c 61 74 65 5f 61 64  ate, template_ad
23780 61 70 74 65 72 3d 4a 69 6e 6a 61 32 54 65 6d 70  apter=Jinja2Temp
23790 6c 61 74 65 29 0a 0a 0a 64 65 66 20 76 69 65 77  late)...def view
237a0 28 74 70 6c 5f 6e 61 6d 65 2c 20 2a 2a 64 65 66  (tpl_name, **def
237b0 61 75 6c 74 73 29 3a 0a 20 20 20 20 27 27 27 20  aults):.    ''' 
237c0 44 65 63 6f 72 61 74 6f 72 3a 20 72 65 6e 64 65  Decorator: rende
237d0 72 73 20 61 20 74 65 6d 70 6c 61 74 65 20 66 6f  rs a template fo
237e0 72 20 61 20 68 61 6e 64 6c 65 72 2e 0a 20 20 20  r a handler..   
237f0 20 20 20 20 20 54 68 65 20 68 61 6e 64 6c 65 72       The handler
23800 20 63 61 6e 20 63 6f 6e 74 72 6f 6c 20 69 74 73   can control its
23810 20 62 65 68 61 76 69 6f 72 20 6c 69 6b 65 20 74   behavior like t
23820 68 61 74 3a 0a 0a 20 20 20 20 20 20 20 20 20 20  hat:..          
23830 2d 20 72 65 74 75 72 6e 20 61 20 64 69 63 74 20  - return a dict 
23840 6f 66 20 74 65 6d 70 6c 61 74 65 20 76 61 72 73  of template vars
23850 20 74 6f 20 66 69 6c 6c 20 6f 75 74 20 74 68 65   to fill out the
23860 20 74 65 6d 70 6c 61 74 65 0a 20 20 20 20 20 20   template.      
23870 20 20 20 20 2d 20 72 65 74 75 72 6e 20 73 6f 6d      - return som
23880 65 74 68 69 6e 67 20 6f 74 68 65 72 20 74 68 61  ething other tha
23890 6e 20 61 20 64 69 63 74 20 61 6e 64 20 74 68 65  n a dict and the
238a0 20 76 69 65 77 20 64 65 63 6f 72 61 74 6f 72 20   view decorator 
238b0 77 69 6c 6c 20 6e 6f 74 0a 20 20 20 20 20 20 20  will not.       
238c0 20 20 20 20 20 70 72 6f 63 65 73 73 20 74 68 65       process the
238d0 20 74 65 6d 70 6c 61 74 65 2c 20 62 75 74 20 72   template, but r
238e0 65 74 75 72 6e 20 74 68 65 20 68 61 6e 64 6c 65  eturn the handle
238f0 72 20 72 65 73 75 6c 74 20 61 73 20 69 73 2e 0a  r result as is..
23900 20 20 20 20 20 20 20 20 20 20 20 20 54 68 69 73              This
23910 20 69 6e 63 6c 75 64 65 73 20 72 65 74 75 72 6e   includes return
23920 69 6e 67 20 61 20 48 54 54 50 52 65 73 70 6f 6e  ing a HTTPRespon
23930 73 65 28 64 69 63 74 29 20 74 6f 20 67 65 74 2c  se(dict) to get,
23940 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72  .            for
23950 20 69 6e 73 74 61 6e 63 65 2c 20 4a 53 4f 4e 20   instance, JSON 
23960 77 69 74 68 20 61 75 74 6f 6a 73 6f 6e 20 6f 72  with autojson or
23970 20 6f 74 68 65 72 20 63 61 73 74 66 69 6c 74 65   other castfilte
23980 72 73 2e 0a 20 20 20 20 27 27 27 0a 20 20 20 20  rs..    '''.    
23990 64 65 66 20 64 65 63 6f 72 61 74 6f 72 28 66 75  def decorator(fu
239a0 6e 63 29 3a 0a 20 20 20 20 20 20 20 20 40 66 75  nc):.        @fu
239b0 6e 63 74 6f 6f 6c 73 2e 77 72 61 70 73 28 66 75  nctools.wraps(fu
239c0 6e 63 29 0a 20 20 20 20 20 20 20 20 64 65 66 20  nc).        def 
239d0 77 72 61 70 70 65 72 28 2a 61 72 67 73 2c 20 2a  wrapper(*args, *
239e0 2a 6b 77 61 72 67 73 29 3a 0a 20 20 20 20 20 20  *kwargs):.      
239f0 20 20 20 20 20 20 72 65 73 75 6c 74 20 3d 20 66        result = f
23a00 75 6e 63 28 2a 61 72 67 73 2c 20 2a 2a 6b 77 61  unc(*args, **kwa
23a10 72 67 73 29 0a 20 20 20 20 20 20 20 20 20 20 20  rgs).           
23a20 20 69 66 20 69 73 69 6e 73 74 61 6e 63 65 28 72   if isinstance(r
23a30 65 73 75 6c 74 2c 20 28 64 69 63 74 2c 20 44 69  esult, (dict, Di
23a40 63 74 4d 69 78 69 6e 29 29 3a 0a 20 20 20 20 20  ctMixin)):.     
23a50 20 20 20 20 20 20 20 20 20 20 20 74 70 6c 76 61             tplva
23a60 72 73 20 3d 20 64 65 66 61 75 6c 74 73 2e 63 6f  rs = defaults.co
23a70 70 79 28 29 0a 20 20 20 20 20 20 20 20 20 20 20  py().           
23a80 20 20 20 20 20 74 70 6c 76 61 72 73 2e 75 70 64       tplvars.upd
23a90 61 74 65 28 72 65 73 75 6c 74 29 0a 20 20 20 20  ate(result).    
23aa0 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
23ab0 72 6e 20 74 65 6d 70 6c 61 74 65 28 74 70 6c 5f  rn template(tpl_
23ac0 6e 61 6d 65 2c 20 2a 2a 74 70 6c 76 61 72 73 29  name, **tplvars)
23ad0 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69  .            eli
23ae0 66 20 72 65 73 75 6c 74 20 69 73 20 4e 6f 6e 65  f result is None
23af0 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
23b00 20 20 72 65 74 75 72 6e 20 74 65 6d 70 6c 61 74    return templat
23b10 65 28 74 70 6c 5f 6e 61 6d 65 2c 20 64 65 66 61  e(tpl_name, defa
23b20 75 6c 74 73 29 0a 20 20 20 20 20 20 20 20 20 20  ults).          
23b30 20 20 72 65 74 75 72 6e 20 72 65 73 75 6c 74 0a    return result.
23b40 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 77          return w
23b50 72 61 70 70 65 72 0a 20 20 20 20 72 65 74 75 72  rapper.    retur
23b60 6e 20 64 65 63 6f 72 61 74 6f 72 0a 0a 6d 61 6b  n decorator..mak
23b70 6f 5f 76 69 65 77 20 3d 20 66 75 6e 63 74 6f 6f  o_view = functoo
23b80 6c 73 2e 70 61 72 74 69 61 6c 28 76 69 65 77 2c  ls.partial(view,
23b90 20 74 65 6d 70 6c 61 74 65 5f 61 64 61 70 74 65   template_adapte
23ba0 72 3d 4d 61 6b 6f 54 65 6d 70 6c 61 74 65 29 0a  r=MakoTemplate).
23bb0 63 68 65 65 74 61 68 5f 76 69 65 77 20 3d 20 66  cheetah_view = f
23bc0 75 6e 63 74 6f 6f 6c 73 2e 70 61 72 74 69 61 6c  unctools.partial
23bd0 28 76 69 65 77 2c 20 74 65 6d 70 6c 61 74 65 5f  (view, template_
23be0 61 64 61 70 74 65 72 3d 43 68 65 65 74 61 68 54  adapter=CheetahT
23bf0 65 6d 70 6c 61 74 65 29 0a 6a 69 6e 6a 61 32 5f  emplate).jinja2_
23c00 76 69 65 77 20 3d 20 66 75 6e 63 74 6f 6f 6c 73  view = functools
23c10 2e 70 61 72 74 69 61 6c 28 76 69 65 77 2c 20 74  .partial(view, t
23c20 65 6d 70 6c 61 74 65 5f 61 64 61 70 74 65 72 3d  emplate_adapter=
23c30 4a 69 6e 6a 61 32 54 65 6d 70 6c 61 74 65 29 0a  Jinja2Template).
23c40 0a 0a 0a 0a 0a 0a 23 23 23 23 23 23 23 23 23 23  ......##########
23c50 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23c60 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23c70 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23c80 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23c90 23 23 23 23 23 0a 23 20 43 6f 6e 73 74 61 6e 74  #####.# Constant
23ca0 73 20 61 6e 64 20 47 6c 6f 62 61 6c 73 20 23 23  s and Globals ##
23cb0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23cc0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23cd0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23ce0 23 23 23 23 23 23 0a 23 23 23 23 23 23 23 23 23  ######.#########
23cf0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23d00 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23d10 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23d20 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23  ################
23d30 23 23 23 23 23 23 0a 0a 0a 54 45 4d 50 4c 41 54  ######...TEMPLAT
23d40 45 5f 50 41 54 48 20 3d 20 5b 27 2e 2f 27 2c 20  E_PATH = ['./', 
23d50 27 2e 2f 76 69 65 77 73 2f 27 5d 0a 54 45 4d 50  './views/'].TEMP
23d60 4c 41 54 45 53 20 3d 20 7b 7d 0a 44 45 42 55 47  LATES = {}.DEBUG
23d70 20 3d 20 46 61 6c 73 65 0a 4e 4f 52 55 4e 20 3d   = False.NORUN =
23d80 20 46 61 6c 73 65 20 23 20 49 66 20 73 65 74 2c   False # If set,
23d90 20 72 75 6e 28 29 20 64 6f 65 73 20 6e 6f 74 68   run() does noth
23da0 69 6e 67 2e 20 55 73 65 64 20 62 79 20 6c 6f 61  ing. Used by loa
23db0 64 5f 61 70 70 28 29 0a 0a 23 3a 20 41 20 64 69  d_app()..#: A di
23dc0 63 74 20 74 6f 20 6d 61 70 20 48 54 54 50 20 73  ct to map HTTP s
23dd0 74 61 74 75 73 20 63 6f 64 65 73 20 28 65 2e 67  tatus codes (e.g
23de0 2e 20 34 30 34 29 20 74 6f 20 70 68 72 61 73 65  . 404) to phrase
23df0 73 20 28 65 2e 67 2e 20 27 4e 6f 74 20 46 6f 75  s (e.g. 'Not Fou
23e00 6e 64 27 29 0a 48 54 54 50 5f 43 4f 44 45 53 20  nd').HTTP_CODES 
23e10 3d 20 68 74 74 70 6c 69 62 2e 72 65 73 70 6f 6e  = httplib.respon
23e20 73 65 73 0a 48 54 54 50 5f 43 4f 44 45 53 5b 34  ses.HTTP_CODES[4
23e30 31 38 5d 20 3d 20 22 49 27 6d 20 61 20 74 65 61  18] = "I'm a tea
23e40 70 6f 74 22 20 23 20 52 46 43 20 32 33 32 34 0a  pot" # RFC 2324.
23e50 48 54 54 50 5f 43 4f 44 45 53 5b 34 32 32 5d 20  HTTP_CODES[422] 
23e60 3d 20 22 55 6e 70 72 6f 63 65 73 73 61 62 6c 65  = "Unprocessable
23e70 20 45 6e 74 69 74 79 22 20 23 20 52 46 43 20 34   Entity" # RFC 4
23e80 39 31 38 0a 48 54 54 50 5f 43 4f 44 45 53 5b 34  918.HTTP_CODES[4
23e90 32 38 5d 20 3d 20 22 50 72 65 63 6f 6e 64 69 74  28] = "Precondit
23ea0 69 6f 6e 20 52 65 71 75 69 72 65 64 22 0a 48 54  ion Required".HT
23eb0 54 50 5f 43 4f 44 45 53 5b 34 32 39 5d 20 3d 20  TP_CODES[429] = 
23ec0 22 54 6f 6f 20 4d 61 6e 79 20 52 65 71 75 65 73  "Too Many Reques
23ed0 74 73 22 0a 48 54 54 50 5f 43 4f 44 45 53 5b 34  ts".HTTP_CODES[4
23ee0 33 31 5d 20 3d 20 22 52 65 71 75 65 73 74 20 48  31] = "Request H
23ef0 65 61 64 65 72 20 46 69 65 6c 64 73 20 54 6f 6f  eader Fields Too
23f00 20 4c 61 72 67 65 22 0a 48 54 54 50 5f 43 4f 44   Large".HTTP_COD
23f10 45 53 5b 35 31 31 5d 20 3d 20 22 4e 65 74 77 6f  ES[511] = "Netwo
23f20 72 6b 20 41 75 74 68 65 6e 74 69 63 61 74 69 6f  rk Authenticatio
23f30 6e 20 52 65 71 75 69 72 65 64 22 0a 5f 48 54 54  n Required"._HTT
23f40 50 5f 53 54 41 54 55 53 5f 4c 49 4e 45 53 20 3d  P_STATUS_LINES =
23f50 20 64 69 63 74 28 28 6b 2c 20 27 25 64 20 25 73   dict((k, '%d %s
23f60 27 25 28 6b 2c 76 29 29 20 66 6f 72 20 28 6b 2c  '%(k,v)) for (k,
23f70 76 29 20 69 6e 20 48 54 54 50 5f 43 4f 44 45 53  v) in HTTP_CODES
23f80 2e 69 74 65 6d 73 28 29 29 0a 0a 23 3a 20 54 68  .items())..#: Th
23f90 65 20 64 65 66 61 75 6c 74 20 74 65 6d 70 6c 61  e default templa
23fa0 74 65 20 75 73 65 64 20 66 6f 72 20 65 72 72 6f  te used for erro
23fb0 72 20 70 61 67 65 73 2e 20 4f 76 65 72 72 69 64  r pages. Overrid
23fc0 65 20 77 69 74 68 20 40 65 72 72 6f 72 28 29 0a  e with @error().
23fd0 45 52 52 4f 52 5f 50 41 47 45 5f 54 45 4d 50 4c  ERROR_PAGE_TEMPL
23fe0 41 54 45 20 3d 20 22 22 22 0a 25 25 74 72 79 3a  ATE = """.%%try:
23ff0 0a 20 20 20 20 25 25 66 72 6f 6d 20 25 73 20 69  .    %%from %s i
24000 6d 70 6f 72 74 20 44 45 42 55 47 2c 20 48 54 54  mport DEBUG, HTT
24010 50 5f 43 4f 44 45 53 2c 20 72 65 71 75 65 73 74  P_CODES, request
24020 2c 20 74 6f 75 6e 69 0a 20 20 20 20 3c 21 44 4f  , touni.    <!DO
24030 43 54 59 50 45 20 48 54 4d 4c 20 50 55 42 4c 49  CTYPE HTML PUBLI
24040 43 20 22 2d 2f 2f 49 45 54 46 2f 2f 44 54 44 20  C "-//IETF//DTD 
24050 48 54 4d 4c 20 32 2e 30 2f 2f 45 4e 22 3e 0a 20  HTML 2.0//EN">. 
24060 20 20 20 3c 68 74 6d 6c 3e 0a 20 20 20 20 20 20     <html>.      
24070 20 20 3c 68 65 61 64 3e 0a 20 20 20 20 20 20 20    <head>.       
24080 20 20 20 20 20 3c 74 69 74 6c 65 3e 45 72 72 6f       <title>Erro
24090 72 3a 20 7b 7b 65 2e 73 74 61 74 75 73 7d 7d 3c  r: {{e.status}}<
240a0 2f 74 69 74 6c 65 3e 0a 20 20 20 20 20 20 20 20  /title>.        
240b0 20 20 20 20 3c 73 74 79 6c 65 20 74 79 70 65 3d      <style type=
240c0 22 74 65 78 74 2f 63 73 73 22 3e 0a 20 20 20 20  "text/css">.    
240d0 20 20 20 20 20 20 20 20 20 20 68 74 6d 6c 20 7b            html {
240e0 62 61 63 6b 67 72 6f 75 6e 64 2d 63 6f 6c 6f 72  background-color
240f0 3a 20 23 65 65 65 3b 20 66 6f 6e 74 2d 66 61 6d  : #eee; font-fam
24100 69 6c 79 3a 20 73 61 6e 73 3b 7d 0a 20 20 20 20  ily: sans;}.    
24110 20 20 20 20 20 20 20 20 20 20 62 6f 64 79 20 7b            body {
24120 62 61 63 6b 67 72 6f 75 6e 64 2d 63 6f 6c 6f 72  background-color
24130 3a 20 23 66 66 66 3b 20 62 6f 72 64 65 72 3a 20  : #fff; border: 
24140 31 70 78 20 73 6f 6c 69 64 20 23 64 64 64 3b 0a  1px solid #ddd;.
24150 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
24160 20 20 20 20 70 61 64 64 69 6e 67 3a 20 31 35 70      padding: 15p
24170 78 3b 20 6d 61 72 67 69 6e 3a 20 31 35 70 78 3b  x; margin: 15px;
24180 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
24190 70 72 65 20 7b 62 61 63 6b 67 72 6f 75 6e 64 2d  pre {background-
241a0 63 6f 6c 6f 72 3a 20 23 65 65 65 3b 20 62 6f 72  color: #eee; bor
241b0 64 65 72 3a 20 31 70 78 20 73 6f 6c 69 64 20 23  der: 1px solid #
241c0 64 64 64 3b 20 70 61 64 64 69 6e 67 3a 20 35 70  ddd; padding: 5p
241d0 78 3b 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20  x;}.            
241e0 3c 2f 73 74 79 6c 65 3e 0a 20 20 20 20 20 20 20  </style>.       
241f0 20 3c 2f 68 65 61 64 3e 0a 20 20 20 20 20 20 20   </head>.       
24200 20 3c 62 6f 64 79 3e 0a 20 20 20 20 20 20 20 20   <body>.        
24210 20 20 20 20 3c 68 31 3e 45 72 72 6f 72 3a 20 7b      <h1>Error: {
24220 7b 65 2e 73 74 61 74 75 73 7d 7d 3c 2f 68 31 3e  {e.status}}</h1>
24230 0a 20 20 20 20 20 20 20 20 20 20 20 20 3c 70 3e  .            <p>
24240 53 6f 72 72 79 2c 20 74 68 65 20 72 65 71 75 65  Sorry, the reque
24250 73 74 65 64 20 55 52 4c 20 3c 74 74 3e 7b 7b 72  sted URL <tt>{{r
24260 65 70 72 28 72 65 71 75 65 73 74 2e 75 72 6c 29  epr(request.url)
24270 7d 7d 3c 2f 74 74 3e 0a 20 20 20 20 20 20 20 20  }}</tt>.        
24280 20 20 20 20 20 20 20 63 61 75 73 65 64 20 61 6e         caused an
24290 20 65 72 72 6f 72 3a 3c 2f 70 3e 0a 20 20 20 20   error:</p>.    
242a0 20 20 20 20 20 20 20 20 3c 70 72 65 3e 7b 7b 65          <pre>{{e
242b0 2e 62 6f 64 79 7d 7d 3c 2f 70 72 65 3e 0a 20 20  .body}}</pre>.  
242c0 20 20 20 20 20 20 20 20 20 20 25 25 69 66 20 44            %%if D
242d0 45 42 55 47 20 61 6e 64 20 65 2e 65 78 63 65 70  EBUG and e.excep
242e0 74 69 6f 6e 3a 0a 20 20 20 20 20 20 20 20 20 20  tion:.          
242f0 20 20 20 20 3c 68 32 3e 45 78 63 65 70 74 69 6f      <h2>Exceptio
24300 6e 3a 3c 2f 68 32 3e 0a 20 20 20 20 20 20 20 20  n:</h2>.        
24310 20 20 20 20 20 20 3c 70 72 65 3e 7b 7b 72 65 70        <pre>{{rep
24320 72 28 65 2e 65 78 63 65 70 74 69 6f 6e 29 7d 7d  r(e.exception)}}
24330 3c 2f 70 72 65 3e 0a 20 20 20 20 20 20 20 20 20  </pre>.         
24340 20 20 20 25 25 65 6e 64 0a 20 20 20 20 20 20 20     %%end.       
24350 20 20 20 20 20 25 25 69 66 20 44 45 42 55 47 20       %%if DEBUG 
24360 61 6e 64 20 65 2e 74 72 61 63 65 62 61 63 6b 3a  and e.traceback:
24370 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 3c  .              <
24380 68 32 3e 54 72 61 63 65 62 61 63 6b 3a 3c 2f 68  h2>Traceback:</h
24390 32 3e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  2>.             
243a0 20 3c 70 72 65 3e 7b 7b 65 2e 74 72 61 63 65 62   <pre>{{e.traceb
243b0 61 63 6b 7d 7d 3c 2f 70 72 65 3e 0a 20 20 20 20  ack}}</pre>.    
243c0 20 20 20 20 20 20 20 20 25 25 65 6e 64 0a 20 20          %%end.  
243d0 20 20 20 20 20 20 3c 2f 62 6f 64 79 3e 0a 20 20        </body>.  
243e0 20 20 3c 2f 68 74 6d 6c 3e 0a 25 25 65 78 63 65    </html>.%%exce
243f0 70 74 20 49 6d 70 6f 72 74 45 72 72 6f 72 3a 0a  pt ImportError:.
24400 20 20 20 20 3c 62 3e 49 6d 70 6f 72 74 45 72 72      <b>ImportErr
24410 6f 72 3a 3c 2f 62 3e 20 43 6f 75 6c 64 20 6e 6f  or:</b> Could no
24420 74 20 67 65 6e 65 72 61 74 65 20 74 68 65 20 65  t generate the e
24430 72 72 6f 72 20 70 61 67 65 2e 20 50 6c 65 61 73  rror page. Pleas
24440 65 20 61 64 64 20 62 6f 74 74 6c 65 20 74 6f 0a  e add bottle to.
24450 20 20 20 20 74 68 65 20 69 6d 70 6f 72 74 20 70      the import p
24460 61 74 68 2e 0a 25 25 65 6e 64 0a 22 22 22 20 25  ath..%%end.""" %
24470 20 5f 5f 6e 61 6d 65 5f 5f 0a 0a 23 3a 20 41 20   __name__..#: A 
24480 74 68 72 65 61 64 2d 73 61 66 65 20 69 6e 73 74  thread-safe inst
24490 61 6e 63 65 20 6f 66 20 3a 63 6c 61 73 73 3a 60  ance of :class:`
244a0 4c 6f 63 61 6c 52 65 71 75 65 73 74 60 2e 20 49  LocalRequest`. I
244b0 66 20 61 63 63 65 73 73 65 64 20 66 72 6f 6d 20  f accessed from 
244c0 77 69 74 68 69 6e 20 61 0a 23 3a 20 72 65 71 75  within a.#: requ
244d0 65 73 74 20 63 61 6c 6c 62 61 63 6b 2c 20 74 68  est callback, th
244e0 69 73 20 69 6e 73 74 61 6e 63 65 20 61 6c 77 61  is instance alwa
244f0 79 73 20 72 65 66 65 72 73 20 74 6f 20 74 68 65  ys refers to the
24500 20 2a 63 75 72 72 65 6e 74 2a 20 72 65 71 75 65   *current* reque
24510 73 74 0a 23 3a 20 28 65 76 65 6e 20 6f 6e 20 61  st.#: (even on a
24520 20 6d 75 6c 74 69 74 68 72 65 61 64 65 64 20 73   multithreaded s
24530 65 72 76 65 72 29 2e 0a 72 65 71 75 65 73 74 20  erver)..request 
24540 3d 20 4c 6f 63 61 6c 52 65 71 75 65 73 74 28 29  = LocalRequest()
24550 0a 0a 23 3a 20 41 20 74 68 72 65 61 64 2d 73 61  ..#: A thread-sa
24560 66 65 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 3a  fe instance of :
24570 63 6c 61 73 73 3a 60 4c 6f 63 61 6c 52 65 73 70  class:`LocalResp
24580 6f 6e 73 65 60 2e 20 49 74 20 69 73 20 75 73 65  onse`. It is use
24590 64 20 74 6f 20 63 68 61 6e 67 65 20 74 68 65 0a  d to change the.
245a0 23 3a 20 48 54 54 50 20 72 65 73 70 6f 6e 73 65  #: HTTP response
245b0 20 66 6f 72 20 74 68 65 20 2a 63 75 72 72 65 6e   for the *curren
245c0 74 2a 20 72 65 71 75 65 73 74 2e 0a 72 65 73 70  t* request..resp
245d0 6f 6e 73 65 20 3d 20 4c 6f 63 61 6c 52 65 73 70  onse = LocalResp
245e0 6f 6e 73 65 28 29 0a 0a 23 3a 20 41 20 74 68 72  onse()..#: A thr
245f0 65 61 64 2d 73 61 66 65 20 6e 61 6d 65 73 70 61  ead-safe namespa
24600 63 65 2e 20 4e 6f 74 20 75 73 65 64 20 62 79 20  ce. Not used by 
24610 42 6f 74 74 6c 65 2e 0a 6c 6f 63 61 6c 20 3d 20  Bottle..local = 
24620 74 68 72 65 61 64 69 6e 67 2e 6c 6f 63 61 6c 28  threading.local(
24630 29 0a 0a 23 20 49 6e 69 74 69 61 6c 69 7a 65 20  )..# Initialize 
24640 61 70 70 20 73 74 61 63 6b 20 28 63 72 65 61 74  app stack (creat
24650 65 20 66 69 72 73 74 20 65 6d 70 74 79 20 42 6f  e first empty Bo
24660 74 74 6c 65 20 61 70 70 29 0a 23 20 42 43 3a 20  ttle app).# BC: 
24670 30 2e 36 2e 34 20 61 6e 64 20 6e 65 65 64 65 64  0.6.4 and needed
24680 20 66 6f 72 20 72 75 6e 28 29 0a 61 70 70 20 3d   for run().app =
24690 20 64 65 66 61 75 6c 74 5f 61 70 70 20 3d 20 41   default_app = A
246a0 70 70 53 74 61 63 6b 28 29 0a 61 70 70 2e 70 75  ppStack().app.pu
246b0 73 68 28 29 0a 0a 23 3a 20 41 20 76 69 72 74 75  sh()..#: A virtu
246c0 61 6c 20 70 61 63 6b 61 67 65 20 74 68 61 74 20  al package that 
246d0 72 65 64 69 72 65 63 74 73 20 69 6d 70 6f 72 74  redirects import
246e0 20 73 74 61 74 65 6d 65 6e 74 73 2e 0a 23 3a 20   statements..#: 
246f0 45 78 61 6d 70 6c 65 3a 20 60 60 69 6d 70 6f 72  Example: ``impor
24700 74 20 62 6f 74 74 6c 65 2e 65 78 74 2e 73 71 6c  t bottle.ext.sql
24710 69 74 65 60 60 20 61 63 74 75 61 6c 6c 79 20 69  ite`` actually i
24720 6d 70 6f 72 74 73 20 60 62 6f 74 74 6c 65 5f 73  mports `bottle_s
24730 71 6c 69 74 65 60 2e 0a 65 78 74 20 3d 20 5f 49  qlite`..ext = _I
24740 6d 70 6f 72 74 52 65 64 69 72 65 63 74 28 27 62  mportRedirect('b
24750 6f 74 74 6c 65 2e 65 78 74 27 20 69 66 20 5f 5f  ottle.ext' if __
24760 6e 61 6d 65 5f 5f 20 3d 3d 20 27 5f 5f 6d 61 69  name__ == '__mai
24770 6e 5f 5f 27 20 65 6c 73 65 20 5f 5f 6e 61 6d 65  n__' else __name
24780 5f 5f 2b 22 2e 65 78 74 22 2c 20 27 62 6f 74 74  __+".ext", 'bott
24790 6c 65 5f 25 73 27 29 2e 6d 6f 64 75 6c 65 0a 0a  le_%s').module..
247a0 69 66 20 5f 5f 6e 61 6d 65 5f 5f 20 3d 3d 20 27  if __name__ == '
247b0 5f 5f 6d 61 69 6e 5f 5f 27 3a 0a 20 20 20 20 6f  __main__':.    o
247c0 70 74 2c 20 61 72 67 73 2c 20 70 61 72 73 65 72  pt, args, parser
247d0 20 3d 20 5f 63 6d 64 5f 6f 70 74 69 6f 6e 73 2c   = _cmd_options,
247e0 20 5f 63 6d 64 5f 61 72 67 73 2c 20 5f 63 6d 64   _cmd_args, _cmd
247f0 5f 70 61 72 73 65 72 0a 20 20 20 20 69 66 20 6f  _parser.    if o
24800 70 74 2e 76 65 72 73 69 6f 6e 3a 0a 20 20 20 20  pt.version:.    
24810 20 20 20 20 5f 73 74 64 6f 75 74 28 27 42 6f 74      _stdout('Bot
24820 74 6c 65 20 25 73 5c 6e 27 25 5f 5f 76 65 72 73  tle %s\n'%__vers
24830 69 6f 6e 5f 5f 29 0a 20 20 20 20 20 20 20 20 73  ion__).        s
24840 79 73 2e 65 78 69 74 28 30 29 0a 20 20 20 20 69  ys.exit(0).    i
24850 66 20 6e 6f 74 20 61 72 67 73 3a 0a 20 20 20 20  f not args:.    
24860 20 20 20 20 70 61 72 73 65 72 2e 70 72 69 6e 74      parser.print
24870 5f 68 65 6c 70 28 29 0a 20 20 20 20 20 20 20 20  _help().        
24880 5f 73 74 64 65 72 72 28 27 5c 6e 45 72 72 6f 72  _stderr('\nError
24890 3a 20 4e 6f 20 61 70 70 6c 69 63 61 74 69 6f 6e  : No application
248a0 20 73 70 65 63 69 66 69 65 64 2e 5c 6e 27 29 0a   specified.\n').
248b0 20 20 20 20 20 20 20 20 73 79 73 2e 65 78 69 74          sys.exit
248c0 28 31 29 0a 0a 20 20 20 20 73 79 73 2e 70 61 74  (1)..    sys.pat
248d0 68 2e 69 6e 73 65 72 74 28 30 2c 20 27 2e 27 29  h.insert(0, '.')
248e0 0a 20 20 20 20 73 79 73 2e 6d 6f 64 75 6c 65 73  .    sys.modules
248f0 2e 73 65 74 64 65 66 61 75 6c 74 28 27 62 6f 74  .setdefault('bot
24900 74 6c 65 27 2c 20 73 79 73 2e 6d 6f 64 75 6c 65  tle', sys.module
24910 73 5b 27 5f 5f 6d 61 69 6e 5f 5f 27 5d 29 0a 0a  s['__main__'])..
24920 20 20 20 20 68 6f 73 74 2c 20 70 6f 72 74 20 3d      host, port =
24930 20 28 6f 70 74 2e 62 69 6e 64 20 6f 72 20 27 6c   (opt.bind or 'l
24940 6f 63 61 6c 68 6f 73 74 27 29 2c 20 38 30 38 30  ocalhost'), 8080
24950 0a 20 20 20 20 69 66 20 27 3a 27 20 69 6e 20 68  .    if ':' in h
24960 6f 73 74 20 61 6e 64 20 68 6f 73 74 2e 72 66 69  ost and host.rfi
24970 6e 64 28 27 5d 27 29 20 3c 20 68 6f 73 74 2e 72  nd(']') < host.r
24980 66 69 6e 64 28 27 3a 27 29 3a 0a 20 20 20 20 20  find(':'):.     
24990 20 20 20 68 6f 73 74 2c 20 70 6f 72 74 20 3d 20     host, port = 
249a0 68 6f 73 74 2e 72 73 70 6c 69 74 28 27 3a 27 2c  host.rsplit(':',
249b0 20 31 29 0a 20 20 20 20 68 6f 73 74 20 3d 20 68   1).    host = h
249c0 6f 73 74 2e 73 74 72 69 70 28 27 5b 5d 27 29 0a  ost.strip('[]').
249d0 0a 20 20 20 20 72 75 6e 28 61 72 67 73 5b 30 5d  .    run(args[0]
249e0 2c 20 68 6f 73 74 3d 68 6f 73 74 2c 20 70 6f 72  , host=host, por
249f0 74 3d 69 6e 74 28 70 6f 72 74 29 2c 20 73 65 72  t=int(port), ser
24a00 76 65 72 3d 6f 70 74 2e 73 65 72 76 65 72 2c 0a  ver=opt.server,.
24a10 20 20 20 20 20 20 20 20 72 65 6c 6f 61 64 65 72          reloader
24a20 3d 6f 70 74 2e 72 65 6c 6f 61 64 2c 20 70 6c 75  =opt.reload, plu
24a30 67 69 6e 73 3d 6f 70 74 2e 70 6c 75 67 69 6e 2c  gins=opt.plugin,
24a40 20 64 65 62 75 67 3d 6f 70 74 2e 64 65 62 75 67   debug=opt.debug
24a50 29 0a 0a 0a 0a 0a 23 20 54 48 45 20 45 4e 44 0a  ).....# THE END.