MobileBlur

Hex Artifact Content
Login

Artifact b42c3be42eae9344b458384db881efa52b51dcab:


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 6d  application = 'm
00e0: 6f 62 69 6c 65 62 6c 75 72 27 20 20 20 20 23 20  obileblur'    # 
00f0: 6f 72 64 69 6e 61 72 69 6c 79 20 73 65 74 20 69  ordinarily set i
0100: 6e 20 62 61 73 65 20 72 6f 75 74 65 73 2e 70 79  n base routes.py
0110: 0a 64 65 66 61 75 6c 74 5f 63 6f 6e 74 72 6f 6c  .default_control
0120: 6c 65 72 20 3d 20 27 64 65 66 61 75 6c 74 27 20  ler = 'default' 
0130: 20 23 20 6f 72 64 69 6e 61 72 69 6c 79 20 73 65   # ordinarily se
0140: 74 20 69 6e 20 61 70 70 2d 73 70 65 63 69 66 69  t in app-specifi
0150: 63 20 72 6f 75 74 65 73 2e 70 79 0a 64 65 66 61  c routes.py.defa
0160: 75 6c 74 5f 66 75 6e 63 74 69 6f 6e 20 3d 20 27  ult_function = '
0170: 69 6e 64 65 78 27 20 20 20 20 20 20 23 20 6f 72  index'      # or
0180: 64 69 6e 61 72 69 6c 79 20 73 65 74 20 69 6e 20  dinarily set in 
0190: 61 70 70 2d 73 70 65 63 69 66 69 63 20 72 6f 75  app-specific rou
01a0: 74 65 73 2e 70 79 0a 0a 23 20 72 6f 75 74 65 73  tes.py..# routes
01b0: 5f 61 70 70 20 69 73 20 61 20 74 75 70 6c 65 20  _app is a tuple 
01c0: 6f 66 20 74 75 70 6c 65 73 2e 20 20 54 68 65 20  of tuples.  The 
01d0: 66 69 72 73 74 20 69 74 65 6d 20 69 6e 20 65 61  first item in ea
01e0: 63 68 20 69 73 20 61 20 72 65 67 65 78 70 20 74  ch is a regexp t
01f0: 68 61 74 20 77 69 6c 6c 0a 23 20 62 65 20 75 73  hat will.# be us
0200: 65 64 20 74 6f 20 6d 61 74 63 68 20 74 68 65 20  ed to match the 
0210: 69 6e 63 6f 6d 69 6e 67 20 72 65 71 75 65 73 74  incoming request
0220: 20 55 52 4c 2e 20 54 68 65 20 73 65 63 6f 6e 64   URL. The second
0230: 20 69 74 65 6d 20 69 6e 20 74 68 65 20 74 75 70   item in the tup
0240: 6c 65 20 69 73 0a 23 20 61 6e 20 61 70 70 6c 69  le is.# an appli
0250: 63 61 74 69 6f 6e 6e 61 6d 65 2e 20 20 54 68 69  cationname.  Thi
0260: 73 20 6d 65 63 68 61 6e 69 73 6d 20 61 6c 6c 6f  s mechanism allo
0270: 77 73 20 79 6f 75 20 74 6f 20 73 70 65 63 69 66  ws you to specif
0280: 79 20 74 68 65 20 75 73 65 20 6f 66 20 61 6e 0a  y the use of an.
0290: 23 20 61 70 70 2d 73 70 65 63 69 66 69 63 20 72  # app-specific r
02a0: 6f 75 74 65 73 2e 70 79 2e 20 54 68 69 73 20 65  outes.py. This e
02b0: 6e 74 72 79 20 69 73 20 6d 65 61 6e 69 6e 67 66  ntry is meaningf
02c0: 75 6c 20 6f 6e 6c 79 20 69 6e 20 74 68 65 20 62  ul only in the b
02d0: 61 73 65 20 72 6f 75 74 65 73 2e 70 79 2e 0a 23  ase routes.py..#
02e0: 0a 23 20 45 78 61 6d 70 6c 65 3a 20 73 75 70 70  .# Example: supp
02f0: 6f 72 74 20 77 65 6c 63 6f 6d 65 2c 20 61 64 6d  ort welcome, adm
0300: 69 6e 2c 20 61 70 70 20 61 6e 64 20 6d 79 61 70  in, app and myap
0310: 70 2c 20 77 69 74 68 20 6d 79 61 70 70 20 74 68  p, with myapp th
0320: 65 20 64 65 66 61 75 6c 74 3a 0a 0a 0a 72 6f 75  e default:...rou
0330: 74 65 73 5f 61 70 70 20 3d 20 28 28 72 27 2f 28  tes_app = ((r'/(
0340: 3f 50 3c 61 70 70 3e 77 65 6c 63 6f 6d 65 7c 61  ?P<app>welcome|a
0350: 64 6d 69 6e 7c 61 70 70 29 5c 62 2e 2a 27 2c 20  dmin|app)\b.*', 
0360: 72 27 5c 67 3c 61 70 70 3e 27 29 2c 0a 20 20 20  r'\g<app>'),.   
0370: 20 20 20 20 20 20 20 20 20 20 20 28 72 27 28 2e             (r'(.
0380: 2a 29 27 2c 20 72 27 6d 79 61 70 70 27 29 2c 0a  *)', r'myapp'),.
0390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28 72                (r
03a0: 27 2f 3f 28 2e 2a 29 27 2c 20 72 27 6d 79 61 70  '/?(.*)', r'myap
03b0: 70 27 29 29 0a 0a 23 20 72 6f 75 74 65 73 5f 69  p'))..# routes_i
03c0: 6e 20 69 73 20 61 20 74 75 70 6c 65 20 6f 66 20  n is a tuple of 
03d0: 74 75 70 6c 65 73 2e 20 20 54 68 65 20 66 69 72  tuples.  The fir
03e0: 73 74 20 69 74 65 6d 20 69 6e 20 65 61 63 68 20  st item in each 
03f0: 69 73 20 61 20 72 65 67 65 78 70 20 74 68 61 74  is a regexp that
0400: 20 77 69 6c 6c 0a 23 20 62 65 20 75 73 65 64 20   will.# be used 
0410: 74 6f 20 6d 61 74 63 68 20 74 68 65 20 69 6e 63  to match the inc
0420: 6f 6d 69 6e 67 20 72 65 71 75 65 73 74 20 55 52  oming request UR
0430: 4c 2e 20 54 68 65 20 73 65 63 6f 6e 64 20 69 74  L. The second it
0440: 65 6d 20 69 6e 20 74 68 65 20 74 75 70 6c 65 20  em in the tuple 
0450: 69 73 0a 23 20 77 68 61 74 20 69 74 20 77 69 6c  is.# what it wil
0460: 6c 20 62 65 20 72 65 70 6c 61 63 65 64 20 77 69  l be replaced wi
0470: 74 68 2e 20 20 54 68 69 73 20 6d 65 63 68 61 6e  th.  This mechan
0480: 69 73 6d 20 61 6c 6c 6f 77 73 20 79 6f 75 20 74  ism allows you t
0490: 6f 20 72 65 64 69 72 65 63 74 20 69 6e 63 6f 6d  o redirect incom
04a0: 69 6e 67 0a 23 20 72 6f 75 74 65 73 20 74 6f 20  ing.# routes to 
04b0: 64 69 66 66 65 72 65 6e 74 20 77 65 62 32 70 79  different web2py
04c0: 20 6c 6f 63 61 74 69 6f 6e 73 0a 23 0a 23 20 45   locations.#.# E
04d0: 78 61 6d 70 6c 65 3a 20 49 66 20 79 6f 75 20 77  xample: If you w
04e0: 69 73 68 20 66 6f 72 20 79 6f 75 72 20 65 6e 74  ish for your ent
04f0: 69 72 65 20 77 65 62 73 69 74 65 20 74 6f 20 75  ire website to u
0500: 73 65 20 69 6e 69 74 27 73 20 73 74 61 74 69 63  se init's static
0510: 20 64 69 72 65 63 74 6f 72 79 3a 0a 23 0a 23 20   directory:.#.# 
0520: 20 20 72 6f 75 74 65 73 5f 69 6e 3d 28 20 28 72    routes_in=( (r
0530: 27 2f 73 74 61 74 69 63 2f 28 3f 50 3c 66 69 6c  '/static/(?P<fil
0540: 65 3e 5b 5c 77 2e 2f 2d 5d 2b 29 27 2c 20 72 27  e>[\w./-]+)', r'
0550: 2f 69 6e 69 74 2f 73 74 61 74 69 63 2f 5c 67 3c  /init/static/\g<
0560: 66 69 6c 65 3e 27 29 20 29 0a 23 0a 0a 72 6f 75  file>') ).#..rou
0570: 74 65 73 5f 69 6e 20 3d 20 28 28 72 27 2e 2a 3a  tes_in = ((r'.*:
0580: 2f 66 61 76 69 63 6f 6e 2e 69 63 6f 27 2c 20 72  /favicon.ico', r
0590: 27 2f 65 78 61 6d 70 6c 65 73 2f 73 74 61 74 69  '/examples/stati
05a0: 63 2f 66 61 76 69 63 6f 6e 2e 69 63 6f 27 29 2c  c/favicon.ico'),
05b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 28 72  .             (r
05c0: 27 2e 2a 3a 2f 72 6f 62 6f 74 73 2e 74 78 74 27  '.*:/robots.txt'
05d0: 2c 20 72 27 2f 65 78 61 6d 70 6c 65 73 2f 73 74  , r'/examples/st
05e0: 61 74 69 63 2f 72 6f 62 6f 74 73 2e 74 78 74 27  atic/robots.txt'
05f0: 29 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ),.             
0600: 28 28 72 27 2e 2a 68 74 74 70 3a 2f 2f 6f 74 68  ((r'.*http://oth
0610: 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2e 2a 20 28  erdomain.com.* (
0620: 3f 50 3c 61 6e 79 3e 2e 2a 29 27 2c 20 72 27 2f  ?P<any>.*)', r'/
0630: 61 70 70 2f 63 74 72 5c 67 3c 61 6e 79 3e 27 29  app/ctr\g<any>')
0640: 29 29 0a 0a 23 20 72 6f 75 74 65 73 5f 6f 75 74  ))..# routes_out
0650: 2c 20 6c 69 6b 65 20 72 6f 75 74 65 73 5f 69 6e  , like routes_in
0660: 20 74 72 61 6e 73 6c 61 74 65 73 20 55 52 4c 20   translates URL 
0670: 70 61 74 68 73 20 63 72 65 61 74 65 64 20 77 69  paths created wi
0680: 74 68 20 74 68 65 20 77 65 62 32 70 79 20 55 52  th the web2py UR
0690: 4c 28 29 0a 23 20 66 75 6e 63 74 69 6f 6e 20 69  L().# function i
06a0: 6e 20 74 68 65 20 73 61 6d 65 20 6d 61 6e 6e 65  n the same manne
06b0: 72 20 74 68 61 74 20 72 6f 75 74 65 5f 69 6e 20  r that route_in 
06c0: 74 72 61 6e 73 6c 61 74 65 73 20 69 6e 62 6f 75  translates inbou
06d0: 6e 64 20 55 52 4c 20 70 61 74 68 73 2e 0a 23 0a  nd URL paths..#.
06e0: 0a 72 6f 75 74 65 73 5f 6f 75 74 20 3d 20 28 28  .routes_out = ((
06f0: 72 27 2e 2a 68 74 74 70 3a 2f 2f 6f 74 68 65 72  r'.*http://other
0700: 64 6f 6d 61 69 6e 2e 63 6f 6d 2e 2a 20 2f 61 70  domain.com.* /ap
0710: 70 2f 63 74 72 28 3f 50 3c 61 6e 79 3e 2e 2a 29  p/ctr(?P<any>.*)
0720: 27 2c 20 72 27 5c 67 3c 61 6e 79 3e 27 29 2c 0a  ', r'\g<any>'),.
0730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28 72                (r
0740: 27 2f 61 70 70 28 3f 50 3c 61 6e 79 3e 2e 2a 29  '/app(?P<any>.*)
0750: 27 2c 20 72 27 5c 67 3c 61 6e 79 3e 27 29 29 0a  ', r'\g<any>')).
0760: 0a 23 20 45 72 72 6f 72 2d 68 61 6e 64 6c 69 6e  .# Error-handlin
0770: 67 20 72 65 64 69 72 65 63 74 73 20 61 6c 6c 20  g redirects all 
0780: 48 54 54 50 20 65 72 72 6f 72 73 20 28 73 74 61  HTTP errors (sta
0790: 74 75 73 20 63 6f 64 65 73 20 3e 3d 20 34 30 30  tus codes >= 400
07a0: 29 20 74 6f 20 61 20 73 70 65 63 69 66 69 65 64  ) to a specified
07b0: 0a 23 20 70 61 74 68 2e 20 20 49 66 20 79 6f 75  .# path.  If you
07c0: 20 77 69 73 68 20 74 6f 20 75 73 65 20 65 72 72   wish to use err
07d0: 6f 72 2d 68 61 6e 64 6c 69 6e 67 20 72 65 64 69  or-handling redi
07e0: 72 65 63 74 73 2c 20 75 6e 63 6f 6d 6d 65 6e 74  rects, uncomment
07f0: 20 74 68 65 20 74 75 70 6c 65 0a 23 20 62 65 6c   the tuple.# bel
0800: 6f 77 2e 20 20 59 6f 75 20 63 61 6e 20 63 75 73  ow.  You can cus
0810: 74 6f 6d 69 7a 65 20 72 65 73 70 6f 6e 73 65 73  tomize responses
0820: 20 62 79 20 61 64 64 69 6e 67 20 61 20 74 75 70   by adding a tup
0830: 6c 65 20 65 6e 74 72 79 20 77 69 74 68 20 74 68  le entry with th
0840: 65 20 66 69 72 73 74 0a 23 20 76 61 6c 75 65 20  e first.# value 
0850: 69 6e 20 27 61 70 70 4e 61 6d 65 2f 48 54 54 50  in 'appName/HTTP
0860: 73 74 61 74 75 73 43 6f 64 65 27 20 66 6f 72 6d  statusCode' form
0870: 61 74 2e 20 28 20 4f 6e 6c 79 20 48 54 54 50 20  at. ( Only HTTP 
0880: 63 6f 64 65 73 20 3e 3d 20 34 30 30 20 61 72 65  codes >= 400 are
0890: 0a 23 20 72 6f 75 74 65 64 2e 20 29 20 61 6e 64  .# routed. ) and
08a0: 20 74 68 65 20 76 61 6c 75 65 20 61 73 20 61 20   the value as a 
08b0: 70 61 74 68 20 74 6f 20 72 65 64 69 72 65 63 74  path to redirect
08c0: 20 74 68 65 20 75 73 65 72 20 74 6f 2e 20 20 59   the user to.  Y
08d0: 6f 75 20 6d 61 79 20 61 6c 73 6f 20 75 73 65 0a  ou may also use.
08e0: 23 20 27 2a 27 20 61 73 20 61 20 77 69 6c 64 63  # '*' as a wildc
08f0: 61 72 64 2e 0a 23 0a 23 20 54 68 65 20 65 72 72  ard..#.# The err
0900: 6f 72 20 68 61 6e 64 6c 69 6e 67 20 70 61 67 65  or handling page
0910: 20 69 73 20 61 6c 73 6f 20 70 61 73 73 65 64 20   is also passed 
0920: 74 68 65 20 65 72 72 6f 72 20 63 6f 64 65 20 61  the error code a
0930: 6e 64 20 74 69 63 6b 65 74 20 61 73 0a 23 20 76  nd ticket as.# v
0940: 61 72 69 61 62 6c 65 73 2e 20 20 54 72 61 63 65  ariables.  Trace
0950: 62 61 63 6b 20 69 6e 66 6f 72 6d 61 74 69 6f 6e  back information
0960: 20 77 69 6c 6c 20 62 65 20 73 74 6f 72 65 64 20   will be stored 
0970: 69 6e 20 74 68 65 20 74 69 63 6b 65 74 2e 0a 23  in the ticket..#
0980: 0a 23 20 72 6f 75 74 65 73 5f 6f 6e 65 72 72 6f  .# routes_onerro
0990: 72 20 3d 20 5b 0a 23 20 20 20 20 20 28 72 27 69  r = [.#     (r'i
09a0: 6e 69 74 2f 34 30 30 27 2c 20 72 27 2f 69 6e 69  nit/400', r'/ini
09b0: 74 2f 64 65 66 61 75 6c 74 2f 6c 6f 67 69 6e 27  t/default/login'
09c0: 29 0a 23 20 20 20 20 2c 28 72 27 69 6e 69 74 2f  ).#    ,(r'init/
09d0: 2a 27 2c 20 72 27 2f 69 6e 69 74 2f 73 74 61 74  *', r'/init/stat
09e0: 69 63 2f 66 61 69 6c 2e 68 74 6d 6c 27 29 0a 23  ic/fail.html').#
09f0: 20 20 20 20 2c 28 72 27 2a 2f 34 30 34 27 2c 20      ,(r'*/404', 
0a00: 72 27 2f 69 6e 69 74 2f 73 74 61 74 69 63 2f 63  r'/init/static/c
0a10: 61 6e 74 66 69 6e 64 2e 68 74 6d 6c 27 29 0a 23  antfind.html').#
0a20: 20 20 20 20 2c 28 72 27 2a 2f 2a 27 2c 20 72 27      ,(r'*/*', r'
0a30: 2f 69 6e 69 74 2f 65 72 72 6f 72 2f 69 6e 64 65  /init/error/inde
0a40: 78 27 29 0a 23 20 5d 0a 0a 23 20 73 70 65 63 69  x').# ]..# speci
0a50: 66 79 20 61 63 74 69 6f 6e 20 69 6e 20 63 68 61  fy action in cha
0a60: 72 67 65 20 6f 66 20 65 72 72 6f 72 20 68 61 6e  rge of error han
0a70: 64 6c 69 6e 67 0a 23 0a 23 20 65 72 72 6f 72 5f  dling.#.# error_
0a80: 68 61 6e 64 6c 65 72 20 3d 20 64 69 63 74 28 61  handler = dict(a
0a90: 70 70 6c 69 63 61 74 69 6f 6e 3d 27 65 72 72 6f  pplication='erro
0aa0: 72 27 2c 0a 23 20 20 20 20 20 20 20 20 20 20 20  r',.#           
0ab0: 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 74 72             contr
0ac0: 6f 6c 6c 65 72 3d 27 64 65 66 61 75 6c 74 27 2c  oller='default',
0ad0: 0a 23 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .#              
0ae0: 20 20 20 20 20 20 20 20 66 75 6e 63 74 69 6f 6e          function
0af0: 3d 27 69 6e 64 65 78 27 29 0a 0a 23 20 49 6e 20  ='index')..# In 
0b00: 74 68 65 20 65 76 65 6e 74 20 74 68 61 74 20 74  the event that t
0b10: 68 65 20 65 72 72 6f 72 2d 68 61 6e 64 6c 69 6e  he error-handlin
0b20: 67 20 70 61 67 65 20 69 74 73 65 6c 66 20 72 65  g page itself re
0b30: 74 75 72 6e 73 20 61 6e 20 65 72 72 6f 72 2c 20  turns an error, 
0b40: 77 65 62 32 70 79 20 77 69 6c 6c 0a 23 20 66 61  web2py will.# fa
0b50: 6c 6c 20 62 61 63 6b 20 74 6f 20 69 74 73 20 6f  ll back to its o
0b60: 6c 64 20 73 74 61 74 69 63 20 72 65 73 70 6f 6e  ld static respon
0b70: 73 65 73 2e 20 20 59 6f 75 20 63 61 6e 20 63 75  ses.  You can cu
0b80: 73 74 6f 6d 69 7a 65 20 74 68 65 6d 20 68 65 72  stomize them her
0b90: 65 2e 0a 23 20 45 72 72 6f 72 4d 65 73 73 61 67  e..# ErrorMessag
0ba0: 65 54 69 63 6b 65 74 20 74 61 6b 65 73 20 61 20  eTicket takes a 
0bb0: 73 74 72 69 6e 67 20 66 6f 72 6d 61 74 20 64 69  string format di
0bc0: 63 74 69 6f 6e 61 72 79 20 63 6f 6e 74 61 69 6e  ctionary contain
0bd0: 69 6e 67 20 28 6f 6e 6c 79 29 20 74 68 65 0a 23  ing (only) the.#
0be0: 20 22 74 69 63 6b 65 74 22 20 6b 65 79 2e 0a 0a   "ticket" key...
0bf0: 23 20 65 72 72 6f 72 5f 6d 65 73 73 61 67 65 20  # error_message 
0c00: 3d 20 27 3c 68 74 6d 6c 3e 3c 62 6f 64 79 3e 3c  = '<html><body><
0c10: 68 31 3e 25 73 3c 2f 68 31 3e 3c 2f 62 6f 64 79  h1>%s</h1></body
0c20: 3e 3c 2f 68 74 6d 6c 3e 27 0a 23 20 65 72 72 6f  ></html>'.# erro
0c30: 72 5f 6d 65 73 73 61 67 65 5f 74 69 63 6b 65 74  r_message_ticket
0c40: 20 3d 20 27 3c 68 74 6d 6c 3e 3c 62 6f 64 79 3e   = '<html><body>
0c50: 3c 68 31 3e 49 6e 74 65 72 6e 61 6c 20 65 72 72  <h1>Internal err
0c60: 6f 72 3c 2f 68 31 3e 54 69 63 6b 65 74 20 69 73  or</h1>Ticket is
0c70: 73 75 65 64 3a 20 3c 61 20 68 72 65 66 3d 22 2f  sued: <a href="/
0c80: 61 64 6d 69 6e 2f 64 65 66 61 75 6c 74 2f 74 69  admin/default/ti
0c90: 63 6b 65 74 2f 25 28 74 69 63 6b 65 74 29 73 22  cket/%(ticket)s"
0ca0: 20 74 61 72 67 65 74 3d 22 5f 62 6c 61 6e 6b 22   target="_blank"
0cb0: 3e 25 28 74 69 63 6b 65 74 29 73 3c 2f 61 3e 3c  >%(ticket)s</a><
0cc0: 2f 62 6f 64 79 3e 3c 2f 68 74 6d 6c 3e 27 0a 0a  /body></html>'..
0cd0: 23 20 73 70 65 63 69 66 79 20 61 20 6c 69 73 74  # specify a list
0ce0: 20 6f 66 20 61 70 70 73 20 74 68 61 74 20 62 79   of apps that by
0cf0: 70 61 73 73 20 61 72 67 73 2d 63 68 65 63 6b 69  pass args-checki
0d00: 6e 67 20 61 6e 64 20 75 73 65 20 72 65 71 75 65  ng and use reque
0d10: 73 74 2e 72 61 77 5f 61 72 67 73 0a 23 0a 23 72  st.raw_args.#.#r
0d20: 6f 75 74 65 73 5f 61 70 70 73 5f 72 61 77 3d 5b  outes_apps_raw=[
0d30: 27 6d 79 61 70 70 27 5d 0a 23 72 6f 75 74 65 73  'myapp'].#routes
0d40: 5f 61 70 70 73 5f 72 61 77 3d 5b 27 6d 79 61 70  _apps_raw=['myap
0d50: 70 27 2c 20 27 6d 79 6f 74 68 65 72 61 70 70 27  p', 'myotherapp'
0d60: 5d 0a 0a 64 65 66 20 5f 5f 72 6f 75 74 65 73 5f  ]..def __routes_
0d70: 64 6f 63 74 65 73 74 28 29 3a 0a 20 20 20 20 27  doctest():.    '
0d80: 27 27 0a 20 20 20 20 44 75 6d 6d 79 20 66 75 6e  ''.    Dummy fun
0d90: 63 74 69 6f 6e 20 66 6f 72 20 64 6f 63 74 65 73  ction for doctes
0da0: 74 69 6e 67 20 72 6f 75 74 65 73 2e 70 79 2e 0a  ting routes.py..
0db0: 0a 20 20 20 20 55 73 65 20 66 69 6c 74 65 72 5f  .    Use filter_
0dc0: 75 72 6c 28 29 20 74 6f 20 74 65 73 74 20 69 6e  url() to test in
0dd0: 63 6f 6d 69 6e 67 20 6f 72 20 6f 75 74 67 6f 69  coming or outgoi
0de0: 6e 67 20 72 6f 75 74 65 73 3b 0a 20 20 20 20 66  ng routes;.    f
0df0: 69 6c 74 65 72 5f 65 72 72 28 29 20 66 6f 72 20  ilter_err() for 
0e00: 65 72 72 6f 72 20 72 65 64 69 72 65 63 74 69 6f  error redirectio
0e10: 6e 2e 0a 0a 20 20 20 20 66 69 6c 74 65 72 5f 75  n...    filter_u
0e20: 72 6c 28 29 20 61 63 63 65 70 74 73 20 6f 76 65  rl() accepts ove
0e30: 72 72 69 64 65 73 20 66 6f 72 20 6d 65 74 68 6f  rrides for metho
0e40: 64 20 61 6e 64 20 72 65 6d 6f 74 65 20 68 6f 73  d and remote hos
0e50: 74 3a 0a 20 20 20 20 20 20 20 20 66 69 6c 74 65  t:.        filte
0e60: 72 5f 75 72 6c 28 75 72 6c 2c 20 6d 65 74 68 6f  r_url(url, metho
0e70: 64 3d 27 67 65 74 27 2c 20 72 65 6d 6f 74 65 3d  d='get', remote=
0e80: 27 30 2e 30 2e 30 2e 30 27 2c 20 6f 75 74 3d 46  '0.0.0.0', out=F
0e90: 61 6c 73 65 29 0a 0a 20 20 20 20 66 69 6c 74 65  alse)..    filte
0ea0: 72 5f 65 72 72 28 29 20 61 63 63 65 70 74 73 20  r_err() accepts 
0eb0: 6f 76 65 72 72 69 64 65 73 20 66 6f 72 20 61 70  overrides for ap
0ec0: 70 6c 69 63 61 74 69 6f 6e 20 61 6e 64 20 74 69  plication and ti
0ed0: 63 6b 65 74 3a 0a 20 20 20 20 20 20 20 20 66 69  cket:.        fi
0ee0: 6c 74 65 72 5f 65 72 72 28 73 74 61 74 75 73 2c  lter_err(status,
0ef0: 20 61 70 70 6c 69 63 61 74 69 6f 6e 3d 27 61 70   application='ap
0f00: 70 27 2c 20 74 69 63 6b 65 74 3d 27 74 6b 74 27  p', ticket='tkt'
0f10: 29 0a 0a 20 20 20 20 3e 3e 3e 20 69 6d 70 6f 72  )..    >>> impor
0f20: 74 20 6f 73 0a 20 20 20 20 3e 3e 3e 20 69 6d 70  t os.    >>> imp
0f30: 6f 72 74 20 67 6c 75 6f 6e 2e 6d 61 69 6e 0a 20  ort gluon.main. 
0f40: 20 20 20 3e 3e 3e 20 66 72 6f 6d 20 67 6c 75 6f     >>> from gluo
0f50: 6e 2e 72 65 77 72 69 74 65 20 69 6d 70 6f 72 74  n.rewrite import
0f60: 20 72 65 67 65 78 5f 73 65 6c 65 63 74 2c 20 6c   regex_select, l
0f70: 6f 61 64 2c 20 66 69 6c 74 65 72 5f 75 72 6c 2c  oad, filter_url,
0f80: 20 72 65 67 65 78 5f 66 69 6c 74 65 72 5f 6f 75   regex_filter_ou
0f90: 74 2c 20 66 69 6c 74 65 72 5f 65 72 72 2c 20 63  t, filter_err, c
0fa0: 6f 6d 70 69 6c 65 5f 72 65 67 65 78 0a 20 20 20  ompile_regex.   
0fb0: 20 3e 3e 3e 20 72 65 67 65 78 5f 73 65 6c 65 63   >>> regex_selec
0fc0: 74 28 29 0a 20 20 20 20 3e 3e 3e 20 6c 6f 61 64  t().    >>> load
0fd0: 28 72 6f 75 74 65 73 3d 6f 73 2e 70 61 74 68 2e  (routes=os.path.
0fe0: 62 61 73 65 6e 61 6d 65 28 5f 5f 66 69 6c 65 5f  basename(__file_
0ff0: 5f 29 29 0a 0a 20 20 20 20 3e 3e 3e 20 6f 73 2e  _))..    >>> os.
1000: 70 61 74 68 2e 72 65 6c 70 61 74 68 28 66 69 6c  path.relpath(fil
1010: 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f  ter_url('http://
1020: 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 66 61 76 69 63  domain.com/favic
1030: 6f 6e 2e 69 63 6f 27 29 29 0a 20 20 20 20 27 61  on.ico')).    'a
1040: 70 70 6c 69 63 61 74 69 6f 6e 73 2f 65 78 61 6d  pplications/exam
1050: 70 6c 65 73 2f 73 74 61 74 69 63 2f 66 61 76 69  ples/static/favi
1060: 63 6f 6e 2e 69 63 6f 27 0a 20 20 20 20 3e 3e 3e  con.ico'.    >>>
1070: 20 6f 73 2e 70 61 74 68 2e 72 65 6c 70 61 74 68   os.path.relpath
1080: 28 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74 74  (filter_url('htt
1090: 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 72  p://domain.com/r
10a0: 6f 62 6f 74 73 2e 74 78 74 27 29 29 0a 20 20 20  obots.txt')).   
10b0: 20 27 61 70 70 6c 69 63 61 74 69 6f 6e 73 2f 65   'applications/e
10c0: 78 61 6d 70 6c 65 73 2f 73 74 61 74 69 63 2f 72  xamples/static/r
10d0: 6f 62 6f 74 73 2e 74 78 74 27 0a 20 20 20 20 3e  obots.txt'.    >
10e0: 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68  >> filter_url('h
10f0: 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d  ttp://domain.com
1100: 27 29 0a 20 20 20 20 27 2f 69 6e 69 74 2f 64 65  ').    '/init/de
1110: 66 61 75 6c 74 2f 69 6e 64 65 78 27 0a 20 20 20  fault/index'.   
1120: 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28   >>> filter_url(
1130: 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63  'http://domain.c
1140: 6f 6d 2f 27 29 0a 20 20 20 20 27 2f 69 6e 69 74  om/').    '/init
1150: 2f 64 65 66 61 75 6c 74 2f 69 6e 64 65 78 27 0a  /default/index'.
1160: 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75      >>> filter_u
1170: 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69  rl('http://domai
1180: 6e 2e 63 6f 6d 2f 69 6e 69 74 2f 64 65 66 61 75  n.com/init/defau
1190: 6c 74 2f 66 63 6e 27 29 0a 20 20 20 20 27 2f 69  lt/fcn').    '/i
11a0: 6e 69 74 2f 64 65 66 61 75 6c 74 2f 66 63 6e 27  nit/default/fcn'
11b0: 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f  .    >>> filter_
11c0: 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61  url('http://doma
11d0: 69 6e 2e 63 6f 6d 2f 69 6e 69 74 2f 64 65 66 61  in.com/init/defa
11e0: 75 6c 74 2f 66 63 6e 2f 27 29 0a 20 20 20 20 27  ult/fcn/').    '
11f0: 2f 69 6e 69 74 2f 64 65 66 61 75 6c 74 2f 66 63  /init/default/fc
1200: 6e 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65  n'.    >>> filte
1210: 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f  r_url('http://do
1220: 6d 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74 72  main.com/app/ctr
1230: 2f 66 63 6e 27 29 0a 20 20 20 20 27 2f 61 70 70  /fcn').    '/app
1240: 2f 63 74 72 2f 66 63 6e 27 0a 20 20 20 20 3e 3e  /ctr/fcn'.    >>
1250: 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74  > filter_url('ht
1260: 74 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f  tp://domain.com/
1270: 61 70 70 2f 63 74 72 2f 66 63 6e 2f 61 72 67 31  app/ctr/fcn/arg1
1280: 27 29 0a 20 20 20 20 22 2f 61 70 70 2f 63 74 72  ').    "/app/ctr
1290: 2f 66 63 6e 20 5b 27 61 72 67 31 27 5d 22 0a 20  /fcn ['arg1']". 
12a0: 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72     >>> filter_ur
12b0: 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69 6e  l('http://domain
12c0: 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f 66 63 6e  .com/app/ctr/fcn
12d0: 2f 61 72 67 31 2f 27 29 0a 20 20 20 20 22 2f 61  /arg1/').    "/a
12e0: 70 70 2f 63 74 72 2f 66 63 6e 20 5b 27 61 72 67  pp/ctr/fcn ['arg
12f0: 31 27 5d 22 0a 20 20 20 20 3e 3e 3e 20 66 69 6c  1']".    >>> fil
1300: 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f  ter_url('http://
1310: 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63  domain.com/app/c
1320: 74 72 2f 66 63 6e 2f 61 72 67 31 2f 2f 27 29 0a  tr/fcn/arg1//').
1330: 20 20 20 20 22 2f 61 70 70 2f 63 74 72 2f 66 63      "/app/ctr/fc
1340: 6e 20 5b 27 61 72 67 31 27 2c 20 27 27 5d 22 0a  n ['arg1', '']".
1350: 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75      >>> filter_u
1360: 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69  rl('http://domai
1370: 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f 66 63  n.com/app/ctr/fc
1380: 6e 2f 2f 61 72 67 31 27 29 0a 20 20 20 20 22 2f  n//arg1').    "/
1390: 61 70 70 2f 63 74 72 2f 66 63 6e 20 5b 27 27 2c  app/ctr/fcn ['',
13a0: 20 27 61 72 67 31 27 5d 22 0a 20 20 20 20 3e 3e   'arg1']".    >>
13b0: 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 48 54  > filter_url('HT
13c0: 54 50 3a 2f 2f 44 4f 4d 41 49 4e 2e 43 4f 4d 2f  TP://DOMAIN.COM/
13d0: 61 70 70 2f 63 74 72 2f 66 63 6e 27 29 0a 20 20  app/ctr/fcn').  
13e0: 20 20 27 2f 61 70 70 2f 63 74 72 2f 66 63 6e 27    '/app/ctr/fcn'
13f0: 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f  .    >>> filter_
1400: 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61  url('http://doma
1410: 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f 66  in.com/app/ctr/f
1420: 63 6e 3f 71 75 65 72 79 27 29 0a 20 20 20 20 27  cn?query').    '
1430: 2f 61 70 70 2f 63 74 72 2f 66 63 6e 20 3f 71 75  /app/ctr/fcn ?qu
1440: 65 72 79 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c  ery'.    >>> fil
1450: 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f  ter_url('http://
1460: 6f 74 68 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2f  otherdomain.com/
1470: 66 63 6e 27 29 0a 20 20 20 20 27 2f 61 70 70 2f  fcn').    '/app/
1480: 63 74 72 2f 66 63 6e 27 0a 20 20 20 20 3e 3e 3e  ctr/fcn'.    >>>
1490: 20 72 65 67 65 78 5f 66 69 6c 74 65 72 5f 6f 75   regex_filter_ou
14a0: 74 28 27 2f 61 70 70 2f 63 74 72 2f 66 63 6e 27  t('/app/ctr/fcn'
14b0: 29 0a 20 20 20 20 27 2f 63 74 72 2f 66 63 6e 27  ).    '/ctr/fcn'
14c0: 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f  .    >>> filter_
14d0: 75 72 6c 28 27 68 74 74 70 73 3a 2f 2f 6f 74 68  url('https://oth
14e0: 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 61 70 70  erdomain.com/app
14f0: 2f 63 74 72 2f 66 63 6e 27 2c 20 6f 75 74 3d 54  /ctr/fcn', out=T
1500: 72 75 65 29 0a 20 20 20 20 27 2f 63 74 72 2f 66  rue).    '/ctr/f
1510: 63 6e 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74  cn'.    >>> filt
1520: 65 72 5f 75 72 6c 28 27 68 74 74 70 73 3a 2f 2f  er_url('https://
1530: 6f 74 68 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2f  otherdomain.com/
1540: 61 70 70 2f 63 74 72 2f 66 63 6e 2f 61 72 67 31  app/ctr/fcn/arg1
1550: 2f 2f 27 2c 20 6f 75 74 3d 54 72 75 65 29 0a 20  //', out=True). 
1560: 20 20 20 27 2f 63 74 72 2f 66 63 6e 2f 61 72 67     '/ctr/fcn/arg
1570: 31 2f 2f 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c  1//'.    >>> fil
1580: 74 65 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f  ter_url('http://
1590: 6f 74 68 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2f  otherdomain.com/
15a0: 61 70 70 2f 63 74 72 2f 66 63 6e 27 2c 20 6f 75  app/ctr/fcn', ou
15b0: 74 3d 54 72 75 65 29 0a 20 20 20 20 27 2f 66 63  t=True).    '/fc
15c0: 6e 27 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65  n'.    >>> filte
15d0: 72 5f 75 72 6c 28 27 68 74 74 70 3a 2f 2f 6f 74  r_url('http://ot
15e0: 68 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 61 70  herdomain.com/ap
15f0: 70 2f 63 74 72 2f 66 63 6e 3f 71 75 65 72 79 27  p/ctr/fcn?query'
1600: 2c 20 6f 75 74 3d 54 72 75 65 29 0a 20 20 20 20  , out=True).    
1610: 27 2f 66 63 6e 3f 71 75 65 72 79 27 0a 20 20 20  '/fcn?query'.   
1620: 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75 72 6c 28   >>> filter_url(
1630: 27 68 74 74 70 3a 2f 2f 6f 74 68 65 72 64 6f 6d  'http://otherdom
1640: 61 69 6e 2e 63 6f 6d 2f 61 70 70 2f 63 74 72 2f  ain.com/app/ctr/
1650: 66 63 6e 23 61 6e 63 68 6f 72 27 2c 20 6f 75 74  fcn#anchor', out
1660: 3d 54 72 75 65 29 0a 20 20 20 20 27 2f 66 63 6e  =True).    '/fcn
1670: 23 61 6e 63 68 6f 72 27 0a 20 20 20 20 3e 3e 3e  #anchor'.    >>>
1680: 20 66 69 6c 74 65 72 5f 65 72 72 28 32 30 30 29   filter_err(200)
1690: 0a 20 20 20 20 32 30 30 0a 20 20 20 20 3e 3e 3e  .    200.    >>>
16a0: 20 66 69 6c 74 65 72 5f 65 72 72 28 33 39 39 29   filter_err(399)
16b0: 0a 20 20 20 20 33 39 39 0a 20 20 20 20 3e 3e 3e  .    399.    >>>
16c0: 20 66 69 6c 74 65 72 5f 65 72 72 28 34 30 30 29   filter_err(400)
16d0: 0a 20 20 20 20 34 30 30 0a 20 20 20 20 3e 3e 3e  .    400.    >>>
16e0: 20 66 69 6c 74 65 72 5f 75 72 6c 28 27 68 74 74   filter_url('htt
16f0: 70 3a 2f 2f 64 6f 6d 61 69 6e 2e 63 6f 6d 2f 77  p://domain.com/w
1700: 65 6c 63 6f 6d 65 27 2c 20 61 70 70 3d 54 72 75  elcome', app=Tru
1710: 65 29 0a 20 20 20 20 27 77 65 6c 63 6f 6d 65 27  e).    'welcome'
1720: 0a 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f  .    >>> filter_
1730: 75 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61  url('http://doma
1740: 69 6e 2e 63 6f 6d 2f 27 2c 20 61 70 70 3d 54 72  in.com/', app=Tr
1750: 75 65 29 0a 20 20 20 20 27 6d 79 61 70 70 27 0a  ue).    'myapp'.
1760: 20 20 20 20 3e 3e 3e 20 66 69 6c 74 65 72 5f 75      >>> filter_u
1770: 72 6c 28 27 68 74 74 70 3a 2f 2f 64 6f 6d 61 69  rl('http://domai
1780: 6e 2e 63 6f 6d 27 2c 20 61 70 70 3d 54 72 75 65  n.com', app=True
1790: 29 0a 20 20 20 20 27 6d 79 61 70 70 27 0a 20 20  ).    'myapp'.  
17a0: 20 20 3e 3e 3e 20 63 6f 6d 70 69 6c 65 5f 72 65    >>> compile_re
17b0: 67 65 78 28 27 2e 2a 68 74 74 70 3a 2f 2f 6f 74  gex('.*http://ot
17c0: 68 65 72 64 6f 6d 61 69 6e 2e 63 6f 6d 2e 2a 20  herdomain.com.* 
17d0: 28 3f 50 3c 61 6e 79 3e 2e 2a 29 27 2c 20 27 2f  (?P<any>.*)', '/
17e0: 61 70 70 2f 63 74 72 5c 67 3c 61 6e 79 3e 27 29  app/ctr\g<any>')
17f0: 5b 30 5d 2e 70 61 74 74 65 72 6e 0a 20 20 20 20  [0].pattern.    
1800: 27 5e 2e 2a 68 74 74 70 3a 2f 2f 6f 74 68 65 72  '^.*http://other
1810: 64 6f 6d 61 69 6e 2e 63 6f 6d 2e 2a 20 28 3f 50  domain.com.* (?P
1820: 3c 61 6e 79 3e 2e 2a 29 24 27 0a 20 20 20 20 3e  <any>.*)$'.    >
1830: 3e 3e 20 63 6f 6d 70 69 6c 65 5f 72 65 67 65 78  >> compile_regex
1840: 28 27 2e 2a 68 74 74 70 3a 2f 2f 6f 74 68 65 72  ('.*http://other
1850: 64 6f 6d 61 69 6e 2e 63 6f 6d 2e 2a 20 28 3f 50  domain.com.* (?P
1860: 3c 61 6e 79 3e 2e 2a 29 27 2c 20 27 2f 61 70 70  <any>.*)', '/app
1870: 2f 63 74 72 5c 67 3c 61 6e 79 3e 27 29 5b 31 5d  /ctr\g<any>')[1]
1880: 0a 20 20 20 20 27 2f 61 70 70 2f 63 74 72 5c 5c  .    '/app/ctr\\
1890: 5c 5c 67 3c 61 6e 79 3e 27 0a 20 20 20 20 3e 3e  \\g<any>'.    >>
18a0: 3e 20 63 6f 6d 70 69 6c 65 5f 72 65 67 65 78 28  > compile_regex(
18b0: 27 2f 24 63 2f 24 66 27 2c 20 27 2f 69 6e 69 74  '/$c/$f', '/init
18c0: 2f 24 63 2f 24 66 27 29 5b 30 5d 2e 70 61 74 74  /$c/$f')[0].patt
18d0: 65 72 6e 0a 20 20 20 20 27 5e 2e 2a 3f 3a 68 74  ern.    '^.*?:ht
18e0: 74 70 73 3f 3a 2f 2f 5b 5e 3a 2f 5d 2b 3a 5b 61  tps?://[^:/]+:[a
18f0: 2d 7a 5d 2b 20 2f 28 3f 50 3c 63 3e 5c 5c 5c 5c  -z]+ /(?P<c>\\\\
1900: 77 2b 29 2f 28 3f 50 3c 66 3e 5c 5c 5c 5c 77 2b  w+)/(?P<f>\\\\w+
1910: 29 24 27 0a 20 20 20 20 3e 3e 3e 20 63 6f 6d 70  )$'.    >>> comp
1920: 69 6c 65 5f 72 65 67 65 78 28 27 2f 24 63 2f 24  ile_regex('/$c/$
1930: 66 27 2c 20 27 2f 69 6e 69 74 2f 24 63 2f 24 66  f', '/init/$c/$f
1940: 27 29 5b 31 5d 0a 20 20 20 20 27 2f 69 6e 69 74  ')[1].    '/init
1950: 2f 5c 5c 5c 5c 67 3c 63 3e 2f 5c 5c 5c 5c 67 3c  /\\\\g<c>/\\\\g<
1960: 66 3e 27 0a 20 20 20 20 27 27 27 0a 20 20 20 20  f>'.    '''.    
1970: 70 61 73 73 0a 0a 69 66 20 5f 5f 6e 61 6d 65 5f  pass..if __name_
1980: 5f 20 3d 3d 20 27 5f 5f 6d 61 69 6e 5f 5f 27 3a  _ == '__main__':
1990: 0a 20 20 20 20 69 6d 70 6f 72 74 20 64 6f 63 74  .    import doct
19a0: 65 73 74 0a 20 20 20 20 64 6f 63 74 65 73 74 2e  est.    doctest.
19b0: 74 65 73 74 6d 6f 64 28 29 0a 0a                 testmod()..