473,756 Members | 1,842 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

mod_python exception catching, other repetitious per-page actions

I'm in the middle of refactoring a small mod_python Web application,
which uses the Publisher handler. This application is currently a
single main Python file (which loads several other files as modules)
with several function entry points for the different pages in the
application.

(The application is a tool to allow staff members here to request
firewall port openings for their servers. Thus there is a page (and
function) for "view my servers", "add a server", "add a service to a
server", and so forth. Each of these is a function in the published
file.)

One thing I would like to do is factor all of the top-level database
connecting, top-level exception handling, and error-page generation into
a single place. Whenever an exception occurs not trapped locally --
including an error connecting to the database -- I want to generate an
HTML error page instead of throwing the stacktrace at the user.

Currently this means that every function is one big try/except block
where the except block calls a TypesetErrorPag e() function. Also
repeated are the function calls to set up the database backend
connection and to set up some per-user globals:

def mainpage(apache _request, some_cgi_arg):
try:
_connect_to_dat abase()
# other repetitious stuff here
_do_user_specif ic_stuff(apache _request)
#
# specific code here
#
except Exception, err:
return _TypesetErrorPa ge(err)

def addserverpage(a pache_request, some_cgi_arg, another_arg):
try:
_connect_to_dat abase()
# other repetitious stuff here
_do_user_specif ic_stuff(apache _request)
#
# specific code here
#
except Exception, err:
return _TypesetErrorPa ge(err)

I'd like to factor this repetition out. However there does not seem to
be a straightforward way to do it -- the connect_to_data base() could be
done at the module level (i.e. outside of any function), but this might
have problems if the Apache instance persists long enough between
requests for the database to time out.

One thing I have considered is to handle _all_ the pages through a
single function, which would look up the specific pages by name:

PAGES = { "mainpage" : mainpagefunc, "addserverp age" : addserverfunc }

def page(apache_req uest, which_page, *args):
try:
connect_to_data base()
# other repetitious stuff here
do_user_specifi c_stuff(apache_ request)
return PAGES[which_page](req, *args) # call the real page
except Exception, err:
return TypesetErrorPag e(err)

.... but this has the problem that it sacrifices the argument name
matching which is a major useful feature of mod_python Publisher. I'm
not sure if keyword args are exactly the Right Thing either. It also
would make the URLs even longer than they already are, though I can
kludge that with Apache URL rewriting rules. (Bleah.)

I feel like I want a Lisp macro, but that's a topic I shouldn't even
invoke. Forget I said that. :)

Any thoughts?

--
Karl A. Krueger <kk******@examp le.edu>
Woods Hole Oceanographic Institution
Email address is spamtrapped. s/example/whoi/
"Outlook not so good." -- Magic 8-Ball Software Reviews
Jul 18 '05 #1
6 2102
You could use a wrapper for each function, which at least keeps you
from needing the which_page argument..

def page_wrapper(ca llable):
def _wrapper(apache _request, *args):
try:
_connect_to_dat abase()
_do_user_specif ic_stuff(apache _request)
return callable(*args)
except Exception, err:
return _TypesetErrorPa ge(err)
return _wrapper

def mainpage(apache _request, some_cgi_arg):
# specific code ehre
mainpage = page_wrapper(ma inpage)
page_wrapper() could do extra magic with exec if you want it to have the
same signature as callable.. something like
def page_wrapper(ca llable):
d = {}
name = callable.__name __
argspec = getargspecstr(c allable) # based on inspect.getargs pec()
callspec = ... # argspec with default values removed
exec """def %s(%s): ... return callable(%s) ...""" \
% (name, argspec, callspec) in d
return d[name]
.... barf, eh?

Jeff
PS one of the currently discussed PEPs may let you write
def mainpage(apache _request, some_cgi_arg)[page_wrapper]: ...
instead of writing mainpage = page_wrapper(ma inpage) after the function
body.

Jul 18 '05 #2

"Karl A. Krueger" wrote:
I'm in the middle of refactoring a small mod_python Web application,
which uses the Publisher handler.
I have never used Publisher handler myself. Yes, I've read about it,
but I've decided to not use it after seeing that I will have to
explicitly tell which modules/functions I DON'T want external user to
be able to run - completely broken idea from security POV.
One thing I would like to do is factor all of the top-level database
connecting, top-level exception handling, and error-page generation into
a single place. Whenever an exception occurs not trapped locally --
including an error connecting to the database -- I want to generate an
HTML error page instead of throwing the stacktrace at the user. [...] One thing I have considered is to handle _all_ the pages through a
single function, which would look up the specific pages by name:
If you do this then you may as well drop Publisher handler completely.
One handle() function will work for you.
... but this has the problem that it sacrifices the argument name
matching which is a major useful feature of mod_python Publisher.
Not so big, as you need to validate arguments format anyway. With calls
like this:
pos = self.GetFsInt( 'posId' )
lastDate = self.GetFsDate( 'lastDate' )
you can get arguments from FieldStorage, ensure that arguments are
present and convert them to usable format (e.g. string=>datetim e.date).
Some examples:

