MobileBlur

Hex Artifact Content
Login

Artifact 65d7dd776840def60f04e6bce35084a91dce78c4:


0000: 23 21 2f 75 73 72 2f 62 69 6e 2f 70 79 74 68 6f  #!/usr/bin/pytho
0010: 6e 0a 23 20 2d 2a 2d 20 63 6f 64 69 6e 67 3a 20  n.# -*- coding: 
0020: 75 74 66 2d 38 20 2d 2a 2d 0a 0a 23 20 64 65 66  utf-8 -*-..# def
0030: 61 75 6c 74 5f 61 70 70 6c 69 63 61 74 69 6f 6e  ault_application
0040: 2c 20 64 65 66 61 75 6c 74 5f 63 6f 6e 74 72 6f  , default_contro
0050: 6c 6c 65 72 2c 20 64 65 66 61 75 6c 74 5f 66 75  ller, default_fu
0060: 6e 63 74 69 6f 6e 0a 23 20 61 72 65 20 75 73 65  nction.# are use
0070: 64 20 77 68 65 6e 20 74 68 65 20 72 65 73 70 65  d when the respe
0080: 63 74 69 76 65 20 65 6c 65 6d 65 6e 74 20 69 73  ctive element is
0090: 20 6d 69 73 73 69 6e 67 20 66 72 6f 6d 20 74 68   missing from th
00a0: 65 0a 23 20 28 70 6f 73 73 69 62 6c 79 20 72 65  e.# (possibly re
00b0: 77 72 69 74 74 65 6e 29 20 69 6e 63 6f 6d 69 6e  written) incomin
00c0: 67 20 55 52 4c 0a 23 0a 64 65 66 61 75 6c 74 5f  g URL.#.default_
00d0: 61 70 70 6c 69 63 61 74 69 6f 6e 20 3d 20 27 69  application = 'i
00e0: 6e 69 74 27 20 20 20 20 23 20 6f 72 64 69 6e 61  nit'    # ordina
00f0: 72 69 6c 79 20 73 65 74 20 69 6e 20 62 61 73 65  rily set in base
0100: 20 72 6f 75 74 65 73 2e 70 79 0a 64 65 66 61 75   routes.py.defau
0110: 6c 74 5f 63 6f 6e 74 72 6f 6c 6c 65 72 20 3d 20  lt_controller = 
0120: 27 64 65 66 61 75 6c 74 27 20 20 23 20 6f 72 64  'default'  # ord
0130: 69 6e 61 72 69 6c 79 20 73 65 74 20 69 6e 20 61  inarily set in a
0140: 70 70 2d 73 70 65 63 69 66 69 63 20 72 6f 75 74  pp-specific rout
0150: 65 73 2e 70 79 0a 64 65 66 61 75 6c 74 5f 66 75  es.py.default_fu
0160: 6e 63 74 69 6f 6e 20 3d 20 27 69 6e 64 65 78 27  nction = 'index'
0170: 20 20 20 20 20 20 23 20 6f 72 64 69 6e 61 72 69        # ordinari
0180: 6c 79 20 73 65 74 20 69 6e 20 61 70 70 2d 73 70  ly set in app-sp
0190: 65 63 69 66 69 63 20 72 6f 75 74 65 73 2e 70 79  ecific routes.py
01a0: 0a 0a 23 20 72 6f 75 74 65 73 5f 61 70 70 20 69  ..# routes_app i
01b0: 73 20 61 20 74 75 70 6c 65 20 6f 66 20 74 75 70  s a tuple of tup
01c0: 6c 65 73 2e 20 20 54 68 65 20 66 69 72 73 74 20  les.  The first 
01d0: 69 74 65 6d 20 69 6e 20 65 61 63 68 20 69 73 20  item in each is 
01e0: 61 20 72 65 67 65 78 70 20 74 68 61 74 20 77 69  a regexp that wi
01f0: 6c 6c 0a 23 20 62 65 20 75 73 65 64 20 74 6f 20  ll.# be used to 
0200: 6d 61 74 63 68 20 74 68 65 20 69 6e 63 6f 6d 69  match the incomi
0210: 6e 67 20 72 65 71 75 65 73 74 20 55 52 4c 2e 20  ng request URL. 
0220: 54 68 65 20 73 65 63 6f 6e 64 20 69 74 65 6d 20  The second item 
0230: 69 6e 20 74 68 65 20 74 75 70 6c 65 20 69 73 0a  in the tuple is.
0240: 23 20 61 6e 20 61 70 70 6c 69 63 61 74 69 6f 6e  # an application
0250: 6e 61 6d 65 2e 20 20 54 68 69 73 20 6d 65 63 68  name.  This mech
0260: 61 6e 69 73 6d 20 61 6c 6c 6f 77 73 20 79 6f 75  anism allows you
0270: 20 74 6f 20 73 70 65 63 69 66 79 20 74 68 65 20   to specify the 
0280: 75 73 65 20 6f 66 20 61 6e 0a 23 20 61 70 70 2d  use of an.# app-
0290: 73 70 65 63 69 66 69 63 20 72 6f 75 74 65 73 2e  specific routes.
02a0: 70 79 2e 20 54 68 69 73 20 65 6e 74 72 79 20 69  py. This entry i
02b0: 73 20 6d 65 61 6e 69 6e 67 66 75 6c 20 6f 6e 6c  s meaningful onl
02c0: 79 20 69 6e 20 74 68 65 20 62 61 73 65 20 72 6f  y in the base ro
02d0: 75 74 65 73 2e 70 79 2e 0a 23 0a 23 20 45 78 61  utes.py..#.# Exa
02e0: 6d 70 6c 65 3a 20 73 75 70 70 6f 72 74 20 77 65  mple: support we
02f0: 6c 63 6f 6d 65 2c 20 61 64 6d 69 6e 2c 20 61 70  lcome, admin, ap
0300: 70 20 61 6e 64 20 6d 79 61 70 70 2c 20 77 69 74  p and myapp, wit
0310: 68 20 6d 79 61 70 70 20 74 68 65 20 64 65 66 61  h myapp the defa
0320: 75 6c 74 3a 0a 0a 0a 72 6f 75 74 65 73 5f 61 70  ult:...routes_ap
0330: 70 20 3d 20 28 28 72 27 2f 28 3f 50 3c 61 70 70  p = ((r'/(?P<app
0340: 3e 77 65 6c 63 6f 6d 65 7c 61 64 6d 69 6e 7c 61  >welcome|admin|a
0350: 70 70 29 5c 62 2e 2a 27 2c 20 72 27 5c 67 3c 61  pp)\b.*', r'\g<a
0360: 70 70 3e 27 29 2c 0a 20 20 20 20 20 20 20 20 20  pp>'),.         
0370: 20 20 20 20 20 28 72 27 28 2e 2a 29 27 2c 20 72       (r'(.*)', r
0380: 27 6d 79 61 70 70 27 29 2c 0a 20 20 20 20 20 20  'myapp'),.      
0390: 20 20 20 20 20 20 20 20 28 72 27 2f 3f 28 2e 2a          (r'/?(.*
03a0: 29 27 2c 20 72 27 6d 79 61 70 70 27 29 29 0a 0a  )', r'myapp'))..
03b0: 23 20 72 6f 75 74 65 73 5f 69 6e 20 69 73 20 61  # routes_in is a
03c0: 20 74 75 70 6c 65 20 6f 66 20 74 75 70 6c 65 73   tuple of tuples
03d0: 2e 20 20 54 68 65 20 66 69 72 73 74 20 69 74 65  .  The first ite
03e0: 6d 20 69 6e 20 65 61 63 68 20 69 73 20 61 20 72  m in each is a r
03f0: 65 67 65 78 70 20 74 68 61 74 20 77 69 6c 6c 0a  egexp that will.
0400: 23 20 62 65 20 75 73 65 64 20 74 6f 20 6d 61 74  # be used to mat
0410: 63 68 20 74 68 65 20 69 6e 63 6f 6d 69 6e 67 20  ch the incoming 
0420: 72 65 71 75 65 73 74 20 55 52 4c 2e 20 54 68 65  request URL. The
0430: 20 73 65 63 6f 6e 64 20 69 74 65 6d 20 69 6e 20   second item in 
0440: 74 68 65 20 74 75 70 6c 65 20 69 73 0a 23 20 77  the tuple is.# w
0450: 68 61 74 20 69 74 20 77 69 6c 6c 20 62 65 20 72  hat it will be r
0460: 65 70 6c 61 63 65 64 20 77 69 74 68 2e 20 20 54  eplaced with.  T
0470: 68 69 73 20 6d 65 63 68 61 6e 69 73 6d 20 61 6c  his mechanism al
0480: 6c 6f 77 73 20 79 6f 75 20 74 6f 20 72 65 64 69  lows you to redi
0490: 72 65 63 74 20 69 6e 63 6f 6d 69 6e 67 0a 23 20  rect incoming.# 
04a0: 72 6f 75 74 65 73 20 74 6f 20 64 69 66 66 65 72  routes to differ
04b0: 65 6e 74 20 77 65 62 32 70 79 20 6c 6f 63 61 74  ent web2py locat
04c0: 69 6f 6e 73 0a 23 0a 23 20 45 78 61 6d 70 6c 65  ions.#.# Example
04d0: 3a 20 49 66 20 79 6f 75 20 77 69 73 68 20 66 6f  : If you wish fo
04e0: 72 20 79 6f 75 72 20 65 6e 74 69 72 65 20 77 65  r your entire we
04f0: 62 73 69 74 65 20 74 6f 20 75 73 65 20 69 6e 69  bsite to use ini
0500: 74 27 73 20 73 74 61 74 69 63 20 64 69 72 65 63  t's static direc
0510: 74 6f 72 79 3a 0a 23 0a 23 20 20 20 72 6f 75 74  tory:.#.#   rout
0520: 65 73 5f 69 6e 3d 28 20 28 72 27 2f 73 74 61 74  es_in=( (r'/stat
0530: 69 63 2f 28 3f 50 3c 66 69 6c 65 3e 5b 5c 77 2e  ic/(?P<file>[\w.
0540: 2f 2d 5d 2b 29 27 2c 20 72 27 2f 69 6e 69 74 2f  /-]+)', r'/init/
0550: 73 74 61 74 69 63 2f 5c 67 3c 66 69 6c 65 3e 27  static/\g<file>'
0560: 29 20 29 0a 23 0a 0a 72 6f 75 74 65 73 5f 69 6e  ) ).#..routes_in
0570: 20 3d 20 28 28 72 27 2e 2a 3a 2f 66 61 76 69 63   = ((r'.*:/favic
0580: 6f 6e 2e 69 63 6f 27 2c 20 72 27 2f 65 78 61 6d  on.ico', r'/exam
0590: 70 6c 65 73 2f 73 74 61 74 69 63 2f 66 61 76 69  ples/static/favi
05a0: 63 6f 6e 2e 69 63 6f 27 29 2c 0a 20 20 20 20 20  con.ico'),.     
05b0: 20 20 20 20 20 20 20 20 28 72 27 2e 2a 3a 2f 72          (r'.*:/r
05c0: 6f 62 6f 74 73 2e 74 78 74 27 2c 20 72 27 2f 65  obots.txt', r'/e
05d0: 78 61 6d 70 6c 65 73 2f 73 74 61 74 69 63 2f 72  xamples/static/r
05e0: 6f 62 6f 74 73 2e 74 78 74 27 29 2c 0a 20 20 20  obots.txt'),.   
05f0: 20 20 20 20 20 20 20 20 20 20 28 28 72 27 2e 2a            ((r'.*
0600: 68 74 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d 61  http://otherdoma
0610: 69 6e 2e 63 6f 6d 2e 2a 20 28 3f 50 3c 61 6e 79  in.com.* (?P<any
0620: 3e 2e 2a 29 27 2c 20 72 27 2f 61 70 70 2f 63 74  >.*)', r'/app/ct
0630: 72 5c 67 3c 61 6e 79 3e 27 29 29 29 0a 0a 23 20  r\g<any>')))..# 
0640: 72 6f 75 74 65 73 5f 6f 75 74 2c 20 6c 69 6b 65  routes_out, like
0650: 20 72 6f 75 74 65 73 5f 69 6e 20 74 72 61 6e 73   routes_in trans
0660: 6c 61 74 65 73 20 55 52 4c 20 70 61 74 68 73 20  lates URL paths 
0670: 63 72 65 61 74 65 64 20 77 69 74 68 20 74 68 65  created with the
0680: 20 77 65 62 32 70 79 20 55 52 4c 28 29 0a 23 20   web2py URL().# 
0690: 66 75 6e 63 74 69 6f 6e 20 69 6e 20 74 68 65 20  function in the 
06a0: 73 61 6d 65 20 6d 61 6e 6e 65 72 20 74 68 61 74  same manner that
06b0: 20 72 6f 75 74 65 5f 69 6e 20 74 72 61 6e 73 6c   route_in transl
06c0: 61 74 65 73 20 69 6e 62 6f 75 6e 64 20 55 52 4c  ates inbound URL
06d0: 20 70 61 74 68 73 2e 0a 23 0a 0a 72 6f 75 74 65   paths..#..route
06e0: 73 5f 6f 75 74 20 3d 20 28 28 72 27 2e 2a 68 74  s_out = ((r'.*ht
06f0: 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d 61 69 6e  tp://otherdomain
0700: 2e 63 6f 6d 2e 2a 20 2f 61 70 70 2f 63 74 72 28  .com.* /app/ctr(
0710: 3f 50 3c 61 6e 79 3e 2e 2a 29 27 2c 20 72 27 5c  ?P<any>.*)', r'\
0720: 67 3c 61 6e 79 3e 27 29 2c 0a 20 20 20 20 20 20  g<any>'),.      
0730: 20 20 20 20 20 20 20 20 28 72 27 2f 61 70 70 28          (r'/app(
0740: 3f 50 3c 61 6e 79 3e 2e 2a 29 27 2c 20 72 27 5c  ?P<any>.*)', r'\
0750: 67 3c 61 6e 79 3e 27 29 29 0a 0a 23 20 45 72 72  g<any>'))..# Err
0760: 6f 72 2d 68 61 6e 64 6c 69 6e 67 20 72 65 64 69  or-handling redi
0770: 72 65 63 74 73 20 61 6c 6c 20 48 54 54 50 20 65  rects all HTTP e
0780: 72 72 6f 72 73 20 28 73 74 61 74 75 73 20 63 6f  rrors (status co
0790: 64 65 73 20 3e 3d 20 34 30 30 29 20 74 6f 20 61  des >= 400) to a
07a0: 20 73 70 65 63 69 66 69 65 64 0a 23 20 70 61 74   specified.# pat
07b0: 68 2e 20 20 49 66 20 79 6f 75 20 77 69 73 68 20  h.  If you wish 
07c0: 74 6f 20 75 73 65 20 65 72 72 6f 72 2d 68 61 6e  to use error-han
07d0: 64 6c 69 6e 67 20 72 65 64 69 72 65 63 74 73 2c  dling redirects,
07e0: 20 75 6e 63 6f 6d 6d 65 6e 74 20 74 68 65 20 74   uncomment the t
07f0: 75 70 6c 65 0a 23 20 62 65 6c 6f 77 2e 20 20 59  uple.# below.  Y
0800: 6f 75 20 63 61 6e 20 63 75 73 74 6f 6d 69 7a 65  ou can customize
0810: 20 72 65 73 70 6f 6e 73 65 73 20 62 79 20 61 64   responses by ad
0820: 64 69 6e 67 20 61 20 74 75 70 6c 65 20 65 6e 74  ding a tuple ent
0830: 72 79 20 77 69 74 68 20 74 68 65 20 66 69 72 73  ry with the firs
0840: 74 0a 23 20 76 61 6c 75 65 20 69 6e 20 27 61 70  t.# value in 'ap
0850: 70 4e 61 6d 65 2f 48 54 54 50 73 74 61 74 75 73  pName/HTTPstatus
0860: 43 6f 64 65 27 20 66 6f 72 6d 61 74 2e 20 28 20  Code' format. ( 
0870: 4f 6e 6c 79 20 48 54 54 50 20 63 6f 64 65 73 20  Only HTTP codes 
0880: 3e 3d 20 34 30 30 20 61 72 65 0a 23 20 72 6f 75  >= 400 are.# rou
0890: 74 65 64 2e 20 29 20 61 6e 64 20 74 68 65 20 76  ted. ) and the v
08a0: 61 6c 75 65 20 61 73 20 61 20 70 61 74 68 20 74  alue as a path t
08b0: 6f 20 72 65 64 69 72 65 63 74 20 74 68 65 20 75  o redirect the u
08c0: 73 65 72 20 74 6f 2e 20 20 59 6f 75 20 6d 61 79  ser to.  You may
08d0: 20 61 6c 73 6f 20 75 73 65 0a 23 20 27 2a 27 20   also use.# '*' 
08e0: 61 73 20 61 20 77 69 6c 64 63 61 72 64 2e 0a 23  as a wildcard..#
08f0: 0a 23 20 54 68 65 20 65 72 72 6f 72 20 68 61 6e  .# The error han
0900: 64 6c 69 6e 67 20 70 61 67 65 20 69 73 20 61 6c  dling page is al
0910: 73 6f 20 70 61 73 73 65 64 20 74 68 65 20 65 72  so passed the er
0920: 72 6f 72 20 63 6f 64 65 20 61 6e 64 20 74 69 63  ror code and tic
0930: 6b 65 74 20 61 73 0a 23 20 76 61 72 69 61 62 6c  ket as.# variabl
0940: 65 73 2e 20 20 54 72 61 63 65 62 61 63 6b 20 69  es.  Traceback i
0950: 6e 66 6f 72 6d 61 74 69 6f 6e 20 77 69 6c 6c 20  nformation will 
0960: 62 65 20 73 74 6f 72 65 64 20 69 6e 20 74 68 65  be stored in the
0970: 20 74 69 63 6b 65 74 2e 0a 23 0a 23 20 72 6f 75   ticket..#.# rou
0980: 74 65 73 5f 6f 6e 65 72 72 6f 72 20 3d 20 5b 0a  tes_onerror = [.
0990: 23 20 20 20 20 20 28 72 27 69 6e 69 74 2f 34 30  #     (r'init/40
09a0: 30 27 2c 20 72 27 2f 69 6e 69 74 2f 64 65 66 61  0', r'/init/defa
09b0: 75 6c 74 2f 6c 6f 67 69 6e 27 29 0a 23 20 20 20  ult/login').#   
09c0: 20 2c 28 72 27 69 6e 69 74 2f 2a 27 2c 20 72 27   ,(r'init/*', r'
09d0: 2f 69 6e 69 74 2f 73 74 61 74 69 63 2f 66 61 69  /init/static/fai
09e0: 6c 2e 68 74 6d 6c 27 29 0a 23 20 20 20 20 2c 28  l.html').#    ,(
09f0: 72 27 2a 2f 34 30 34 27 2c 20 72 27 2f 69 6e 69  r'*/404', r'/ini
0a00: 74 2f 73 74 61 74 69 63 2f 63 61 6e 74 66 69 6e  t/static/cantfin
0a10: 64 2e 68 74 6d 6c 27 29 0a 23 20 20 20 20 2c 28  d.html').#    ,(
0a20: 72 27 2a 2f 2a 27 2c 20 72 27 2f 69 6e 69 74 2f  r'*/*', r'/init/
0a30: 65 72 72 6f 72 2f 69 6e 64 65 78 27 29 0a 23 20  error/index').# 
0a40: 5d 0a 0a 23 20 73 70 65 63 69 66 79 20 61 63 74  ]..# specify act
0a50: 69 6f 6e 20 69 6e 20 63 68 61 72 67 65 20 6f 66  ion in charge of
0a60: 20 65 72 72 6f 72 20 68 61 6e 64 6c 69 6e 67 0a   error handling.
0a70: 23 0a 23 20 65 72 72 6f 72 5f 68 61 6e 64 6c 65  #.# error_handle
0a80: 72 20 3d 20 64 69 63 74 28 61 70 70 6c 69 63 61  r = dict(applica
0a90: 74 69 6f 6e 3d 27 65 72 72 6f 72 27 2c 0a 23 20  tion='error',.# 
0aa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ab0: 20 20 20 20 20 63 6f 6e 74 72 6f 6c 6c 65 72 3d       controller=
0ac0: 27 64 65 66 61 75 6c 74 27 2c 0a 23 20 20 20 20  'default',.#    
0ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ae0: 20 20 66 75 6e 63 74 69 6f 6e 3d 27 69 6e 64 65    function='inde
0af0: 78 27 29 0a 0a 23 20 49 6e 20 74 68 65 20 65 76  x')..# In the ev
0b00: 65 6e 74 20 74 68 61 74 20 74 68 65 20 65 72 72  ent that the err
0b10: 6f 72 2d 68 61 6e 64 6c 69 6e 67 20 70 61 67 65  or-handling page
0b20: 20 69 74 73 65 6c 66 20 72 65 74 75 72 6e 73 20   itself returns 
0b30: 61 6e 20 65 72 72 6f 72 2c 20 77 65 62 32 70 79  an error, web2py
0b40: 20 77 69 6c 6c 0a 23 20 66 61 6c 6c 20 62 61 63   will.# fall bac
0b50: 6b 20 74 6f 20 69 74 73 20 6f 6c 64 20 73 74 61  k to its old sta
0b60: 74 69 63 20 72 65 73 70 6f 6e 73 65 73 2e 20 20  tic responses.  
0b70: 59 6f 75 20 63 61 6e 20 63 75 73 74 6f 6d 69 7a  You can customiz
0b80: 65 20 74 68 65 6d 20 68 65 72 65 2e 0a 23 20 45  e them here..# E
0b90: 72 72 6f 72 4d 65 73 73 61 67 65 54 69 63 6b 65  rrorMessageTicke
0ba0: 74 20 74 61 6b 65 73 20 61 20 73 74 72 69 6e 67  t takes a string
0bb0: 20 66 6f 72 6d 61 74 20 64 69 63 74 69 6f 6e 61   format dictiona
0bc0: 72 79 20 63 6f 6e 74 61 69 6e 69 6e 67 20 28 6f  ry containing (o
0bd0: 6e 6c 79 29 20 74 68 65 0a 23 20 22 74 69 63 6b  nly) the.# "tick
0be0: 65 74 22 20 6b 65 79 2e 0a 0a 23 20 65 72 72 6f  et" key...# erro
0bf0: 72 5f 6d 65 73 73 61 67 65 20 3d 20 27 3c 68 74  r_message = '<ht
0c00: 6d 6c 3e 3c 62 6f 64 79 3e 3c 68 31 3e 25 73 3c  ml><body><h1>%s<
0c10: 2f 68 31 3e 3c 2f 62 6f 64 79 3e 3c 2f 68 74 6d  /h1></body></htm
0c20: 6c 3e 27 0a 23 20 65 72 72 6f 72 5f 6d 65 73 73  l>'.# error_mess
0c30: 61 67 65 5f 74 69 63 6b 65 74 20 3d 20 27 3c 68  age_ticket = '<h
0c40: 74 6d 6c 3e 3c 62 6f 64 79 3e 3c 68 31 3e 49 6e  tml><body><h1>In
0c50: 74 65 72 6e 61 6c 20 65 72 72 6f 72 3c 2f 68 31  ternal error</h1
0c60: 3e 54 69 63 6b 65 74 20 69 73 73 75 65 64 3a 20  >Ticket issued: 
0c70: 3c 61 20 68 72 65 66 3d 22 2f 61 64 6d 69 6e 2f  <a href="/admin/
0c80: 64 65 66 61 75 6c 74 2f 74 69 63 6b 65 74 2f 25  default/ticket/%
0c90: 28 74 69 63 6b 65 74 29 73 22 20 74 61 72 67 65  (ticket)s" targe
0ca0: 74 3d 22 5f 62 6c 61 6e 6b 22 3e 25 28 74 69 63  t="_blank">%(tic
0cb0: 6b 65 74 29 73 3c 2f 61 3e 3c 2f 62 6f 64 79 3e  ket)s</a></body>
0cc0: 3c 2f 68 74 6d 6c 3e 27 0a 0a 23 20 73 70 65 63  </html>'..# spec
0cd0: 69 66 79 20 61 20 6c 69 73 74 20 6f 66 20 61 70  ify a list of ap
0ce0: 70 73 20 74 68 61 74 20 62 79 70 61 73 73 20 61  ps that bypass a
0cf0: 72 67 73 2d 63 68 65 63 6b 69 6e 67 20 61 6e 64  rgs-checking and
0d00: 20 75 73 65 20 72 65 71 75 65 73 74 2e 72 61 77   use request.raw
0d10: 5f 61 72 67 73 0a 23 0a 23 72 6f 75 74 65 73 5f  _args.#.#routes_
0d20: 61 70 70 73 5f 72 61 77 3d 5b 27 6d 79 61 70 70  apps_raw=['myapp
0d30: 27 5d 0a 23 72 6f 75 74 65 73 5f 61 70 70 73 5f  '].#routes_apps_
0d40: 72 61 77 3d 5b 27 6d 79 61 70 70 27 2c 20 27 6d  raw=['myapp', 'm
0d50: 79 6f 74 68 65 72 61 70 70 27 5d 0a 0a 64 65 66  yotherapp']..def
0d60: 20 5f 5f 72 6f 75 74 65 73 5f 64 6f 63 74 65 73   __routes_doctes
0d70: 74 28 29 3a 0a 20 20 20 20 27 27 27 0a 20 20 20  t():.    '''.   
0d80: 20 44 75 6d 6d 79 20 66 75 6e 63 74 69 6f 6e 20   Dummy function 
0d90: 66 6f 72 20 64 6f 63 74 65 73 74 69 6e 67 20 72  for doctesting r
0da0: 6f 75 74 65 73 2e 70 79 2e 0a 0a 20 20 20 20 55  outes.py...    U
0db0: 73 65 20 66 69 6c 74 65 72 5f 75 72 6c 28 29 20  se filter_url() 
0dc0: 74 6f 20 74 65 73 74 20 69 6e 63 6f 6d 69 6e 67  to test incoming
0dd0: 20 6f 72 20 6f 75 74 67 6f 69 6e 67 20 72 6f 75   or outgoing rou
0de0: 74 65 73 3b 0a 20 20 20 20 66 69 6c 74 65 72 5f  tes;.    filter_
0df0: 65 72 72 28 29 20 66 6f 72 20 65 72 72 6f 72 20  err() for error 
0e00: 72 65 64 69 72 65 63 74 69 6f 6e 2e 0a 0a 20 20  redirection...  
0e10: 20 20 66 69 6c 74 65 72 5f 75 72 6c 28 29 20 61    filter_url() a
0e20: 63 63 65 70 74 73 20 6f 76 65 72 72 69 64 65 73  ccepts overrides
0e30: 20 66 6f 72 20 6d 65 74 68 6f 64 20 61 6e 64 20   for method and 
0e40: 72 65 6d 6f 74 65 20 68 6f 73 74 3a 0a 20 20 20  remote host:.   
0e50: 20 20 20 20 20 66 69 6c 74 65 72 5f 75 72 6c 28       filter_url(
0e60: 75 72 6c 2c 20 6d 65 74 68 6f 64 3d 27 67 65 74  url, method='get
0e70: 27 2c 20 72 65 6d 6f 74 65 3d 27 30 2e 30 2e 30  ', remote='0.0.0
0e80: 2e 30 27 2c 20 6f 75 74 3d 46 61 6c 73 65 29 0a  .0', out=False).
0e90: 0a 20 20 20 20 66 69 6c 74 65 72 5f 65 72 72 28  .    filter_err(
0ea0: 29 20 61 63 63 65 70 74 73 20 6f 76 65 72 72 69  ) accepts overri
0eb0: 64 65 73 20 66 6f 72 20 61 70 70 6c 69 63 61 74  des for applicat
0ec0: 69 6f 6e 20 61 6e 64 20 74 69 63 6b 65 74 3a 0a  ion and ticket:.
0ed0: 20 20 20 20 20 20 20 20 66 69 6c 74 65 72 5f 65          filter_e
0ee0: 72 72 28 73 74 61 74 75 73 2c 20 61 70 70 6c 69  rr(status, appli
0ef0: 63 61 74 69 6f 6e 3d 27 61 70 70 27 2c 20 74 69  cation='app', ti
0f00: 63 6b 65 74 3d 27 74 6b 74 27 29 0a 0a 20 20 20  cket='tkt')..   
0f10: 20 3e 3e 3e 20 69 6d 70 6f 72 74 20 6f 73 0a 20   >>> import os. 
0f20: 20 20 20 3e 3e 3e 20 69 6d 70 6f 72 74 20 67 6c     >>> import gl
0f30: 75 6f 6e 2e 6d 61 69 6e 0a 20 20 20 20 3e 3e 3e  uon.main.    >>>
0f40: 20 66 72 6f 6d 20 67 6c 75 6f 6e 2e 72 65 77 72   from gluon.rewr
0f50: 69 74 65 20 69 6d 70 6f 72 74 20 72 65 67 65 78  ite import regex
0f60: 5f 73 65 6c 65 63 74 2c 20 6c 6f 61 64 2c 20 66  _select, load, f
0f70: 69 6c 74 65 72 5f 75 72 6c 2c 20 72 65 67 65 78  ilter_url, regex
0f80: 5f 66 69 6c 74 65 72 5f 6f 75 74 2c 20 66 69 6c  _filter_out, fil
0f90: 74 65 72 5f 65 72 72 2c 20 63 6f 6d 70 69 6c 65  ter_err, compile
0fa0: 5f 72 65 67 65 78 0a 20 20 20 20 3e 3e 3e 20 72  _regex.    >>> r
0fb0: 65 67 65 78 5f 73 65 6c 65 63 74 28 29 0a 20 20  egex_select().  
0fc0: 20 20 3e 3e 3e 20 6c 6f 61 64 28 72 6f 75 74 65    >>> load(route
0fd0: 73 3d 6f 73 2e 70 61 74 68 2e 62 61 73 65 6e 61  s=os.path.basena
0fe0: 6d 65 28 5f 5f 66 69 6c 65 5f 5f 29 29 0a 0a 20  me(__file__)).. 
0ff0: 20 20 20 3e 3e 3e 20 6f 73 2e 70 61 74 68 2e 72     >>> os.path.r
1000: 65 6c 70 61 74 68 28 66 69 6c 74 65 72 5f 75 72  elpath(filter_ur
1010: 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e  l('http://domain
1020: 2e 63 6f 6d 2f 66 61 76 69 63 6f 6e 2e 69 63 6f  .com/favicon.ico
1030: 27 29 29 0a 20 20 20 20 27 61 70 70 6c 69 63 61  ')).    'applica
1040: 74 69 6f 6e 73 2f 65 78 61 6d 70 6c 65 73 2f 73  tions/examples/s
1050: 74 61 74 69 63 2f 66 61 76 69 63 6f 6e 2e 69 63  tatic/favicon.ic
1060: 6f 27 0a 20 20 20 20 3e 3e 3e 20 6f 73 2e 70 61  o'.    >>> os.pa
1070: 74 68 2e 72 65 6c 70 61 74 68 28 66 69 6c 74 65  th.relpath(filte
1080: 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f  r_url('http://do
1090: 6d 61 69 6e 2e 63 6f 6d 2f 72 6f 62 6f 74 73 2e  main.com/robots.
10a0: 74 78 74 27 29 29 0a 20 20 20 20 27 61 70 70 6c  txt')).    'appl
10b0: 69 63 61 74 69 6f 6e 73 2f 65 78 61 6d 70 6c 65  ications/example
10c0: 73 2f 73 74 61 74 69 63 2f 72 6f 62 6f 74 73 2e  s/static/robots.
10d0: 74 78 74 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c  txt'.    >>> fil
10e0: 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f  ter_url('http://
10f0: 64 6f 6d 61 69 6e 2e 63 6f 6d 27 29 0a 20 20 20  domain.com').   
1100: 20 27 2f 69 6e 69 74 2f 64 65 66 61 75 6c 74 2f   '/init/default/
1110: 69 6e 64 65 78 27 0a 20 20 20 20 3e 3e 3e 20 66  index'.    >>> f
1120: 69 6c 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a  ilter_url('http:
1130: 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 27 29 0a  //domain.com/').
1140: 20 20 20 20 27 2f 69 6e 69 74 2f 64 65 66 61 75      '/init/defau
1150: 6c 74 2f 69 6e 64 65 78 27 0a 20 20 20 20 3e 3e  lt/index'.    >>
1160: 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74  > filter_url('ht
1170: 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f  tp://domain.com/
1180: 69 6e 69 74 2f 64 65 66 61 75 6c 74 2f 66 63 6e  init/default/fcn
1190: 27 29 0a 20 20 20 20 27 2f 69 6e 69 74 2f 64 65  ').    '/init/de
11a0: 66 61 75 6c 74 2f 66 63 6e 27 0a 20 20 20 20 3e  fault/fcn'.    >
11b0: 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68  >> filter_url('h
11c0: 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d  ttp://domain.com
11d0: 2f 69 6e 69 74 2f 64 65 66 61 75 6c 74 2f 66 63  /init/default/fc
11e0: 6e 2f 27 29 0a 20 20 20 20 27 2f 69 6e 69 74 2f  n/').    '/init/
11f0: 64 65 66 61 75 6c 74 2f 66 63 6e 27 0a 20 20 20  default/fcn'.   
1200: 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28   >>> filter_url(
1210: 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63  'http://domain.c
1220: 6f 6d 2f 61 70 70 2f 63 74 72 2f 66 63 6e 27 29  om/app/ctr/fcn')
1230: 0a 20 20 20 20 27 2f 61 70 70 2f 63 74 72 2f 66  .    '/app/ctr/f
1240: 63 6e 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74  cn'.    >>> filt
1250: 65 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64  er_url('http://d
1260: 6f 6d 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74  omain.com/app/ct
1270: 72 2f 66 63 6e 2f 61 72 67 31 27 29 0a 20 20 20  r/fcn/arg1').   
1280: 20 22 2f 61 70 70 2f 63 74 72 2f 66 63 6e 20 5b   "/app/ctr/fcn [
1290: 27 61 72 67 31 27 5d 22 0a 20 20 20 20 3e 3e 3e  'arg1']".    >>>
12a0: 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74 74   filter_url('htt
12b0: 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 61  p://domain.com/a
12c0: 70 70 2f 63 74 72 2f 66 63 6e 2f 61 72 67 31 2f  pp/ctr/fcn/arg1/
12d0: 27 29 0a 20 20 20 20 22 2f 61 70 70 2f 63 74 72  ').    "/app/ctr
12e0: 2f 66 63 6e 20 5b 27 61 72 67 31 27 5d 22 0a 20  /fcn ['arg1']". 
12f0: 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72     >>> filter_ur
1300: 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e  l('http://domain
1310: 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f 66 63 6e  .com/app/ctr/fcn
1320: 2f 61 72 67 31 2f 2f 27 29 0a 20 20 20 20 22 2f  /arg1//').    "/
1330: 61 70 70 2f 63 74 72 2f 66 63 6e 20 5b 27 61 72  app/ctr/fcn ['ar
1340: 67 31 27 2c 20 27 27 5d 22 0a 20 20 20 20 3e 3e  g1', '']".    >>
1350: 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74  > filter_url('ht
1360: 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f  tp://domain.com/
1370: 61 70 70 2f 63 74 72 2f 66 63 6e 2f 2f 61 72 67  app/ctr/fcn//arg
1380: 31 27 29 0a 20 20 20 20 22 2f 61 70 70 2f 63 74  1').    "/app/ct
1390: 72 2f 66 63 6e 20 5b 27 27 2c 20 27 61 72 67 31  r/fcn ['', 'arg1
13a0: 27 5d 22 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74  ']".    >>> filt
13b0: 65 72 5f 75 72 6c 28 27 48 54 54 50 3a 2f 2f 44  er_url('HTTP://D
13c0: 4f 4d 41 49 4e 2e 43 4f 4d 2f 61 70 70 2f 63 74  OMAIN.COM/app/ct
13d0: 72 2f 66 63 6e 27 29 0a 20 20 20 20 27 2f 61 70  r/fcn').    '/ap
13e0: 70 2f 63 74 72 2f 66 63 6e 27 0a 20 20 20 20 3e  p/ctr/fcn'.    >
13f0: 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68  >> filter_url('h
1400: 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d  ttp://domain.com
1410: 2f 61 70 70 2f 63 74 72 2f 66 63 6e 3f 71 75 65  /app/ctr/fcn?que
1420: 72 79 27 29 0a 20 20 20 20 27 2f 61 70 70 2f 63  ry').    '/app/c
1430: 74 72 2f 66 63 6e 20 3f 71 75 65 72 79 27 0a 20  tr/fcn ?query'. 
1440: 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72     >>> filter_ur
1450: 6c 28 27 68 74 74 70 3a 2f 2f 6f 74 68 65 72 64  l('http://otherd
1460: 6f 6d 61 69 6e 2e 63 6f 6d 2f 66 63 6e 27 29 0a  omain.com/fcn').
1470: 20 20 20 20 27 2f 61 70 70 2f 63 74 72 2f 66 63      '/app/ctr/fc
1480: 6e 27 0a 20 20 20 20 3e 3e 3e 20 72 65 67 65 78  n'.    >>> regex
1490: 5f 66 69 6c 74 65 72 5f 6f 75 74 28 27 2f 61 70  _filter_out('/ap
14a0: 70 2f 63 74 72 2f 66 63 6e 27 29 0a 20 20 20 20  p/ctr/fcn').    
14b0: 27 2f 63 74 72 2f 66 63 6e 27 0a 20 20 20 20 3e  '/ctr/fcn'.    >
14c0: 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68  >> filter_url('h
14d0: 74 74 70 73 3a 2f 2f 6f 74 68 65 72 64 6f 6d 61  ttps://otherdoma
14e0: 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f 66  in.com/app/ctr/f
14f0: 63 6e 27 2c 20 6f 75 74 3d 54 72 75 65 29 0a 20  cn', out=True). 
1500: 20 20 20 27 2f 63 74 72 2f 66 63 6e 27 0a 20 20     '/ctr/fcn'.  
1510: 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c    >>> filter_url
1520: 28 27 68 74 74 70 73 3a 2f 2f 6f 74 68 65 72 64  ('https://otherd
1530: 6f 6d 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74  omain.com/app/ct
1540: 72 2f 66 63 6e 2f 61 72 67 31 2f 2f 27 2c 20 6f  r/fcn/arg1//', o
1550: 75 74 3d 54 72 75 65 29 0a 20 20 20 20 27 2f 63  ut=True).    '/c
1560: 74 72 2f 66 63 6e 2f 61 72 67 31 2f 2f 27 0a 20  tr/fcn/arg1//'. 
1570: 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72     >>> filter_ur
1580: 6c 28 27 68 74 74 70 3a 2f 2f 6f 74 68 65 72 64  l('http://otherd
1590: 6f 6d 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74  omain.com/app/ct
15a0: 72 2f 66 63 6e 27 2c 20 6f 75 74 3d 54 72 75 65  r/fcn', out=True
15b0: 29 0a 20 20 20 20 27 2f 66 63 6e 27 0a 20 20 20  ).    '/fcn'.   
15c0: 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28   >>> filter_url(
15d0: 27 68 74 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d  'http://otherdom
15e0: 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f  ain.com/app/ctr/
15f0: 66 63 6e 3f 71 75 65 72 79 27 2c 20 6f 75 74 3d  fcn?query', out=
1600: 54 72 75 65 29 0a 20 20 20 20 27 2f 66 63 6e 3f  True).    '/fcn?
1610: 71 75 65 72 79 27 0a 20 20 20 20 3e 3e 3e 20 66  query'.    >>> f
1620: 69 6c 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a  ilter_url('http:
1630: 2f 2f 6f 74 68 65 72 64 6f 6d 61 69 6e 2e 63 6f  //otherdomain.co
1640: 6d 2f 61 70 70 2f 63 74 72 2f 66 63 6e 23 61 6e  m/app/ctr/fcn#an
1650: 63 68 6f 72 27 2c 20 6f 75 74 3d 54 72 75 65 29  chor', out=True)
1660: 0a 20 20 20 20 27 2f 66 63 6e 23 61 6e 63 68 6f  .    '/fcn#ancho
1670: 72 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65  r'.    >>> filte
1680: 72 5f 65 72 72 28 32 30 30 29 0a 20 20 20 20 32  r_err(200).    2
1690: 30 30 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65  00.    >>> filte
16a0: 72 5f 65 72 72 28 33 39 39 29 0a 20 20 20 20 33  r_err(399).    3
16b0: 39 39 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65  99.    >>> filte
16c0: 72 5f 65 72 72 28 34 30 30 29 0a 20 20 20 20 34  r_err(400).    4
16d0: 30 30 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65  00.    >>> filte
16e0: 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f  r_url('http://do
16f0: 6d 61 69 6e 2e 63 6f 6d 2f 77 65 6c 63 6f 6d 65  main.com/welcome
1700: 27 2c 20 61 70 70 3d 54 72 75 65 29 0a 20 20 20  ', app=True).   
1710: 20 27 77 65 6c 63 6f 6d 65 27 0a 20 20 20 20 3e   'welcome'.    >
1720: 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68  >> filter_url('h
1730: 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d  ttp://domain.com
1740: 2f 27 2c 20 61 70 70 3d 54 72 75 65 29 0a 20 20  /', app=True).  
1750: 20 20 27 6d 79 61 70 70 27 0a 20 20 20 20 3e 3e    'myapp'.    >>
1760: 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74  > filter_url('ht
1770: 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 27  tp://domain.com'
1780: 2c 20 61 70 70 3d 54 72 75 65 29 0a 20 20 20 20  , app=True).    
1790: 27 6d 79 61 70 70 27 0a 20 20 20 20 3e 3e 3e 20  'myapp'.    >>> 
17a0: 63 6f 6d 70 69 6c 65 5f 72 65 67 65 78 28 27 2e  compile_regex('.
17b0: 2a 68 74 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d  *http://otherdom
17c0: 61 69 6e 2e 63 6f 6d 2e 2a 20 28 3f 50 3c 61 6e  ain.com.* (?P<an
17d0: 79 3e 2e 2a 29 27 2c 20 27 2f 61 70 70 2f 63 74  y>.*)', '/app/ct
17e0: 72 5c 67 3c 61 6e 79 3e 27 29 5b 30 5d 2e 70 61  r\g<any>')[0].pa
17f0: 74 74 65 72 6e 0a 20 20 20 20 27 5e 2e 2a 68 74  ttern.    '^.*ht
1800: 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d 61 69 6e  tp://otherdomain
1810: 2e 63 6f 6d 2e 2a 20 28 3f 50 3c 61 6e 79 3e 2e  .com.* (?P<any>.
1820: 2a 29 24 27 0a 20 20 20 20 3e 3e 3e 20 63 6f 6d  *)$'.    >>> com
1830: 70 69 6c 65 5f 72 65 67 65 78 28 27 2e 2a 68 74  pile_regex('.*ht
1840: 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d 61 69 6e  tp://otherdomain
1850: 2e 63 6f 6d 2e 2a 20 28 3f 50 3c 61 6e 79 3e 2e  .com.* (?P<any>.
1860: 2a 29 27 2c 20 27 2f 61 70 70 2f 63 74 72 5c 67  *)', '/app/ctr\g
1870: 3c 61 6e 79 3e 27 29 5b 31 5d 0a 20 20 20 20 27  <any>')[1].    '
1880: 2f 61 70 70 2f 63 74 72 5c 5c 5c 5c 67 3c 61 6e  /app/ctr\\\\g<an
1890: 79 3e 27 0a 20 20 20 20 3e 3e 3e 20 63 6f 6d 70  y>'.    >>> comp
18a0: 69 6c 65 5f 72 65 67 65 78 28 27 2f 24 63 2f 24  ile_regex('/$c/$
18b0: 66 27 2c 20 27 2f 69 6e 69 74 2f 24 63 2f 24 66  f', '/init/$c/$f
18c0: 27 29 5b 30 5d 2e 70 61 74 74 65 72 6e 0a 20 20  ')[0].pattern.  
18d0: 20 20 27 5e 2e 2a 3f 3a 68 74 74 70 73 3f 3a 2f    '^.*?:https?:/
18e0: 2f 5b 5e 3a 2f 5d 2b 3a 5b 61 2d 7a 5d 2b 20 2f  /[^:/]+:[a-z]+ /
18f0: 28 3f 50 3c 63 3e 5c 5c 5c 5c 77 2b 29 2f 28 3f  (?P<c>\\\\w+)/(?
1900: 50 3c 66 3e 5c 5c 5c 5c 77 2b 29 24 27 0a 20 20  P<f>\\\\w+)$'.  
1910: 20 20 3e 3e 3e 20 63 6f 6d 70 69 6c 65 5f 72 65    >>> compile_re
1920: 67 65 78 28 27 2f 24 63 2f 24 66 27 2c 20 27 2f  gex('/$c/$f', '/
1930: 69 6e 69 74 2f 24 63 2f 24 66 27 29 5b 31 5d 0a  init/$c/$f')[1].
1940: 20 20 20 20 27 2f 69 6e 69 74 2f 5c 5c 5c 5c 67      '/init/\\\\g
1950: 3c 63 3e 2f 5c 5c 5c 5c 67 3c 66 3e 27 0a 20 20  <c>/\\\\g<f>'.  
1960: 20 20 27 27 27 0a 20 20 20 20 70 61 73 73 0a 0a    '''.    pass..
1970: 69 66 20 5f 5f 6e 61 6d 65 5f 5f 20 3d 3d 20 27  if __name__ == '
1980: 5f 5f 6d 61 69 6e 5f 5f 27 3a 0a 20 20 20 20 69  __main__':.    i
1990: 6d 70 6f 72 74 20 64 6f 63 74 65 73 74 0a 20 20  mport doctest.  
19a0: 20 20 64 6f 63 74 65 73 74 2e 74 65 73 74 6d 6f    doctest.testmo
19b0: 64 28 29 0a 0a                                   d()..