Publish.py
上传用户:gyjinxi
上传日期:2007-01-04
资源大小:159k
文件大小:13k
源码类别:

WEB邮件程序

开发平台:

Python

  1. ##############################################################################
  2. # Zope Public License (ZPL) Version 1.0
  3. # -------------------------------------
  4. # Copyright (c) Digital Creations.  All rights reserved.
  5. # This license has been certified as Open Source(tm).
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are
  8. # met:
  9. # 1. Redistributions in source code must retain the above copyright
  10. #    notice, this list of conditions, and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. #    notice, this list of conditions, and the following disclaimer in
  13. #    the documentation and/or other materials provided with the
  14. #    distribution.
  15. # 3. Digital Creations requests that attribution be given to Zope
  16. #    in any manner possible. Zope includes a "Powered by Zope"
  17. #    button that is installed by default. While it is not a license
  18. #    violation to remove this button, it is requested that the
  19. #    attribution remain. A significant investment has been put
  20. #    into Zope, and this effort will continue if the Zope community
  21. #    continues to grow. This is one way to assure that growth.
  22. # 4. All advertising materials and documentation mentioning
  23. #    features derived from or use of this software must display
  24. #    the following acknowledgement:
  25. #      "This product includes software developed by Digital Creations
  26. #      for use in the Z Object Publishing Environment
  27. #      (http://www.zope.org/)."
  28. #    In the event that the product being advertised includes an
  29. #    intact Zope distribution (with copyright and license included)
  30. #    then this clause is waived.
  31. # 5. Names associated with Zope or Digital Creations must not be used to
  32. #    endorse or promote products derived from this software without
  33. #    prior written permission from Digital Creations.
  34. # 6. Modified redistributions of any form whatsoever must retain
  35. #    the following acknowledgment:
  36. #      "This product includes software developed by Digital Creations
  37. #      for use in the Z Object Publishing Environment
  38. #      (http://www.zope.org/)."
  39. #    Intact (re-)distributions of any official Zope release do not
  40. #    require an external acknowledgement.
  41. # 7. Modifications are encouraged but must be packaged separately as
  42. #    patches to official Zope releases.  Distributions that do not
  43. #    clearly separate the patches from the original work must be clearly
  44. #    labeled as unofficial distributions.  Modifications which do not
  45. #    carry the name Zope may be packaged in any form, as long as they
  46. #    conform to all of the clauses above.
  47. # Disclaimer
  48. #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
  49. #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  51. #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
  52. #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  54. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  55. #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  56. #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  57. #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  58. #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. #   SUCH DAMAGE.
  60. # This software consists of contributions made by Digital Creations and
  61. # many individuals on behalf of Digital Creations.  Specific
  62. # attributions are listed in the accompanying credits file.
  63. ##############################################################################
  64. __doc__="""Python Object Publisher -- Publish Python objects on web servers
  65. $Id: Publish.py,v 1.143 1999/09/23 21:57:46 jim Exp $"""
  66. __version__='$Revision: 1.143 $'[11:-2]
  67. import sys, os
  68. from string import lower, atoi, rfind, strip
  69. from Response import Response
  70. from Request import Request
  71. from maybe_lock import allocate_lock
  72. from mapply import mapply
  73. class Retry(Exception):
  74.     """Raise this to retry a request
  75.     """
  76. def call_object(object, args, request):
  77.     result=apply(object,args) # Type s<cr> to step into published object.
  78.     return result
  79. def missing_name(name, request):
  80.     if name=='self': return request['PARENTS'][0]
  81.     request.response.badRequestError(name)
  82. def dont_publish_class(klass, request):
  83.     request.response.forbiddenError("class %s" % klass.__name__)
  84. def publish(request, module_name, after_list, debug=0,
  85.             # Optimize:
  86.             call_object=call_object,
  87.             missing_name=missing_name,
  88.             dont_publish_class=dont_publish_class,
  89.             mapply=mapply,
  90.             ):
  91.     (bobo_before, bobo_after, object, realm, debug_mode, err_hook,
  92.      have_transactions)= get_module_info(module_name)
  93.     parents=None
  94.     try:
  95.         request.processInputs()
  96.         request_get=request.get
  97.         response=request.response
  98.     
  99.         # First check for "cancel" redirect:
  100.         cancel=''
  101.         if lower(strip(request_get('SUBMIT','')))=='cancel':
  102.             cancel=request_get('CANCEL_ACTION','')
  103.             if cancel: raise 'Redirect', cancel
  104.     
  105.         after_list[0]=bobo_after
  106.         if debug_mode: response.debug_mode=debug_mode
  107.         if realm and not request.get('REMOTE_USER',None):
  108.             response.realm=realm
  109.     
  110.         if bobo_before is not None: bobo_before();
  111.     
  112.         # Get a nice clean path list:
  113.         path=strip(request_get('PATH_INFO'))
  114.     
  115.         request['PARENTS']=parents=[object]
  116.         
  117.         if have_transactions: get_transaction().begin()
  118.     
  119.         object=request.traverse(path)
  120.     
  121.         # Record transaction meta-data
  122.         if have_transactions:
  123.             get_transaction().note(request_get('PATH_INFO'))
  124.             auth_user=request_get('AUTHENTICATED_USER',None)
  125.             if auth_user is not None:
  126.                 get_transaction().setUser(auth_user,
  127.                                           request_get('AUTHENTICATION_PATH'))
  128.     
  129.         result=mapply(object, request.args, request,
  130.                       call_object,1,
  131.                       missing_name, 
  132.                       dont_publish_class,
  133.                       request, bind=1)
  134.     
  135.         if result is not response: response.setBody(result)
  136.     
  137.         if have_transactions: get_transaction().commit()
  138.         return response
  139.     except:
  140.         if err_hook is not None:
  141.             if parents: parents=parents[0]
  142.             try:
  143.                 return err_hook(parents, request,
  144.                                 sys.exc_info()[0],
  145.                                 sys.exc_info()[1],
  146.                                 sys.exc_info()[2],
  147.                                 )
  148.             except Retry:
  149.                 # We need to try again....
  150.                 if not request.supports_retry():
  151.                     return err_hook(parents, request,
  152.                                     sys.exc_info()[0],
  153.                                     sys.exc_info()[1],
  154.                                     sys.exc_info()[2],
  155.                                     )
  156.                 newrequest=request.retry()
  157.                 try:
  158.                     return publish(newrequest, module_name, after_list, debug)
  159.                 finally:
  160.                     newrequest.close()
  161.                     
  162.         else: raise
  163.             
  164. def publish_module(module_name,
  165.                    stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,
  166.                    environ=os.environ, debug=0, request=None, response=None):
  167.     must_die=0
  168.     status=200
  169.     after_list=[None]
  170.     try:
  171.         try:
  172.             if response is None:
  173.                 response=Response(stdout=stdout, stderr=stderr)
  174.             else:
  175.                 stdout=response.stdout
  176.             if request is None:
  177.                 request=Request(stdin, environ, response)
  178.             response = publish(request, module_name, after_list, debug=debug)
  179.         except SystemExit, v:
  180.             must_die=sys.exc_info()
  181.             response.exception(must_die)
  182.         except ImportError, v:
  183.             if type(v) is type(()) and len(v)==3: must_die=v
  184.             elif hasattr(sys, 'exc_info'): must_die=sys.exc_info()
  185.             else: must_die = SystemExit, v, sys.exc_info()[2]
  186.             response.exception(1, v)
  187.         except:
  188.             response.exception()
  189.             status=response.getStatus()
  190.         if response:
  191.             outputBody=getattr(response, 'outputBody', None)
  192.             if outputBody is not None:
  193.                 outputBody()
  194.             else:
  195.                 response=str(response)
  196.                 if response: stdout.write(response)
  197.         # The module defined a post-access function, call it
  198.         if after_list[0] is not None: after_list[0]()
  199.     finally:
  200.         if request is not None: request.close()
  201.     if must_die:
  202.         try: raise must_die[0], must_die[1], must_die[2]
  203.         finally: must_die=None
  204.     return status
  205. _l=allocate_lock()
  206. def get_module_info(module_name, modules={},
  207.                     acquire=_l.acquire,
  208.                     release=_l.release,
  209.                     ):
  210.     if modules.has_key(module_name): return modules[module_name]
  211.     if module_name[-4:]=='.cgi': module_name=module_name[:-4]
  212.     acquire()
  213.     tb=None
  214.     try:
  215.         try:
  216.             module=__import__(module_name, globals(), globals(), ('__doc__',))
  217.             realm=module_name
  218.             # Let the app specify a realm
  219.             if hasattr(module,'__bobo_realm__'):
  220.                 realm=module.__bobo_realm__
  221.             elif os.environ.has_key('Z_REALM'):
  222.                 realm=os.environ['Z_REALM']
  223.             elif os.environ.has_key('BOBO_REALM'):
  224.                 realm=os.environ['BOBO_REALM']
  225.             else: realm=module_name
  226.             # Check for debug mode
  227.             if hasattr(module,'__bobo_debug_mode__'):
  228.                 debug_mode=not not module.__bobo_debug_mode__
  229.             elif (os.environ.has_key('Z_DEBUG_MODE') or
  230.                   os.environ.has_key('BOBO_DEBUG_MODE')):
  231.                 if os.environ.has_key('Z_DEBUG_MODE'):
  232.                     debug_mode=lower(os.environ['Z_DEBUG_MODE'])
  233.                 else:
  234.                     debug_mode=lower(os.environ['BOBO_DEBUG_MODE'])
  235.                 if debug_mode=='y' or debug_mode=='yes':
  236.                     debug_mode=1
  237.                 else:
  238.                     try: debug_mode=atoi(debug_mode)
  239.                     except: debug_mode=None
  240.             else: debug_mode=None
  241.             if hasattr(module,'__bobo_before__'):
  242.                 bobo_before=module.__bobo_before__
  243.             else: bobo_before=None
  244.             if hasattr(module,'__bobo_after__'): bobo_after=module.__bobo_after__
  245.             else: bobo_after=None
  246.             if hasattr(module,'bobo_application'):
  247.                 object=module.bobo_application
  248.             elif hasattr(module,'web_objects'):
  249.                 object=module.web_objects
  250.             else: object=module
  251.             error_hook=getattr(module,'zpublisher_exception_hook', None)
  252.             try: get_transaction()
  253.             except: have_transactions=0
  254.             else: have_transactions=1
  255.             info= (bobo_before, bobo_after, object, realm, debug_mode,
  256.                    error_hook, have_transactions)
  257.             modules[module_name]=modules[module_name+'.cgi']=info
  258.             
  259.             return info
  260.         except:
  261.             t,v,tb=sys.exc_info()
  262.             v=str(v)
  263.             raise ImportError, (t, v), tb
  264.     finally:
  265.         tb=None
  266.         release()
  267. # ZPublisher profiler support
  268. # ---------------------------
  269. if os.environ.get('PROFILE_PUBLISHER', None):
  270.     import profile, pstats
  271.     _pfile=os.environ['PROFILE_PUBLISHER']
  272.     _plock=allocate_lock()
  273.     _pfunc=publish_module
  274.     _pstat=None
  275.     def pm(module_name, stdin, stdout, stderr, 
  276.            environ, debug, request, response):
  277.         try:
  278.             r=_pfunc(module_name, stdin=stdin, stdout=stdout, 
  279.                      stderr=stderr, environ=environ, debug=debug, 
  280.                      request=request, response=response)
  281.         except: r=None
  282.         sys._pr_=r
  283.     def publish_module(module_name, stdin=sys.stdin, stdout=sys.stdout, 
  284.                        stderr=sys.stderr, environ=os.environ, debug=0, 
  285.                        request=None, response=None):
  286.         _plock.acquire()
  287.         try:
  288.             if request is not None:
  289.                 path_info=request.get('PATH_INFO')
  290.             else: path_info=environ.get('PATH_INFO')
  291.             if path_info[-14:]=='manage_profile':
  292.                 return _pfunc(module_name, stdin=stdin, stdout=stdout, 
  293.                               stderr=stderr, environ=environ, debug=debug, 
  294.                               request=request, response=response)
  295.             pobj=profile.Profile()
  296.             pobj.runcall(pm, module_name, stdin, stdout, stderr, 
  297.                          environ, debug, request, response)
  298.             result=sys._pr_
  299.             pobj.create_stats()
  300.             if _pstat is None:
  301.                 global _pstat
  302.                 _pstat=sys._ps_=pstats.Stats(pobj)
  303.             else: _pstat.add(pobj)
  304.         finally:
  305.             _plock.release()
  306.         if result is None:
  307.             try:
  308.                 error=sys.exc_info()
  309.                 file=open(_pfile, 'w')
  310.                 sys.stdout=file
  311.                 _pstat.strip_dirs().sort_stats('cumulative').print_stats(250)
  312.                 _pstat.strip_dirs().sort_stats('time').print_stats(250)
  313.                 file.flush()
  314.                 file.close()
  315.             except: pass
  316.             raise error[0], error[1], error[2]
  317.         return result