def RaiseMangled( self ):
raise apache.SERVER_R ETURN, apache.HTTP_BAD _REQUEST

def RaiseNotFound( self ):
raise apache.SERVER_R ETURN, apache.HTTP_NOT _FOUND

def GetFsString( self, key, default=None ):
if(default != None):
if self.fs.has_key (key):
value = self.fs[key]
else:
value = default
else:
value = self.fs[key]
if not isinstance( value, str ):
self.RaiseMangl ed()
return value

def GetFsInt( self, key ):
try:
return int( self.GetFsStrin g(key,'') )
except ValueError:
self.RaiseMangl ed()

def GetFsDate( self, key ):
try:
return Url2Date( self.GetFsStrin g(key,'') )
except ValueError:
self.RaiseMangl ed()

I've used one method in class to handle db connections, dispatch
requests and handle errors:

def handler( req ):
h = Handler()
return h.Handle( req )

class Handler:
[...]
def Handle(req):
try:
db = DbAccess.Connec tDb( dbName, host, user )
self.fs = util.FieldStora ge( self.req, True )
[...]
self.req.add_co mmon_vars()
env = req.subprocess_ env
self.script = env['SCRIPT_NAME']
self.cmd = self.script[ rfind(self.scri pt,'/')+1: ]

if self.cmd == '':
self.HandleMenu ( db )
elif self.cmd == 'PosDailyFeed':
self.HandlePosD ailyFeed( db )
elif self.cmd == 'PosDailySubmit ':
self.HandlePosD ailySubmit( db )
[...]
else:
self.RaiseNotFo und()
[...]
except:
[...]

# handler for urls like this:
# /PosDailyFeed?po sId=3&date=2004-03-22
def HandlePosDailyF eed( self, db ):
pos = self.GetFsInt( 'posId' )
date = self.GetFsDate( 'date' )
pb = self.CreatePage Builder( db )
valueDict = db.GetPosWorker Data( date, pos )
BuildDailyFeedP age( pb, db, date, pos, valueDict,
String2Html(db. GetPosName(pos) ) )
self.SendPage( pb )

I'm not sure if keyword args are exactly the Right Thing either. It also
would make the URLs even longer than they already are, though I can
kludge that with Apache URL rewriting rules. (Bleah.)


If you use straight handler() function instead of Publisher handler then
you have complete freedom how your URLs will look like.

Best regards,
Jacek.
Jul 18 '05 #3
One more idea -- I don't know mod_python, but is the Publisher class
something you could subclass, to add your own behavior there instead of
in each page function?

Jeff

Jul 18 '05 #4
Jeff Epler <je****@unpytho nic.net> wrote:
page_wrapper() could do extra magic with exec if you want it to have the
same signature as callable.. something like
def page_wrapper(ca llable):
d = {}
name = callable.__name __
argspec = getargspecstr(c allable) # based on inspect.getargs pec()
callspec = ... # argspec with default values removed
exec """def %s(%s): ... return callable(%s) ...""" \
% (name, argspec, callspec) in d
return d[name]
... barf, eh?


Barf? I -did- say I kind of wanted a Lisp macro; exec is about as close
as Python can get, I suppose.

Anyway, this has given me useful thoughts. Of course, I may just end up
back with keyword arguments. :-/

(But probably -not- reimplementing my whole application in Lisp. I'm
not that good in Lisp yet.)

--
Karl A. Krueger <kk******@examp le.edu>
Woods Hole Oceanographic Institution
Email address is spamtrapped. s/example/whoi/
"Outlook not so good." -- Magic 8-Ball Software Reviews
Jul 18 '05 #5
Jacek Trzmiel <sc***@hot.pl > wrote:
"Karl A. Krueger" wrote:
I'm in the middle of refactoring a small mod_python Web application,
which uses the Publisher handler.


I have never used Publisher handler myself. Yes, I've read about it,
but I've decided to not use it after seeing that I will have to
explicitly tell which modules/functions I DON'T want external user to
be able to run - completely broken idea from security POV.


Actually, Publisher never exposes modules imported into yours. It
traverses your module for names and types before exposing anything -- it
won't expose any object whose name begins with an underscore, or any
module.

(Oddly enough, it does expose exceptions, but just their string
representation. )

If anyone reading this is concerned about Publisher security, these
audit functions might help:

def AuditModuleForP ublisher(module ):
import types
for name in module.__dict__ :
object = module.__dict__[name]
if name.startswith ("_"):
# name starts with an underscore, not exposed
pass
elif type(object) == types.ModuleTyp e:
# object is a module, not exposed
pass
elif type(object) == types.FunctionT ype:
print ":: Exposed function:", name
elif isinstance(obje ct, str) or isinstance(obje ct, unicode):
if "passw" in name or "PASSW" in name:
print "!! Your %s password is %s." % (name, object)
else:
print ":: Exposed string:", name
else:
print ":: Exposed variable:", name

A nicer one:

