Author: chrisz
Date: Thu Nov 3 07:46:41 2005
New Revision: 3586
Modified:
Webware/trunk/MiddleKit/Run/ObjectStore.py
Webware/trunk/MiscUtils/Funcs.py
Webware/trunk/MiscUtils/PickleRPC.py
Webware/trunk/PSP/ParseEventHandler.py
Webware/trunk/WebKit/Adapters/Adapter.py
Webware/trunk/WebKit/Adapters/HTTPAdapter.py
Webware/trunk/WebKit/AppServer.py
Webware/trunk/WebKit/Application.py
Webware/trunk/WebKit/Cookie.py
Webware/trunk/WebKit/Experimental/NewPage.py
Webware/trunk/WebKit/Tasks/__init__.py
Webware/trunk/WebKit/WebwarePathLocation.py
Webware/trunk/WebUtils/FieldStorage.py
Webware/trunk/bin/checksrc.py
Log:
Comment clean-up to fit the style guide.
Modified: Webware/trunk/MiddleKit/Run/ObjectStore.py
==============================================================================
--- Webware/trunk/MiddleKit/Run/ObjectStore.py (original)
+++ Webware/trunk/MiddleKit/Run/ObjectStore.py Thu Nov 3 07:46:41 2005
@@ -398,7 +398,7 @@
If you subclass MiddleObject, then you're taken care of.
"""
self.willChange()
- self._changedObjects[object] = object ## @@ 2000-10-06 ce: Should this be keyed by the object.key()? Does it matter?
+ self._changedObjects[object] = object # @@ 2000-10-06 ce: Should this be keyed by the object.key()? Does it matter?
## Serial numbers ##
Modified: Webware/trunk/MiscUtils/Funcs.py
==============================================================================
--- Webware/trunk/MiscUtils/Funcs.py (original)
+++ Webware/trunk/MiscUtils/Funcs.py Thu Nov 3 07:46:41 2005
@@ -4,7 +4,7 @@
Funcs.py, a member of MiscUtils, holds functions that don't fit in anywhere else.
"""
-import md5, os, random, string, time, sys, tempfile
+import md5, os, random, time, sys, tempfile
try: # backward compatibility for Python < 2.3
True, False
@@ -13,7 +13,14 @@
def commas(number):
- """ Returns the given number as a string with commas to separate the thousands positions. The number can be a float, int, long or string. Returns None for None. """
+ """Insert commas in a number.
+
+ Return the given number as a string with commas to separate
+ the thousands positions.
+
+ The number can be a float, int, long or string. Returns None for None.
+
+ """
if number is None:
return None
if not number:
@@ -25,25 +32,33 @@
i = len(number)
while 1:
i = i-3
- if i<=0 or number[i-1]=='-':
+ if i <= 0 or number[i-1] == '-':
break
number[i:i] = [',']
- return string.join(number, '')
+ return ''.join(number)
def charWrap(s, width, hanging=0):
- """ Returns a new version of the string word wrapped with the given width and hanging indent. The font is assumed to be monospaced.
- This can be useful for including text between <pre> </pre> tags since <pre> will not word wrap and for lengthly lines, will increase the width of a web page.
- It can also be used to help delineate the entries in log-style output by passing hanging=4.
+ """Word wrap a string.
+
+ Return a new version of the string word wrapped with the given width
+ and hanging indent. The font is assumed to be monospaced.
+
+ This can be useful for including text between <pre> </pre> tags,
+ since <pre> will not word wrap, and for lengthly lines,
+ will increase the width of a web page.
+
+ It can also be used to help delineate the entries in log-style
+ output by passing hanging=4.
+
"""
- import string
if not s:
return s
- assert hanging<width
+ assert hanging < width
hanging = ' ' * hanging
- lines = string.split(s, '\n')
+ lines = s.split('\n')
i = 0
- while i<len(lines):
+ while i < len(lines):
s = lines[i]
while len(s)>width:
t = s[width:]
@@ -55,16 +70,18 @@
else:
lines[i] = s
i = i + 1
- return string.join(lines, '\n')
+ return '\n'.join(lines)
def excstr(e):
- """
- Returns a string for the exception in the format that Python normally outputs in interactive
- shells and such:
+ """Return a string for the exception.
+
+ The string will be in the format that Python normally outputs
+ in interactive shells and such:
<ExceptionName>: <message>
AttributeError: 'object' object has no attribute 'bar'
Neither str(e) nor repr(e) do that.
+
"""
if e is None:
return None
@@ -80,12 +97,12 @@
from tempfile import mktemp, mkstemp
else:
def mktemp(suffix="", dir=None):
- """
- User-callable function to return a unique temporary file name.
+ """User-callable function to return a unique temporary file name.
Duplicated from Python's own tempfile with the optional "dir"
argument added. This allows customization of the directory, without
having to take over the module level variable, tempdir.
+
"""
if not dir: dir = tempfile.gettempdir()
pre = tempfile.gettempprefix()
@@ -96,24 +113,27 @@
return file
def mkstemp(suffix="", dir=None):
- """
- User-callable function to return a tuple containing:
- - a os-level file handle for the temp file, open for read/write
- - the absolute path of that file
+ """User-callable function to return an opened temporary file.
+
+ The tuple will contain:
+ - a os-level file handle for the temp file, open for read/write
+ - the absolute path of that file
Note that this version of the function is not as secure as the
version included in Python 2.3.
+
"""
path = mktemp(suffix, dir)
return os.open(path, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0600), path
def wordWrap(s, width=78):
- """
- Returns a version of the string word wrapped to the given width.
+ """Returnsa version of the string word wrapped to the given width.
+
Respects existing newlines in the string.
Taken from:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
+
"""
return reduce(
lambda line, word, width=width: "%s%s%s" % (
@@ -126,44 +146,49 @@
def dateForEmail(now=None):
- """ Returns a properly formatted date/time string for email messages """
+ """Return a properly formatted date/time string for email messages."""
if now is None:
now = time.localtime(time.time())
- if now[8]==1:
+ if now[8] == 1:
offset = -time.altzone / 60
else:
offset = -time.timezone / 60
- if offset<0:
+ if offset < 0:
plusminus = '-'
else:
plusminus = '+'
- return time.strftime('%a, %d %b %Y %H:%M:%S ', now) + plusminus + '%02d%02d' % (abs(offset/60), abs(offset%60))
+ return time.strftime('%a, %d %b %Y %H:%M:%S ', now) \
+ + plusminus + '%02d%02d' % (abs(offset/60), abs(offset%60))
def hostName():
- """
- Returns the host name which is taken first from the os environment and failing that, from the 'hostname' executable. May return None if neither attempt succeeded.
- The environment keys checked are HOST and HOSTNAME both upper and lower case.
+ """Return the host name.
+
+ The name is taken first from the os environment and failing that,
+ from the 'hostname' executable. May return None if neither attempt
+ succeeded. The environment keys checked are HOST and HOSTNAME,
+ both upper and lower case.
+
"""
for name in ['HOST', 'HOSTNAME', 'host', 'hostname']:
hostName = os.environ.get(name, None)
if hostName:
break
if not hostName:
- hostName = string.strip(os.popen('hostname').read())
+ hostName = os.popen('hostname').read().strip()
if not hostName:
hostName = None
else:
- hostName = string.lower(hostName)
+ hostName = hostName.lower()
return hostName
_localIP = None
def localIP(remote=('www.yahoo.com', 80), useCache=1):
- """
- Gets the "public" address of the local machine, i.e. that address
- which is connected to the general Internet.
+ """Get the "public" address of the local machine.
+
+ This is the address which is connected to the general Internet.
This function connects to a remote HTTP server the first time it is
invoked (or every time it is invoked with useCache=0). If that is
@@ -175,6 +200,7 @@
about what you really want and how your network is really set up.
Search comp.lang.python for "local ip" for more information.
http://groups.google.com/groups?q=%22local+ip%22+group:comp.lang.python.*
+
"""
global _localIP
if useCache and _localIP:
@@ -184,10 +210,10 @@
# code from Donn Cave on comp.lang.python
# My notes:
- # Q: Why not use this? socket.gethostbyname(socket.gethostname())
+ # Q: Why not use this? socket.gethostbyname(socket.gethostname())
# A: On some machines, it returns '127.0.0.1' - not what we had in mind.
#
- # Q: Why not use this? socket.gethostbyname_ex(socket.gethostname())[2]
+ # Q: Why not use this? socket.gethostbyname_ex(socket.gethostname())[2]
# A: Because some machines have more than one IP (think "VPN", etc.) and
# there is no easy way to tell which one is the externally visible IP.
@@ -204,7 +230,7 @@
addresses = socket.gethostbyname_ex(socket.gethostname())[2]
for address in addresses:
- if address!='127.0.0.1':
+ if address != '127.0.0.1':
if useCache:
_localIP = address
return address
@@ -214,12 +240,11 @@
def safeDescription(x, what='what'):
- """
- Returns the repr() of x and its class (or type) for help in
- debugging. A major benefit here is that exceptions from
- repr() are consumed. This is important in places like
- "assert" where you don't want to lose the assertion
- exception in your attempt to get more information.
+ """Return the repr() of x and its class (or type) for help in debugging.
+
+ A major benefit here is that exceptions from repr() are consumed.
+ This is important in places like "assert" where you don't want
+ to lose the assertion exception in your attempt to get more information.
Example use:
assert isinstance(foo, Foo), safeDescription(foo)
@@ -228,6 +253,7 @@
# better output format:
assert isinstance(foo, Foo), safeDescription(foo, 'foo')
print safeDescription(foo, 'foo')
+
"""
try:
xRepr = repr(x)
@@ -247,9 +273,10 @@
return '%s=%s type=%s' % (what, xRepr, cRepr)
def _descExc(reprOfWhat, e):
- """
- Returns a description of an exception. This is a private function
- for use by safeDescription().
+ """Return a description of an exception.
+
+ This is a private function for use by safeDescription().
+
"""
try:
return '(exception from repr(%s): %s: %s)' % (reprOfWhat, e.__class__, e)
@@ -257,16 +284,22 @@
return '(exception from repr(%s))' % reprOfWhat
def timestamp(numSecs=None):
- """
- Returns a dictionary whose keys give different versions of the timestamp:
+ """Return a dictionary whose keys give different versions of the timestamp.
+
+ The dictionary will contain the following timestamp versions:
'numSecs': the number of seconds
'tuple': (year, month, day, hour, min, sec)
'pretty': 'YYYY-MM-DD HH:MM:SS'
'condensed': 'YYYYMMDDHHMMSS'
'dashed': 'YYYY-MM-DD-HH-MM-SS'
- The focus is on the year, month, day, hour and second, with no additional information such as timezone or day of year. This form of timestamp is often ideal for print statements, logs and filenames.
- If the current number of seconds is not passed, then the current time is taken.
- The 'pretty' format is ideal for print statements, while the 'condensed' and 'dashed' formats are generally more appropriate for filenames.
+
+ The focus is on the year, month, day, hour and second, with no additional
+ information such as timezone or day of year. This form of timestamp is
+ often ideal for print statements, logs and filenames. If the current number
+ of seconds is not passed, then the current time is taken. The 'pretty'
+ format is ideal for print statements, while the 'condensed' and 'dashed'
+ formats are generally more appropriate for filenames.
+
"""
if numSecs is None:
numSecs = time.time()
@@ -278,12 +311,14 @@
def uniqueId(forObject=None):
- """
- Generates an opaque, identifier string that is practically guaranteed to be unique.
+ """Generate an opaque, identifier string.
+
+ The string is practically guaranteed to be unique
If an object is passed, then its id() is incorporated into the generation.
Relies on md5 and returns a 32 character long string.
+
"""
- if hasattr(os, 'urandom'): # prefer os.urandom(), if available
+ if hasattr(os, 'urandom'): # prefer os.urandom(), if available
r = [os.urandom(8)]
else:
r = [time.time(), random.random(), os.times()]
@@ -297,17 +332,19 @@
hexdigest = []
for char in md5object.digest():
hexdigest.append('%02x' % ord(char))
- return string.join(hexdigest, '')
+ return ''.join(hexdigest)
def valueForString(s):
- """
+ """Return value for a string.
+
For a given string, returns the most appropriate Pythonic value
such as None, a long, an int, a list, etc. If none of those
make sense, then returns the string as-is.
"None", "True" and "False" are case-insensitive because there is
already too much case sensitivity in computing, damn it!
+
"""
if not s:
return s
@@ -324,18 +361,18 @@
except ValueError:
pass
t = s.lower()
- if t=='none':
+ if t == 'none':
return None
- if t.lower()=='true':
+ if t.lower() == 'true':
return True
- if t.lower()=='false':
+ if t.lower() == 'false':
return False
if s[0] in '[({"\'':
return eval(s)
return s
-### Deprecated
+## Deprecated ##
def Commas(number):
print 'DEPRECATED: MiscUtils.Funcs.Commas() on 02/23/01 in ver 0.5. Use commas() instead.'
Modified: Webware/trunk/MiscUtils/PickleRPC.py
==============================================================================
--- Webware/trunk/MiscUtils/PickleRPC.py (original)
+++ Webware/trunk/MiscUtils/PickleRPC.py Thu Nov 3 07:46:41 2005
@@ -286,11 +286,11 @@
# magic method dispatcher
return _Method(self.__requestValue, name)
- ## note: to call a remote object with an non-standard name, use
- ## result getattr(server, "strange-python-name")(args)
+ # note: to call a remote object with an non-standard name, use
+ # result getattr(server, "strange-python-name")(args)
-ServerProxy = Server # be like xmlrpclib for those who might guess or expect it
+ServerProxy = Server # be like xmlrpclib for those who might guess or expect it
Modified: Webware/trunk/PSP/ParseEventHandler.py
==============================================================================
--- Webware/trunk/PSP/ParseEventHandler.py (original)
+++ Webware/trunk/PSP/ParseEventHandler.py Thu Nov 3 07:46:41 2005
@@ -261,9 +261,9 @@
gen = MethodEndGenerator(self._reader.getChars(start, stop),attrs)
self.addGenerator(gen)
- #####################################################################
- ##The generation of the page begins here
- #####################################################################
+ # --------------------------------------
+ # The generation of the page begins here
+ # --------------------------------------
def beginProcessing(self):
pass
Modified: Webware/trunk/WebKit/Adapters/Adapter.py
==============================================================================
--- Webware/trunk/WebKit/Adapters/Adapter.py (original)
+++ Webware/trunk/WebKit/Adapters/Adapter.py Thu Nov 3 07:46:41 2005
@@ -56,8 +56,8 @@
data = dumps(dict)
s.send(dumps(int(len(data))))
s.send(data)
-
- sent=0
+
+ sent=0
inputLength = len(myInput)
while sent < inputLength:
chunk = s.send(myInput[sent:])
@@ -68,8 +68,8 @@
bufsize = 8*1024
# @@ 2000-04-26 ce: this should be configurable, also we should run some tests on different sizes
# @@ 2001-01-25 jsl: It really doesn't make a massive difference. 8k is fine and recommended.
-
-## s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, struct.pack('ll',0,5)) #wait for 0.5 seconds for data
+
+ #s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, struct.pack('ll',0,5)) #wait for 0.5 seconds for data
while 1:
data = s.recv(bufsize)
if not data:
@@ -81,4 +81,4 @@
def processResponse(self, data):
""" Process response data as it arrives."""
self._respData = self._respData + data
-
+
Modified: Webware/trunk/WebKit/Adapters/HTTPAdapter.py
==============================================================================
--- Webware/trunk/WebKit/Adapters/HTTPAdapter.py (original)
+++ Webware/trunk/WebKit/Adapters/HTTPAdapter.py Thu Nov 3 07:46:41 2005
@@ -9,9 +9,7 @@
AppWorkDir = None
-############################################################
-## Path setup
-############################################################
+## Path setup ##
try:
import os, sys
@@ -31,17 +29,15 @@
host = 'localhost'
port = int(port)
except 0:
- ## @@: Is there something we should do with exceptions here?
- ## I'm apt to just let them print to stderr and quit like normal,
- ## but I'm not sure.
+ # @@: Is there something we should do with exceptions here?
+ # I'm apt to just let them print to stderr and quit like normal,
+ # but I'm not sure.
pass
import BaseHTTPServer, threading, socket
-############################################################
-## HTTP Server
-############################################################
+## HTTP Server ##
from WebKit.HTTPServer import HTTPHandler
@@ -107,9 +103,7 @@
httpd.serve_forever()
-############################################################
-## Comand-line interface
-############################################################
+## Comand-line interface ##
usage = """HTTPServer - Standalone HTTP server to connect to AppServer
Usage:
Modified: Webware/trunk/WebKit/AppServer.py
==============================================================================
--- Webware/trunk/WebKit/AppServer.py (original)
+++ Webware/trunk/WebKit/AppServer.py Thu Nov 3 07:46:41 2005
@@ -1,6 +1,19 @@
#!/usr/bin/env python
-"""
-.. inline:: AppServer
+"""The AppServer singleton.
+
+The `AppServer` singleton is the controlling object/process/thread.
+`AppServer` receives requests and dispatches them to `Application`
+(via `Application.dispatchRawRequest`).
+
+`ThreadedAppServer` completes the implementation, dispatching
+these requests to separate threads. `AppServer`, at least in the
+abstract, could support different execution models and environments,
+but that support is not yet realized (Will it ever be realized?).
+
+The distinction between `AppServer` and `Application` is somewhat
+vague -- both are global singletons and both handle dispatching requests.
+`AppServer` works on a lower level, handling sockets and threads.
+
"""
from Common import *
@@ -39,19 +52,10 @@
class AppServer(ConfigurableForServerSidePath, Object):
"""The AppServer singleton.
- The `AppServer` a singleton is the controlling object/process/thread.
+ The `AppServer` singleton is the controlling object/process/thread.
`AppServer` receives requests and dispatches them to `Application`
(via `Application.dispatchRawRequest`).
- `ThreadedAppServer` completes the implementation, dispatching
- these requests to separate threads. `AppServer`, at least in the
- abstract, could support different execution models and environments,
- but that support is not yet realized (Will it ever be realized?).
-
- The distinction between `AppServer` and `Application` is somewhat
- vague -- both are global singletons and both handle dispatching requests.
- `AppServer` works on a lower level, handling sockets and threads.
-
"""
Modified: Webware/trunk/WebKit/Application.py
==============================================================================
--- Webware/trunk/WebKit/Application.py (original)
+++ Webware/trunk/WebKit/Application.py Thu Nov 3 07:46:41 2005
@@ -262,18 +262,16 @@
}
def configFilename(self):
- ":ignore:"
return self.serverSidePath('Configs/Application.config')
def configReplacementValues(self):
- ":ignore:"
return self._server.configReplacementValues()
## Versions ##
def version(self):
- """Returns the version of the application.
+ """Return the version of the application.
This implementation returns '0.1'. Subclasses should
override to return the correct version number.
@@ -285,21 +283,21 @@
return '0.1'
def webwareVersion(self):
- """Returns the Webware version as a tuple."""
+ """Return the Webware version as a tuple."""
return self._webwareVersion
def webwareVersionString(self):
- """Returns the Webware version as a printable string."""
+ """Return the Webware version as a printable string."""
return self._webwareVersionString
def webKitVersion(self):
- """ Returns the WebKit version as a tuple. """
+ """ Return the WebKit version as a tuple."""
# @@ 2003-03 ib: This is synced with Webware now, should be removed
# because redundant (and not that useful anyway)
return self._webKitVersion
def webKitVersionString(self):
- """ Returns the WebKit version as a printable string. """
+ """Return the WebKit version as a printable string."""
return self._webKitVersionString
@@ -317,7 +315,7 @@
return self._sessions.get(sessionId, default)
def hasSession(self, sessionId):
- """Check whether session `sessionId` exist."""
+ """Check whether session `sessionId` exists."""
return self._sessions.has_key(sessionId)
def sessions(self):
@@ -541,7 +539,7 @@
def runTransactionViaServlet(self, servlet, trans):
"""Execute the transaction using the servlet.
- This is the `awake`/`respond`/`sleep` sequence of calls, or if
+ This is the `awake`/`respond`/`sleep` sequence of calls, or if
the servlet supports it, a single `runTransaction` call (which is
presumed to make the awake/respond/sleep calls on its own). Using
`runTransaction` allows the servlet to override the basic call
@@ -550,7 +548,6 @@
Called by `runTransaction`.
"""
-
trans.setServlet(servlet)
if hasattr(servlet, 'runTransaction'):
servlet.runTransaction(trans)
Modified: Webware/trunk/WebKit/Cookie.py
==============================================================================
--- Webware/trunk/WebKit/Cookie.py (original)
+++ Webware/trunk/WebKit/Cookie.py Thu Nov 3 07:46:41 2005
@@ -72,7 +72,7 @@
# We can optimize later.
- ## Init ##
+ ## Init ##
def __init__(self, name, value):
"""Create a cookie.
@@ -158,7 +158,7 @@
"""
When sent, this should delete the cookie from the user's
browser, by making it empty, expiring it in the past,
- and setting its max-age to 0. One of these will delete
+ and setting its max-age to 0. One of these will delete
the cookie for any browser (which one actually works
depends on the browser).
"""
Modified: Webware/trunk/WebKit/Experimental/NewPage.py
==============================================================================
--- Webware/trunk/WebKit/Experimental/NewPage.py (original)
+++ Webware/trunk/WebKit/Experimental/NewPage.py Thu Nov 3 07:46:41 2005
@@ -9,610 +9,613 @@
class NewPage(Servlet):
- def __init__(self):
- Servlet.__init__(self)
- self._methodForRequestType = {} # a cache; see respond()
- if not hasattr(self, '_title'):
- self._title = self.__class__.__name__
- self.exc = ExceptionGetter(self)
-
- def respond(self, trans):
- try:
- if self.actionLogin:
- self.actionLogin()
- self.setup()
- httpMethodName = trans.request().method()
- method = self._methodForRequestType.get(httpMethodName)
- if not method:
- methName = 'respondTo' + httpMethodName.capitalize()
- method = getattr(self, methName, self.notImplemented)
- self._methodForRequestType[httpMethodName] = method
- method()
- except HTTPExceptions.HTTPError, v:
- self._contentAction = 'error'
- self._exception = v
- self.resetResponse()
- trans.response().setStatus(v.code(servlet=self),
- v.codeMessage(servlet=self))
- for name, value in v.headers(servlet=self).items():
- trans.response().setHeader(name, value)
- self.response().write(v.htDescription(servlet=self))
- self.teardown()
-
- actionLogin = None
-
- def setup(self):
- pass
-
- def teardown(self):
- """
- Cleanup anything necessary. This method will be called
- *regardless* of any exceptions. So things that you expect
- to be initialized may not have been.
- """
- pass
-
- def notImplemented(self):
- raise self.exc.NotImplemented
-
- # The 200-series of statuses aren't errors, so they aren't set
- # by exceptions. 200 OK is the default, of course.
-
- def statusCreated(self):
- self.response().setStatus(201, 'Created')
-
- def statusNoContent(self):
- self.response().setStatus(204, 'No Content')
-
- def statusMultiStatus(self):
- self.response().setStatus(207, 'Multi-Status')
-
- def host(self):
- """The hostname of the server, with port number if necessary
- (i.e., not 80)"""
- env = self.request().environ()
- if env.has_key('SCRIPT_URI'):
- host = env['SCRIPT_URI']
- host = host[host.find('//'):] # get rid of http://
- host = host[:host.find('/')] # get rid of rest of path
- return host
- # @@: maybe this should check if it's https, and the applicable
- # port number for that... then we need a protocol method too
- host = self._environ['HTTP_HOST']
- port = int(self._environ['HTTP_PORT'])
- if port != 80:
- host = "%s:%i" % (host, port)
- return host
-
- def webKitURL(self):
- """Similar to adapterName: this returns the first portion of
- the URL that points to the WebKit base."""
- req = self.request()
- env = req.environ()
- if env.has_key('SCRIPT_URL'):
- path = env['SCRIPT_URL']
- contextName = req.contextName()
- if path.find('/%s/' % contextName) != -1:
- path = path[:path.find('/%s/' % contextName)]
- return path
- else:
- # @@: I should be checking for something else here,
- # like a servlet name or something, as in
- # /WK/SomeServlet (in default context)
- return ''
- return req.adapterName()
-
- def contextURL(self):
- """Everything up to the context (including webKitURL)"""
- req = self.request()
- env = req.environ()
- contextName = req.contextName()
- if env.has_key('SCRIPT_URL'):
- path = env['SCRIPT_URL']
- if path.find('/%s/' % contextName) != -1:
- path = path[:path.find('/%s/' % contextName) + 1 +
- len(contextName)]
- return path
- else:
- return ''
- # @@: There should be a urljoin function... I guess urlparse
- # might even have it, but whatever...
- return '%s/%s' % (req.webKitURL(), contextName)
-
- def servletURL(self, extraPath=1, queryString=0):
- """Everything through the servlet (and perhaps beyond!)"""
- return self.url()
-
- def url(self, servletName=None, extraPath=None, args=None,
- absolute=1, host=0):
- assert absolute, 'Relative URLs not yet supported'
- if not servletName:
- # @@: doesn't work with packages
- servletName = self.__class__.__name__
- extraPath = extraPath or ''
- if args:
- args = "?" + dictToGetArgs(args)
- else:
- args = ''
- if host:
- url = 'http://' + self.host()
- else:
- url = ''
- url = url + self.contextURL()
- url = url + '/' + servletName.replace('.', '/') + extraPath + args
- if self.urlSession():
- url = self.session().sessionEncode(url)
- return url
-
- def urlSession(self):
- """If you want to encode the session ID in the url,
- return True."""
- return 0
-
- def awake(self, transaction):
- Servlet.awake(self, transaction)
- self._transaction = transaction
- self._response = transaction.response()
- self._request = transaction.request()
- self._session = None # don't create unless needed
- self._messagesDisplayed = 0
- self._contentAction = None
- self._exception = None
- self.field = self._request.field
- self.fields = self._request.fields
- self.hasField = self._request.hasField
- assert self._transaction is not None
- assert self._response is not None
- assert self._request is not None
-
- def sleep(self, transaction):
- Servlet.sleep(self, transaction)
- self._session = None
- self._request = None
- self._response = None
- self._transaction = None
- self.field = None
- self.fields = None
- self.hasField = None
- self._exception = None
-
- def respondToGet(self):
- """ Invokes _respond() to handle the transaction. """
- self._respond()
-
- def respondToPost(self):
- """ Invokes _respond() to handle the transaction. """
- self._respond()
-
- def respondToHead(self):
- """
- A correct but inefficient implementation.
- Should perhaps provide Last-Modified.
- """
- bytes = [0]
- d = DummyWriter()
- res = self.response()
- w = res.write
- res.write = d.write
- self.respondToGet(trans)
- res.write = w
- res.setHeader('Content-Length', d.bytes)
-
- def _respond(self):
- """
- Handles actions if an _action_ field is defined, otherwise
- invokes writeHTML().
- Invoked by both respondToGet() and respondToPost(),
- and indirectly by respondToHead().
- """
- req = self.request()
- # Check for actions
- for action in self.actions():
- if req.hasField('_action_%s' % action) \
- or req.hasField('_action_%s.x' % action):
- self._contentAction = action
- self.writeHTML()
-
-
- ## Access ##
-
- def application(self):
- return self._transaction.application()
-
- def transaction(self):
- return self._transaction
-
- def request(self):
- return self._request
-
- def response(self):
- return self._response
-
- def session(self):
- if not self._session:
- self._session = self._transaction.session()
- return self._session
-
- def contentAction(self):
- """
- The kind of action we are handling. None means normal. If
- you use _action_actionName, then it will be the string "actionName".
- If there is an error, it will be "error"
- """
- return self._contentAction
-
- def title(self):
- """
- The title of the page. It is recommended you override
- pageTitle() or set self._title
- """
- if self.contentAction() == "error":
- return self._exception.title()
- else:
- return self.pageTitle()
-
- def pageTitle(self):
- """
- Override to create a dynamic title. You may want to pay
- attention to self.contentAction() (if an _action_* has been
- invoked).
- """
- return self._title
-
- def htTitle(self):
- """
- Subclasses may override this to provide an HTML enhanced
- version of the title. This is the method that should be
- used when including the page title in the actual page
- contents. Override htPageTitle()
- """
- if self.contentAction() == "error":
- return self._exception.htTitle()
- else:
- return self.htPageTitle()
-
- def htPageTitle(self):
- return self.pageTitle()
-
- def htBodyArgs(self):
- """
- Returns the arguments used for the HTML <body> tag. Invoked by
- writeBody(). If you return a dictionary, the attributes given
- will be included, like:
- {'bgcolor': '#ffffff', 'onLoad': 'cacheImages()'}
- """
- return ''
-
- def writeHTML(self):
- """
- Writes all the HTML for the page.
-
- Subclasses may override this method (which is invoked by
- respondToGet() and respondToPost()) or more commonly its
- constituent methods, writeDocType(), writeHead() and
- writeBody().
-
- If you wish to send non-HTML content, or unadorned HTML,
- you might override fullPage()
- """
- full = self.fullPage()
- if not full or self.contentAction() == 'error':
- self.writeDocType()
- self.write('<html>\n')
- self.writeHead()
- self.writeBody()
- self.write('</html>\n')
- else:
- self.writeBodyContent()
-
- def writeDocType(self):
- """
- Invoked by writeHTML() to write the <!DOCTYPE ...> tag. This
- implementation specifies HTML 4.01 Transitional. Subclasses may
- override to specify something else.
-
- You can find out more about doc types by searching for DOCTYPE
- on the web, or visiting:
- http://www.htmlhelp.com/tools/validator/doctype.html
- """
- self.writeln('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">')
-
- def writeHead(self):
- """
- Writes the <head> portion of the page by writing the
- <head>...</head> tags and invoking writeHeadParts() in between.
- """
- self.write('<head>\n')
- self.writeHeadParts()
- self.write('</head>\n')
-
- def writeHeadParts(self):
- """
- Writes the parts inside the <head>...</head> tags. It's best
- to override title(), styleSheet(), styleSheetHref(), and
- headJavaScript(), not the write* methods.
-
- Subclasses can override this to add additional items and
- should invoke super.
- """
- self.writeTitle()
- self.writeStyleSheet()
- self.writeHeadJavascript()
-
- def writeTitle(self):
- self.write('<title>%s</title>\n' % Funcs.htmlEncode(self.title()))
-
- def writeStyleSheet(self):
- """
- Writes stylesheet (CSS) information -- you should probably
- override styleSheetHref() or styleSheet() instead.
- """
- href = self.styleSheetHref()
- if href:
- self.write('<link rel="stylesheet" href="%s" type="text/css">\n'
- % Funcs.htmlEncode(href))
- styles = self.styleSheet()
- if styles:
- self.write('<style type="text/css"><!--\n%s\n--></style>\n'
- % styles)
-
- def styleSheetHref(self):
- return None
-
- def styleSheet(self):
- return None
-
- def writeHeadJavascript(self):
- js = self.headJavascript()
- if js:
- self.write('<script language="JavaScript"><!--\n%s\n//--></script>\n'
- % js)
-
- def headJavascript(self):
- return None
-
- def writeBody(self):
- """
- Writes the <body> portion of the page by writing the
- <body>...</body> (making use of self.htBodyArgs()) and invoking
- self.writeBodyParts() in between.
- """
- wr = self.writeln
- bodyArgs = self.htBodyArgs()
- if type(bodyArgs) is DictionaryType:
- bodyArgs = ' '.join(map(lambda x: '%s="%s"' % (x[0], Funcs.htmlEncode(x[1])),
- bodyArgs.items()))
- if bodyArgs:
- wr('<body %s>' % bodyArgs)
- else:
- wr('<body>')
- self.writeBodyContent()
- wr('</body>')
-
- def writeBodyContent(self):
- a = self.contentAction()
- full = self.fullPage()
- if not full:
- self.writeBodyStart()
- if a is None:
- self.writeContent()
- elif a == "error":
- self.writeErrorContent(self._exception)
- else:
- getattr(self, a)()
- if not full:
- self.writeBodyEnd()
-
- def fullPage(self):
- """
- Return True here if you don't want anything displayed
- besides writeContent (i.e., no headers, footers, HTML,
- etc.) Good for non-HTML content.
- """
- return 0
-
- def writeBodyStart(self):
- """
- Override this to provide a standard header.
- If you want to embed everything in a table, you can
- do something like:
- <table><tr><td>Menu<br>Options</td><td>
- in the header, and in the footer (writeEndBody):
- </td></tr></table>
- """
- self.writeMessages()
-
- def writeBodyEnd(self):
- """Override this to provide a standard footer"""
- pass
-
- def writeContent(self):
- """
- Writes the unique, central content for the page.
-
- Subclasses should override this method (not invoking super) to
- write their unique page content.
-
- Invoked by writeBodyParts().
- """
- self.write('<p> This page has not yet customized its content. </p>\n')
-
- def write(self, *args):
- for arg in args:
- self._response.write(str(arg))
-
- def writeln(self, *args):
- for arg in args:
- self._response.write(str(arg))
- self._response.write('\n')
-
-
- ## Threading ##
-
- def canBeThreaded(self):
- """
- Returns 0 because of the ivars we set up in awake().
- """
- return 0
-
-
- ## Actions ##
-
- def actions(self):
- """
- Returns a list of method names that are allowable actions from
- HTML forms. The default implementation returns [].
- """
- return []
-
- ## Utility functions ##
-
- # (you should just have a standard module for these, though) #
-
- def htmlEncode(self, s):
- return Funcs.htmlEncode(s)
-
- def htmlDecode(self, s):
- return Funcs.htmlDecode(s)
-
- def urlEncode(self, s):
- return Funcs.urlEncode(s)
-
- def urlDecode(self, s):
- return Funcs.urlDecode(s)
-
-
- ## Delegation and forwarding ##
-
- def forward(self, URL):
- """
- Forwards this request to another servlet. See
- Application.forward() for details.
- The main difference is that here you don't have to pass in
- the transaction as the first argument.
- """
- self.application().forward(self.transaction(), URL)
-
- def includeURL(self, URL):
- """
- Includes the response of another servlet in the current
- servlet's response. See Application.includeURL() for details.
- The main difference is that here you don't have to pass in the
- transaction as the first argument.
- """
- self.application().includeURL(self.transaction(), URL)
-
- def callMethodOfServlet(self, URL, method, *args, **kwargs):
- """
- Call a method of another servlet. See
- Application.callMethodOfServlet() for details.
- The main difference is that here you don't have to pass in
- the transaction as the first argument.
- """
- return apply(self.application().callMethodOfServlet, (self.transaction(), URL, method) + args, kwargs)
-
-
- ## Self utility ##
-
- def sessionEncode(self, url=None):
- """
- Utility function to access session.sessionEncode.
- Takes a url and adds the session ID as a parameter. This is for
- cases where you don't know if the client will accepts cookies.
- """
- if url == None:
- url = self.request().uri()
- return self.session().sessionEncode(url)
-
-
- ## Exception reports ##
-
- def writeExceptionReport(self, handler):
- handler.writeTitle(self.__class__.__name__)
- handler.writeln('''Servlets can provide debugging information here by overriding writeExceptionReport().<br>For example:
-<pre> exceptionReportAttrs = 'foo bar baz'.split()
- def writeExceptionReport(self, handler):
- handler.writeTitle(self.__class__.__name__)
- handler.writeAttrs(self, self.exceptionReportAttrs)
- handler.write('any string')
-</pre>
-
-See WebKit/ExceptionHandler.py for more information.
-''')
-
-
- ## Messages ##
-
- def resetResponse(self):
- """
- When you want to throw away everything you've done,
- and start all over again... for instance, if you've had
- an error.
- """
- self._messagesDisplayed = 0
-
- def writeMessages(self):
- """
- Call this in your SitePage or other template, so that
- the messages are displayed at the top of the page.
- In your CSS file you'll want to define a style for the
- "message" class.
- """
- ses = self.session()
- if ses.value('messages', None):
- self.write('<div align=center width="60%%" class="message">%s</div>\n'
- % '<br>\n'.join(ses.value('messages')))
- self._messagesDisplayed = 1
-
- def message(self, *msg):
- """
- Queue up a message to be sent to the user. Even if the page
- is redirected, the message will be sent when they arrive at
- the redirected page. If you set it in your writeContent,
- it may not come to the user until they visit another page --
- in other words, avoid using this in writeContent (except
- when you are about to raise an HTTPError exception).
- """
- msg = ' '.join(map(str, msg))
- ses = self.session()
- if not ses.value('messages', None):
- ses.setValue('messages', [msg])
- else:
- ses.setValue('mesages', ses.value('messages').append(msg))
-
- def sleep(self, trans):
- if self._messagesDisplayed:
- self.session().setValue('messages', [])
- self._transaction = None
- self._response = None
- self._request = None
- self._session = None
- self._exception = None
-
- def pathArgs(self):
- args = self.request().extraURLPath()
- if not args:
- return []
- args = filter(None, args.split('/'))
- return args
+ def __init__(self):
+ Servlet.__init__(self)
+ self._methodForRequestType = {} # a cache; see respond()
+ if not hasattr(self, '_title'):
+ self._title = self.__class__.__name__
+ self.exc = ExceptionGetter(self)
+
+ def respond(self, trans):
+ try:
+ if self.actionLogin:
+ self.actionLogin()
+ self.setup()
+ httpMethodName = trans.request().method()
+ method = self._methodForRequestType.get(httpMethodName)
+ if not method:
+ methName = 'respondTo' + httpMethodName.capitalize()
+ method = getattr(self, methName, self.notImplemented)
+ self._methodForRequestType[httpMethodName] = method
+ method()
+ except HTTPExceptions.HTTPError, v:
+ self._contentAction = 'error'
+ self._exception = v
+ self.resetResponse()
+ trans.response().setStatus(v.code(servlet=self),
+ v.codeMessage(servlet=self))
+ for name, value in v.headers(servlet=self).items():
+ trans.response().setHeader(name, value)
+ self.response().write(v.htDescription(servlet=self))
+ self.teardown()
+
+ actionLogin = None
+
+ def setup(self):
+ pass
+
+ def teardown(self):
+ """
+ Cleanup anything necessary. This method will be called
+ *regardless* of any exceptions. So things that you expect
+ to be initialized may not have been.
+ """
+ pass
+
+ def notImplemented(self):
+ raise self.exc.NotImplemented
+
+ # The 200-series of statuses aren't errors, so they aren't set
+ # by exceptions. 200 OK is the default, of course.
+
+ def statusCreated(self):
+ self.response().setStatus(201, 'Created')
+
+ def statusNoContent(self):
+ self.response().setStatus(204, 'No Content')
+
+ def statusMultiStatus(self):
+ self.response().setStatus(207, 'Multi-Status')
+
+ def host(self):
+ """The hostname of the server, with port number if necessary
+ (i.e., not 80)"""
+ env = self.request().environ()
+ if env.has_key('SCRIPT_URI'):
+ host = env['SCRIPT_URI']
+ host = host[host.find('//'):] # get rid of http://
+ host = host[:host.find('/')] # get rid of rest of path
+ return host
+ # @@: maybe this should check if it's https, and the applicable
+ # port number for that... then we need a protocol method too
+ host = self._environ['HTTP_HOST']
+ port = int(self._environ['HTTP_PORT'])
+ if port != 80:
+ host = "%s:%i" % (host, port)
+ return host
+
+ def webKitURL(self):
+ """Similar to adapterName: this returns the first portion of
+ the URL that points to the WebKit base."""
+ req = self.request()
+ env = req.environ()
+ if env.has_key('SCRIPT_URL'):
+ path = env['SCRIPT_URL']
+ contextName = req.contextName()
+ if path.find('/%s/' % contextName) != -1:
+ path = path[:path.find('/%s/' % contextName)]
+ return path
+ else:
+ # @@: I should be checking for something else here,
+ # like a servlet name or something, as in
+ # /WK/SomeServlet (in default context)
+ return ''
+ return req.adapterName()
+
+ def contextURL(self):
+ """Everything up to the context (including webKitURL)"""
+ req = self.request()
+ env = req.environ()
+ contextName = req.contextName()
+ if env.has_key('SCRIPT_URL'):
+ path = env['SCRIPT_URL']
+ if path.find('/%s/' % contextName) != -1:
+ path = path[:path.find('/%s/' % contextName) + 1 +
+ len(contextName)]
+ return path
+ else:
+ return ''
+ # @@: There should be a urljoin function... I guess urlparse
+ # might even have it, but whatever...
+ return '%s/%s' % (req.webKitURL(), contextName)
+
+ def servletURL(self, extraPath=1, queryString=0):
+ """Everything through the servlet (and perhaps beyond!)"""
+ return self.url()
+
+ def url(self, servletName=None, extraPath=None, args=None,
+ absolute=1, host=0):
+ assert absolute, 'Relative URLs not yet supported'
+ if not servletName:
+ # @@: doesn't work with packages
+ servletName = self.__class__.__name__
+ extraPath = extraPath or ''
+ if args:
+ args = "?" + dictToGetArgs(args)
+ else:
+ args = ''
+ if host:
+ url = 'http://' + self.host()
+ else:
+ url = ''
+ url = url + self.contextURL()
+ url = url + '/' + servletName.replace('.', '/') + extraPath + args
+ if self.urlSession():
+ url = self.session().sessionEncode(url)
+ return url
+
+ def urlSession(self):
+ """If you want to encode the session ID in the url,
+ return True."""
+ return 0
+
+ def awake(self, transaction):
+ Servlet.awake(self, transaction)
+ self._transaction = transaction
+ self._response = transaction.response()
+ self._request = transaction.request()
+ self._session = None # don't create unless needed
+ self._messagesDisplayed = 0
+ self._contentAction = None
+ self._exception = None
+ self.field = self._request.field
+ self.fields = self._request.fields
+ self.hasField = self._request.hasField
+ assert self._transaction is not None
+ assert self._response is not None
+ assert self._request is not None
+
+ def sleep(self, transaction):
+ Servlet.sleep(self, transaction)
+ self._session = None
+ self._request = None
+ self._response = None
+ self._transaction = None
+ self.field = None
+ self.fields = None
+ self.hasField = None
+ self._exception = None
+
+ def respondToGet(self):
+ """ Invokes _respond() to handle the transaction. """
+ self._respond()
+
+ def respondToPost(self):
+ """ Invokes _respond() to handle the transaction. """
+ self._respond()
+
+ def respondToHead(self):
+ """
+ A correct but inefficient implementation.
+ Should perhaps provide Last-Modified.
+ """
+ bytes = [0]
+ d = DummyWriter()
+ res = self.response()
+ w = res.write
+ res.write = d.write
+ self.respondToGet(trans)
+ res.write = w
+ res.setHeader('Content-Length', d.bytes)
+
+ def _respond(self):
+ """
+ Handles actions if an _action_ field is defined, otherwise
+ invokes writeHTML().
+ Invoked by both respondToGet() and respondToPost(),
+ and indirectly by respondToHead().
+ """
+ req = self.request()
+ # Check for actions
+ for action in self.actions():
+ if req.hasField('_action_%s' % action) \
+ or req.hasField('_action_%s.x' % action):
+ self._contentAction = action
+ self.writeHTML()
+
+
+ ## Access ##
+
+ def application(self):
+ return self._transaction.application()
+
+ def transaction(self):
+ return self._transaction
+
+ def request(self):
+ return self._request
+
+ def response(self):
+ return self._response
+
+ def session(self):
+ if not self._session:
+ self._session = self._transaction.session()
+ return self._session
+
+ def contentAction(self):
+ """
+ The kind of action we are handling. None means normal. If
+ you use _action_actionName, then it will be the string "actionName".
+ If there is an error, it will be "error"
+ """
+ return self._contentAction
+
+ def title(self):
+ """
+ The title of the page. It is recommended you override
+ pageTitle() or set self._title
+ """
+ if self.contentAction() == "error":
+ return self._exception.title()
+ else:
+ return self.pageTitle()
+
+ def pageTitle(self):
+ """
+ Override to create a dynamic title. You may want to pay
+ attention to self.contentAction() (if an _action_* has been
+ invoked).
+ """
+ return self._title
+
+ def htTitle(self):
+ """
+ Subclasses may override this to provide an HTML enhanced
+ version of the title. This is the method that should be
+ used when including the page title in the actual page
+ contents. Override htPageTitle()
+ """
+ if self.contentAction() == "error":
+ return self._exception.htTitle()
+ else:
+ return self.htPageTitle()
+
+ def htPageTitle(self):
+ return self.pageTitle()
+
+ def htBodyArgs(self):
+ """
+ Returns the arguments used for the HTML <body> tag. Invoked by
+ writeBody(). If you return a dictionary, the attributes given
+ will be included, like:
+ {'bgcolor': '#ffffff', 'onLoad': 'cacheImages()'}
+ """
+ return ''
+
+ def writeHTML(self):
+ """
+ Writes all the HTML for the page.
+
+ Subclasses may override this method (which is invoked by
+ respondToGet() and respondToPost()) or more commonly its
+ constituent methods, writeDocType(), writeHead() and
+ writeBody().
+
+ If you wish to send non-HTML content, or unadorned HTML,
+ you might override fullPage()
+ """
+ full = self.fullPage()
+ if not full or self.contentAction() == 'error':
+ self.writeDocType()
+ self.write('<html>\n')
+ self.writeHead()
+ self.writeBody()
+ self.write('</html>\n')
+ else:
+ self.writeBodyContent()
+
+ def writeDocType(self):
+ """
+ Invoked by writeHTML() to write the <!DOCTYPE ...> tag. This
+ implementation specifies HTML 4.01 Transitional. Subclasses may
+ override to specify something else.
+
+ You can find out more about doc types by searching for DOCTYPE
+ on the web, or visiting:
+ http://www.htmlhelp.com/tools/validator/doctype.html
+ """
+ self.writeln('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">')
+
+ def writeHead(self):
+ """
+ Writes the <head> portion of the page by writing the
+ <head>...</head> tags and invoking writeHeadParts() in between.
+ """
+ self.write('<head>\n')
+ self.writeHeadParts()
+ self.write('</head>\n')
+
+ def writeHeadParts(self):
+ """
+ Writes the parts inside the <head>...</head> tags. It's best
+ to override title(), styleSheet(), styleSheetHref(), and
+ headJavaScript(), not the write* methods.
+
+ Subclasses can override this to add additional items and
+ should invoke super.
+ """
+ self.writeTitle()
+ self.writeStyleSheet()
+ self.writeHeadJavascript()
+
+ def writeTitle(self):
+ self.write('<title>%s</title>\n' % Funcs.htmlEncode(self.title()))
+
+ def writeStyleSheet(self):
+ """
+ Writes stylesheet (CSS) information -- you should probably
+ override styleSheetHref() or styleSheet() instead.
+ """
+ href = self.styleSheetHref()
+ if href:
+ self.write('<link rel="stylesheet" href="%s" type="text/css">\n'
+ % Funcs.htmlEncode(href))
+ styles = self.styleSheet()
+ if styles:
+ self.write('<style type="text/css">'
+ '<!--\n%s\n--></style>\n' % styles)
+
+ def styleSheetHref(self):
+ return None
+
+ def styleSheet(self):
+ return None
+
+ def writeHeadJavascript(self):
+ js = self.headJavascript()
+ if js:
+ self.write('<script language="JavaScript">'
+ '<!--\n%s\n//--></script>\n' % js)
+
+ def headJavascript(self):
+ return None
+
+ def writeBody(self):
+ """
+ Writes the <body> portion of the page by writing the
+ <body>...</body> (making use of self.htBodyArgs()) and invoking
+ self.writeBodyParts() in between.
+ """
+ wr = self.writeln
+ bodyArgs = self.htBodyArgs()
+ if type(bodyArgs) is DictionaryType:
+ bodyArgs = ' '.join(map(lambda x: '%s="%s"' % (x[0],
+ Funcs.htmlEncode(x[1])), bodyArgs.items()))
+ if bodyArgs:
+ wr('<body %s>' % bodyArgs)
+ else:
+ wr('<body>')
+ self.writeBodyContent()
+ wr('</body>')
+
+ def writeBodyContent(self):
+ a = self.contentAction()
+ full = self.fullPage()
+ if not full:
+ self.writeBodyStart()
+ if a is None:
+ self.writeContent()
+ elif a == "error":
+ self.writeErrorContent(self._exception)
+ else:
+ getattr(self, a)()
+ if not full:
+ self.writeBodyEnd()
+
+ def fullPage(self):
+ """
+ Return True here if you don't want anything displayed
+ besides writeContent (i.e., no headers, footers, HTML,
+ etc.) Good for non-HTML content.
+ """
+ return 0
+
+ def writeBodyStart(self):
+ """
+ Override this to provide a standard header.
+ If you want to embed everything in a table, you can
+ do something like:
+ <table><tr><td>Menu<br>Options</td><td>
+ in the header, and in the footer (writeEndBody):
+ </td></tr></table>
+ """
+ self.writeMessages()
+
+ def writeBodyEnd(self):
+ """Override this to provide a standard footer"""
+ pass
+
+ def writeContent(self):
+ """
+ Writes the unique, central content for the page.
+
+ Subclasses should override this method (not invoking super) to
+ write their unique page content.
+
+ Invoked by writeBodyParts().
+ """
+ self.write('<p> This page has not yet customized its content. </p>\n')
+
+ def write(self, *args):
+ for arg in args:
+ self._response.write(str(arg))
+
+ def writeln(self, *args):
+ for arg in args:
+ self._response.write(str(arg))
+ self._response.write('\n')
+
+
+ ## Threading ##
+
+ def canBeThreaded(self):
+ """
+ Returns 0 because of the ivars we set up in awake().
+ """
+ return 0
+
+
+ ## Actions ##
+
+ def actions(self):
+ """
+ Returns a list of method names that are allowable actions from
+ HTML forms. The default implementation returns [].
+ """
+ return []
+
+ ## Utility functions ##
+
+ # (you should just have a standard module for these, though) #
+
+ def htmlEncode(self, s):
+ return Funcs.htmlEncode(s)
+
+ def htmlDecode(self, s):
+ return Funcs.htmlDecode(s)
+
+ def urlEncode(self, s):
+ return Funcs.urlEncode(s)
+
+ def urlDecode(self, s):
+ return Funcs.urlDecode(s)
+
+
+ ## Delegation and forwarding ##
+
+ def forward(self, URL):
+ """
+ Forwards this request to another servlet. See
+ Application.forward() for details.
+ The main difference is that here you don't have to pass in
+ the transaction as the first argument.
+ """
+ self.application().forward(self.transaction(), URL)
+
+ def includeURL(self, URL):
+ """
+ Includes the response of another servlet in the current
+ servlet's response. See Application.includeURL() for details.
+ The main difference is that here you don't have to pass in the
+ transaction as the first argument.
+ """
+ self.application().includeURL(self.transaction(), URL)
+
+ def callMethodOfServlet(self, URL, method, *args, **kwargs):
+ """
+ Call a method of another servlet. See
+ Application.callMethodOfServlet() for details.
+ The main difference is that here you don't have to pass in
+ the transaction as the first argument.
+ """
+ return apply(self.application().callMethodOfServlet,
+ (self.transaction(), URL, method) + args, kwargs)
+
+
+ ## Self utility ##
+
+ def sessionEncode(self, url=None):
+ """
+ Utility function to access session.sessionEncode.
+ Takes a url and adds the session ID as a parameter. This is for
+ cases where you don't know if the client will accepts cookies.
+ """
+ if url == None:
+ url = self.request().uri()
+ return self.session().sessionEncode(url)
+
+
+ ## Exception reports ##
+
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeln('''Servlets can provide debugging information here'
+ by overriding writeExceptionReport().<br>For example:
+ <pre>
+ exceptionReportAttrs = 'foo bar baz'.split()
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeAttrs(self, self.exceptionReportAttrs)
+ handler.write('any string')
+ </pre>
+
+ See WebKit/ExceptionHandler.py for more information.
+ ''')
+
+
+ ## Messages ##
+
+ def resetResponse(self):
+ """
+ When you want to throw away everything you've done,
+ and start all over again... for instance, if you've had
+ an error.
+ """
+ self._messagesDisplayed = 0
+
+ def writeMessages(self):
+ """
+ Call this in your SitePage or other template, so that
+ the messages are displayed at the top of the page.
+ In your CSS file you'll want to define a style for the
+ "message" class.
+ """
+ ses = self.session()
+ if ses.value('messages', None):
+ self.write('<div align=center width="60%%" class="message">%s</div>\n'
+ % '<br>\n'.join(ses.value('messages')))
+ self._messagesDisplayed = 1
+
+ def message(self, *msg):
+ """
+ Queue up a message to be sent to the user. Even if the page
+ is redirected, the message will be sent when they arrive at
+ the redirected page. If you set it in your writeContent,
+ it may not come to the user until they visit another page --
+ in other words, avoid using this in writeContent (except
+ when you are about to raise an HTTPError exception).
+ """
+ msg = ' '.join(map(str, msg))
+ ses = self.session()
+ if not ses.value('messages', None):
+ ses.setValue('messages', [msg])
+ else:
+ ses.setValue('mesages', ses.value('messages').append(msg))
+
+ def sleep(self, trans):
+ if self._messagesDisplayed:
+ self.session().setValue('messages', [])
+ self._transaction = None
+ self._response = None
+ self._request = None
+ self._session = None
+ self._exception = None
+
+ def pathArgs(self):
+ args = self.request().extraURLPath()
+ if not args:
+ return []
+ args = filter(None, args.split('/'))
+ return args
class DummyWriter:
- """Used for HEAD requests"""
+ """Used for HEAD requests"""
- def __init__(self):
- self.bytes = 0
+ def __init__(self):
+ self.bytes = 0
- def write(self, *args):
- for arg in args:
- self.bytes = self.bytes + len(arg)
+ def write(self, *args):
+ for arg in args:
+ self.bytes = self.bytes + len(arg)
class ExceptionGetter:
- """Used to handle exceptions"""
+ """Used to handle exceptions"""
- def __init__(self, servlet):
- self._servlet = servlet
+ def __init__(self, servlet):
+ self._servlet = servlet
- def __getattr__(self, attr):
- return HTTPExceptions.exception(self._servlet.request().contextName(),
- attr)
+ def __getattr__(self, attr):
+ return HTTPExceptions.exception(
+ self._servlet.request().contextName(), attr)
Modified: Webware/trunk/WebKit/Tasks/__init__.py
==============================================================================
--- Webware/trunk/WebKit/Tasks/__init__.py (original)
+++ Webware/trunk/WebKit/Tasks/__init__.py Thu Nov 3 07:46:41 2005
@@ -1 +1 @@
-###
+#
Modified: Webware/trunk/WebKit/WebwarePathLocation.py
==============================================================================
--- Webware/trunk/WebKit/WebwarePathLocation.py (original)
+++ Webware/trunk/WebKit/WebwarePathLocation.py Thu Nov 3 07:46:41 2005
@@ -1,2 +1,2 @@
-## Used solely to have a module to import from a definite location ##
+# Used solely to have a module to import from a definite location
Modified: Webware/trunk/WebUtils/FieldStorage.py
==============================================================================
--- Webware/trunk/WebUtils/FieldStorage.py (original)
+++ Webware/trunk/WebUtils/FieldStorage.py Thu Nov 3 07:46:41 2005
@@ -21,13 +21,13 @@
Explicitly parse the query string, even if it's a POST request
"""
self._method = string.upper(self._environ['REQUEST_METHOD'])
- if self._method == "GET" or self._method == "HEAD":
+ if self._method == "GET" or self._method == "HEAD":
# print __file__, "bailing on GET or HEAD request"
- return #bail because cgi.FieldStorage already did this
+ return # bail because cgi.FieldStorage already did this
self._qs = self._environ.get('QUERY_STRING', None)
if not self._qs:
# print __file__, "bailing on no query_string"
- return ##bail if no query string
+ return # bail if no query string
name_value_pairs = string.splitfields(self._qs, '&')
dict = {}
Modified: Webware/trunk/bin/checksrc.py
==============================================================================
--- Webware/trunk/bin/checksrc.py (original)
+++ Webware/trunk/bin/checksrc.py Thu Nov 3 07:46:41 2005
@@ -6,7 +6,10 @@
INTRODUCTION
-This utility checks for violations of various source code conventions in the hope of keeping the project clean and consistent. Please see Webware/Documentation/StyleGuidelines.html for more information including some guidelines not checked for by this utility.
+This utility checks for violations of various source code conventions
+in the hope of keeping the project clean and consistent.
+Please see Webware/Documentation/StyleGuidelines.html for more information
+including some guidelines not checked for by this utility.
COMMAND LINE
@@ -27,7 +30,8 @@
AS A MODULE AND CLASS
-If you imported this as a module, you would use the CheckSrc class, possibly like so:
+If you imported this as a module, you would use the CheckSrc class,
+possibly like so:
from CheckSrc import CheckSrc
CheckSrc().check()
@@ -41,21 +45,32 @@
cs.setOutput('results.text')
cs.check()
-And of course, you could subclass CheckSrc() to customize it, which is why even command line utils get done with classes (rather than collections of functions and nekkid code).
+And of course, you could subclass CheckSrc() to customize it,
+which is why even command line utils get done with classes
+(rather than collections of functions and nekkid code).
-You can also setDirectory(), setOutput() setRecurse() and setVerbose() the defaults of which are '.', sys.stdout, 1 and 0.
+You can also setDirectory(), setOutput() setRecurse() and setVerbose()
+the defaults of which are '.', sys.stdout, 1 and 0.
CAVEATS
-Note that checksrc.py takes a line oriented approach. Since it does not actually properly parse Python code, it can be fooled in some cases. Therefore, it's possible to get false alarms. While we could implement a full parser to close the gap, doing so would be labor intensive with little pay off. So we live with a few false alarms.
-
-However, we currently don't skip multi-line strings which is the source of *many* false alarms. This needs to be addressed soon. There is some code for it in checkFileLines(), but it is far from complete and may be the wrong approach.
+Note that checksrc.py takes a line oriented approach. Since it does not
+actually properly parse Python code, it can be fooled in some cases.
+Therefore, it's possible to get false alarms. While we could implement
+a full parser to close the gap, doing so would be labor intensive with
+little pay off. So we live with a few false alarms.
+
+However, we currently don't skip multi-line strings which is the source
+of *many* false alarms. This needs to be addressed soon. There is some
+code for it in checkFileLines(), but it is far from complete and ma
+ be the wrong approach.
CONFIG FILES
-You can modify the behavior of checksrc.py for a particular directory by creating a .checksrc.config file like so:
+You can modify the behavior of checksrc.py for a particular directory
+by creating a .checksrc.config file like so:
{
'SkipDirs': ['Cache'],
@@ -69,7 +84,9 @@
Some notes:
* You can specify some or all of the options.
* SkipDirs and SkipFiles both require lists of filenames.
- * DisableError keys are error codes defined by checksrc.py. You can find these out by running checksrc with the -h command line option or checking the source below.
+ * DisableError keys are error codes defined by checksrc.py.
+ You can find these out by running checksrc with the
+ -h command line option or checking the source below.
* The value for disabling an error:
* Can be an individual filename or a list of filenames.
* Can be '*' for "all files".
@@ -88,7 +105,9 @@
X Method and attribute names have no underscores after the first character.
X Expressions following if, while and return are not enclosed in parenthesees, ().
- Data attributes not only start with an underscore _, but are followed by a lower case letter.
- - Class defs and category comments, ## Like this ## are preceded by 2 blank lines and are followed by one blank line (unless the class implementation is pass).
+ - Class defs and category comments, ## Like this ##
+ are preceded by 2 blank lines and are followed by one blank line
+ (unless the class implementation is pass).
FUTURE
@@ -101,7 +120,9 @@
Consider (optionally) displaying the source line.
-Maybe: Experiment with including the name of the last seen method/function with the error messages to help guide the user to where the error occurred.
+Maybe: Experiment with including the name of the last seen method/function
+with the error messages to help guide the user to where the error occurred.
+
"""
@@ -164,14 +185,19 @@
return self._directory
def setDirectory(self, dir):
- """ Sets the directory that checking starts in. """
+ """Sets the directory that checking starts in."""
self._directory = dir
def output(self):
return self._out
def setOutput(self, output):
- """ Sets the destination output which can either be an object which must respond to write() or a string which is a filename used for one invocation of check(). """
+ """Set the destination output.
+
+ It can either be an object which must respond to write() or
+ a string which is a filename used for one invocation of check().
+
+ """
if type(output) is type(''):
self._out = open(output, 'w')
self._shouldClose = 1
@@ -183,21 +209,29 @@
return self._recurse
def setRecurse(self, flag):
- """ Sets whether or not to recurse into subdirectories. """
+ """Set whether or not to recurse into subdirectories."""
self._recurse = flag
def verbose(self):
return self._verbose
def setVerbose(self, flag):
- """ Sets whether or not to print extra information during check (such as every directory and file name scanned). """
+ """Set whether or not to print extra information during check.
+
+ For instance, print every directory and file name scanned.
+ """
self._verbose = flag
## Command line use ##
def readArgs(self, args=sys.argv):
- """ Reads a list of arguments in command line style (e.g., sys.argv). You can pass your own args if you like, otherwise sys.argv is used. Returns 1 on success; 0 otherwise. """
+ """Read a list of arguments in command line style (e.g., sys.argv).
+
+ You can pass your own args if you like, otherwise sys.argv is used.
+ Returns 1 on success; 0 otherwise.
+
+ """
setDir = setOut = 0
for arg in args[1:]:
if arg=='-h' or arg=='--help':
@@ -262,14 +296,22 @@
## Printing, errors, etc. ##
def write(self, *args):
- """ Invoked by self for all printing so that output can be easily redirected. """
+ """Invoked by self for all printing.
+
+ This allows output to be easily redirected.
+
+ """
write = self._out.write
for arg in args:
write(str(arg))
def error(self, msgCode, args):
- """ Invoked by self when a source code error is detected. Prints the error message and it's location. Does not raise exceptions or halt the program. """
+ """Invoked by self when a source code error is detected.
+ Prints the error message and it's location.
+ Does not raise exceptions or halt the program.
+
+ """
# Implement the DisableErrors option
disableNames = self.setting('DisableErrors', {}).get(msgCode, [])
if '*' in disableNames or self._fileName in disableNames:
@@ -281,12 +323,21 @@
self.write(self.location(), msg, '\n')
def fatalError(self, msg):
- """ Reports a fatal error such as an invalid configuration file and raises CheckSrcError. """
+ """Report a fatal error and raise CheckSrcError.
+
+ For instance, handle an invalid configuration file.
+
+ """
self.write('FATAL ERROR: %s\n' % msg)
raise CheckSrcError
def location(self):
- """ Returns a string indicating the current location such as "fileName:lineNum:charNum". The string may be shorter if the latter components are undefined. """
+ """Return a string indicating the current location.
+
+ The string format is "fileName:lineNum:charNum:".
+ The string may be shorter if the latter components are undefined.
+
+ """
s = ''
if self._fileName!=None:
s = s + self._fileName
@@ -299,7 +350,7 @@
return s
def printDir(self):
- """ Self utility method to print the directory being processed. """
+ """Self utility method to print the directory being processed."""
self.write('\n', self._dirName, '\n')
self._printedDir = 1
@@ -316,7 +367,6 @@
dict = eval(contents)
except:
self.fatalError('Invalid config file at %s.' % filename)
-
# For DisableErrors, we expect a dictionary keyed by error codes.
# For each code, we allow a value that is either a string or a list.
# But for ease-of-use purposes, we now convert single strings to
@@ -347,14 +397,18 @@
self._out.close()
def checkDir(self, arg, dirName, names):
- """ Invoked by os.path.walk() which is kicked off by check(). Recursively checks the given directory and all it's subdirectories. """
+ """Invoked by os.path.walk() which is kicked off by check().
+
+ Recursively checks the given directory and all it's subdirectories.
+
+ """
# Initialize location attributes.
# These are updated while processing and
# used when reporting errors.
- self._dirName = dirName
+ self._dirName = dirName
self._fileName = None
- self._lineNum = None
- self._charNum = None
+ self._lineNum = None
+ self._charNum = None
self._printedDir = 0
if self._verbose:
@@ -418,7 +472,7 @@
# @@ 2000-10-10 ce: not finished. maybe not even good approach...
# This version handles multiline strings
self._lineNum = 1
- inMLS = 0 # MS = multi-line string
+ inMLS = 0 # MS = multi-line string
for line in lines:
# the dbg var is used for debugging output
# you could set to self, sys.stdout, _DummyWriter,
@@ -529,7 +583,7 @@
if '_' in group[6:]:
bad = 1
# Make sure it's not one of those __foo__ identifiers.
- group = group[5:] # shave off "self."
+ group = group[5:] # shave off "self."
if len(group)>4 and group[:2]=='__' and group[-2:]=='__':
if not '_' in group[2:-2]:
bad = 0
@@ -543,7 +597,7 @@
keywords = ['if', 'while', 'return']
msg = string.join(keywords[:-1], ', ') + ' and ' + keywords[-1]
parts = string.split(line)
- if len(parts)>1 and parts[0] in keywords and parts[1][0]=='(':
+ if len(parts)>1 and parts[0] in keywords and parts[1][0]=='(':
keyword = parts[0]
self.error('ExtraParens', locals())
|