def SymbolsExposedT oPublisher(modu le):
return [ sym for sym in module.__dict__
if (not sym.startswith( "_"))
and (type(module.__ dict__[sym]) != type(module)) ]

By enumerating the list of functions and variables you *intend* to
expose, a unit test should not be too hard to derive from this.

One thing I have considered is to handle _all_ the pages through a
single function, which would look up the specific pages by name:


If you do this then you may as well drop Publisher handler completely.
One handle() function will work for you.


I agree. However, since I want the functionality of Publisher's
argument name mapping, that is not what I want to do.

--
Karl A. Krueger <kk******@examp le.edu>
Woods Hole Oceanographic Institution
Email address is spamtrapped. s/example/whoi/
"Outlook not so good." -- Magic 8-Ball Software Reviews
Jul 18 '05 #6
In article <ma************ *************** *********@pytho n.org>, Jeff Epler wrote:
One more idea -- I don't know mod_python, but is the Publisher class
something you could subclass, to add your own behavior there instead of
in each page function?


I suppose I should be embarrassed to say this, but I just made a copy and
modified it to suit my own needs. I don't think its design is particularly
extensible, but it's a small script that's easy to understand.

--
..:[ dave benjamin: ramen/[sp00] -:- spoomusic.com -:- ramenfest.com ]:.
: please talk to your son or daughter about parametric polymorphism. :
Jul 18 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
2291
by: wolf | last post by:
i would like to briefly share my experiences with installing mod_python on a w2000 box. i must say that i believe the installation process to be unnecessarily complicated by the simple fact that the installer itself seems to be buggy -- in my case, no combination of mod_python 3.0.4, 3.1.2b and python 2.2.3, 2.3.3 ever came to completion. rather, the installer would exit -- after an initial declaration of having successfully found python...
6
3257
by: Piet | last post by:
Hi there, I cannot install mod_python v3.1.3 on either Win2k/ActivePython 2.3.2 or WinMe/Python 2.3.4. When I run the Windows installer, I get the following error message: Traceback (most recent call last): File "C:\Programme\Python23\Scripts\win32_postinstall.py", line 86, in ? apachediroptions = getApacheDirOptions() File "C:\Programme\Python23\Scripts\win32_postinstall.py", line 45, in getApacheDirOptions
3
1426
by: JWA | last post by:
Hi All, How can you capture unhandled exceptions thrown by an MDI child form separate from the entire app? I have an application-wide exception handler to catch crashes by doing the following in my Application entry point: Public Shared Sub Main() 'Explicitly set apartment state to Single Thread Apartment (STA) System.Threading.Thread.CurrentThread.ApartmentState = System.Threading.ApartmentState.STA Dim eh As New MyExceptionHandler()
11
3272
by: Master of C++ | last post by:
Hi, I am writing a simulation package in C++, and so far I've written about 8000 lines of code and have about 30 classes. I haven't used C++ exceptions so far (for various reasons). The only two "resources" I use are memory and file I/O and whenever there is a memory allocation failure or file I/O failure I just simply call a custom assert-type function to check, print a error message and abort. This seems to be OK for now (for the...
1
4359
by: treelife | last post by:
I'm getting and internal server error when | run the following mod_python script. I am actually trying to run Django. Script: from mod_python import apache def handler(req): req.content_type = 'text/plain' req.write("Under Construction")
3
2472
by: Charles | last post by:
Hello, I'm think about using mod_python for a project but I need to make sure: Does mod_python time out after a minute ? (I hope not). If I leave an HTTP connection open so that the content keeps loading inside the browser window indefinately, and if I close the browser window, the mod_python process is terminated, right? Thanks, -- Charles.
5
2169
by: Fernando | last post by:
I would like to know if this is OK or if it is better to just let the exception go instead of re-throwing it: I have: try { } catch(OracleException ex) {
5
3117
by: m.banaouas | last post by:
Hi, bonjour, witch versions are suitable to use for apache & mod_python ? Can i install and use "Apache 2.2.3" & "mod_python 3.2.10" (most recent versions) without facing any known major issue ? thanks for any help.
1
6206
TMS
by: TMS | last post by:
I installed mod_python 3.3.1 for Apache 2.0.58 and Windows XP. Per instructions I added this line to the httpd.conf file: LoadModule mod_python modules/mod_python.so And I get this error: Syntax error on line 174 of C:/Program Files/Apache Group/Apache2/conf/httpd.con f: Can't locate API module structure `mod_python' in file C:/Program Files/Apache G roup/Apache2/modules/mod_python.so: No error
4
1232
by: chris.monsanto | last post by:
Recently I've had to move my site to a new dedicated server running FreeBSD 6.1. After installing apache 2.0.59, python 2.4.4 and mod_python 3.3.1, I decided to bench a script in PHP vs one in Python. I found out that for some reason, my mod_python was performing extremely slow - magnitudes slower than it should. I scowered the internet for hours and asked a few friends and still haven't been able to find a solution to the problem. from...
0
9456
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9275
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10034
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9713
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
5142
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5304
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3805
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3358
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2666
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.