Author: ianb
Date: 2004-04-21 21:01:39 -0600 (Wed, 21 Apr 2004)
New Revision: 95
Added:
Component/component.py
Component/cpage.py
Removed:
Component/__init__.py
Log:
refactored file layout
Deleted: Component/__init__.py
===================================================================
--- Component/__init__.py 2004-04-22 02:58:59 UTC (rev 94)
+++ Component/__init__.py 2004-04-22 03:01:39 UTC (rev 95)
@@ -1,386 +0,0 @@
-from WebKit.Page import Page
-from WebKit.HTTPExceptions import *
-from WebUtils import Funcs
-
-class CPage(Page):
-
- """
- CPage is an alternative to WebKit.Page, which adds support
- for Components.
-
- Components can contain functionality like user logins,
- widgets and layout generation, template handling... whatever.
-
- Components for a servlet are listed in the components
- class variable, like::
-
- class SitePage(CPage):
- components = [UserComponent(), OtherFancyComponent()]
-
- You can also run ``servlet.addComponent(component)``.
-
- Components can respond to events, and add methods to the
- servlet. See the ServletComponent class for more about writing
- components.
-
- To fire your own event use callEvent, like::
-
- self.callEvent('eventname', ...)
-
- Use whatever arguments you want. Interested components
- will implement a method eventnameEvent(), which will be
- passed those arguments. callEvent will return a false
- value if a component wants to abort this event (because
- the component deals with the event on its own).
- """
-
- # Events listed in _standardEvents will be run a bit faster,
- # as CPage keeps track of these events specially. You can
- # add your custom events here.
- _standardEvents = ['awake', 'sleep', 'exception']
-
- def __init__(self):
- Page.__init__(self)
- self._instanceComponents = []
- self._standardEventHandlers = {}
- for eventName in self._standardEvents:
- self._standardEventHandlers[eventName] = []
- for componentFactory in self.components:
- self.addComponent(componentFactory)
-
- def actions(self):
- return []
-
- def addComponent(self, componentFactory):
- component = componentFactory.componentFor(self)
- if not component:
- return
- component.addComponentTo(self)
- self._instanceComponents.append(component)
- for name in self._standardEventHandlers.keys():
- if getattr(component, '%sEvent' % name, None):
- self._standardEventHandlers[name].append(getattr(component, '%sEvent' % name))
-
- def callEvent(self, eventName, *args, **kw):
- """
- Fire an event, to interested components.
-
- @@: maybe this should be replaced with PyDispatcher:
- http://pydispatcher.sourceforge.net/
- """
- if self._standardEventHandlers.has_key(eventName):
- for handler in self._standardEventHandlers[eventName]:
- if not handler(*args, **kw):
- return 0
- else:
- for component in self._instanceComponents:
- meth = getattr(component, "%sEvent" % eventName, None)
- if meth and not meth(*args, **kw):
- return 0
- return 1
-
- def awake(self, trans):
- Page.awake(self, trans)
- self._title = self.__class__.__name__
- self.setView('writeContent')
- self.callEvent('awake', trans)
-
- def sleep(self, trans):
- self.callEvent('sleep', trans)
- self._title = None
- self._view = None
- Page.sleep(self, trans)
-
- def runTransaction(self, trans):
- try:
- try:
- self.awake(trans)
- self.respond(trans)
- except Exception, e:
- if self.handleException(e) == 'break':
- return
- for component in self._instanceComponents:
- if component.handleExceptionEvent(e) == 'break':
- return
- raise
- finally:
- self.sleep(trans)
-
- def handleException(self, exc):
- pass
-
- def servletLink(self, name, absolute=False, extraURLPath=None,
- args=None):
- """
- Links to the named servlet; or use 'path/to/servlet'; do not
- include a leading /
- """
- assert not name.startswith('/'), 'The link name must not start with a / (%r)' % name
- url = ''
- req = self.request()
- env = req.environ()
- if absolute:
- # @@: Should detect HTTPS
- url = 'http://%s' % env.get('HTTP_HOST', env['SERVER_NAME'])
- port = env.get('SERVER_PORT', '80')
- if port != '80':
- url = url + ':' + port
- url = url + req.adapterName() + '/' + name
- if extraURLPath:
- if not extraURLPath.startswith('/'):
- extraURLPath = '/' + extraURLPath
- url = url + extraURLPath
- if args:
- fields = []
- if isinstance(args, dict):
- args = args.items()
- for name, value in args:
- fields.append('%s=%s' % (self.urlEncode(str(name)),
- self.urlEncode(str(value))))
- url = url + '?' + '&'.join(fields)
- return url
-
- def linkToSelf(self, absolute=False, extraURLPath=None, args=None):
- # @@: should test for default context
- return self.servletLink(
- self.request().contextName() + '/' + self.__class__.__name__,
- absolute=absolute,
- extraURLPath=extraURLPath, args=args)
-
- ############################################################
- ## Reorganized action system:
- ############################################################
-
- def writeHeader(self):
- pass
-
- def writeFooter(self):
- pass
-
- def title(self):
- return self._title
-
- def viewMethod(self):
- if type(self._view) in (type(""), type(u"")):
- return getattr(self, self._view)
- else:
- return self._view
-
- def setView(self, view):
- self._view = view
-
- def writeBodyParts(self):
- self.writeHeader()
- self.viewMethod()()
- self.writeFooter()
-
- def _respond(self, transaction):
- """
- Handles actions if an ``_action_`` or ``_action_XXX``
- field is defined, otherwise invokes `writeHTML`.
- Invoked by both `respondToGet` and `respondToPost`.
-
- Copied with slight modification from Page._respond
- """
- req = transaction.request()
-
- # Support old style actions from 0.5.x and below.
- # Use setting OldStyleActions in Application.config
- # to use this.
- if self.transaction().application().setting('OldStyleActions', ) \
- and req.hasField('_action_'):
- action = self.methodNameForAction(req.field('_action_'))
- actions = self._actionSet()
- if actions.has_key(action):
- self.preAction(action)
- apply(getattr(self, action), (transaction,))
- self.postAction(action)
- return
- else:
- raise PageError, "Action '%s' is not in the public list of actions, %s, for %s." % (action, actions.keys(), self)
-
- # Check for actions
- # @@: This is the only change for CPage:
- for action in self._actionSet().keys():
- if req.hasField('_action_%s' % action) or \
- req.field('_action_', None) == action or \
- (req.hasField('_action_%s.x' % action) and \
- req.hasField('_action_%s.y' % action)):
- self.handleAction(action)
- return
-
- self.defaultAction()
-
- def _actionSet(self):
- if not hasattr(self, '_actionDict'):
- self._actionDict = {}
- for action in self.actions():
- self._actionDict[action] = 1
- for component in self._instanceComponents:
- for action in component.actions():
- self._actionDict[action] = 1
- return self._actionDict
-
- def preAction(self, actionName):
- pass
-
- def postAction(self, actionName):
- pass
-
- components = []
-
-class Component:
-
- """
- Subclasses of Component are the public view of components,
- i.e., the objects that go in the CPage.components class
- variable.
-
- However, CPage instances actually work with ServletComponents,
- which are bound to a specific servlet. So in most cases this
- factory class need only be used like::
-
- class SomeServletComponent(ServletComponent):
- # real work...
-
- class SomeComponent(Component):
- _componentClass = SomeServletComponent
- """
-
- def __init__(self, *args, **kw):
- self._args = args
- self._kw = kw
-
- def componentFor(self, servlet):
- return self.createComponent()
-
- def createComponent(self):
- return self._componentClass(*self._args, **self._kw)
-
-
-class ServletComponent:
-
- """
- The real workhorse of the component system are the subclasses
- of ServletComponent. These are where you implement your
- component functionality.
-
- To hook your class to the servlet, you may wish to define:
-
- ``*Event`` methods:
- Events are fired by name, such as the 'awake' event (fired
- in the awake() method). Appending 'Event' gives the
- method name for that event, e.g., 'awakeEvent'. If the
- class defines an appropriate method, then it will be
- automatically called. Different events take different
- arguments.
-
- ``_servletMethods``:
- Class variable, a list. The names of methods which should
- be added to the servlet. E.g.::
-
- class BrowserServletComponent(ServletComponent):
- _servletMethods = ['browser']
-
- def browser(self):
- req = self.servlet().request()
- # ... code that returns an object encapsulating
- # browser compatibility information ...
-
- Then servlets that used this component would have a method
- ``self.browser()``. self is still bound to the
- ServletComponent instance, not the servlet instance.
-
- ``_handleExceptions``:
- Class variable, a list. The exceptions (or names of
- exceptions) that this class handles. E.g.::
-
- class SearchOn404(ServletComponent):
- _handleExceptions = ['HTTPNotFound']
-
- def exceptionHTTPNotFoundEvent(self, exc):
- self.servlet().write('...')
- # returning 'break' means the exception has been
- # handled and needn't be propagated up:
- return 'break'
-
- Actual exceptions are simply fired as 'exception' events,
- i.e., calling exceptionEvent. By using _handleExceptions
- you can catch subclasses of these exceptions, and ignore
- other exceptions.
-
- In your methods, you'll probably want to take advantage of
- these useful methods:
-
- ``servlet()``:
- The servlet this instance is bound to.
- ``optionalMethod(methodName, defaultValue, *args, **kw)``:
- Call the method `methodName` of our servlet, with
- *args and **kw. If the servlet does not define such
- a method, return `defaultValue`.
- """
-
- def __init__(self):
- if self.handleExceptions():
- self.exceptionEvent = self.handleExceptionEvent
-
- _servletMethods = []
- _handleExceptions = []
-
- def addComponentTo(self, servlet):
- """
- Modify the servlet in some way specific to this component.
- General hook for the component to add functionality
- and methods to the servlet. By default it adds any
- methods named in the _servletMethods attribute to the
- servlet.
- """
- self._servlet = servlet
- for method in self._servletMethods:
- if not getattr(servlet, method, None):
- setattr(servlet, method, getattr(self, method))
-
- def actions(self):
- return []
-
- def servlet(self):
- return self._servlet
-
- def optionalMethod(self, methodName, default, *args, **kw):
- """
- Calls a method of the servlet. If the method does
- not exist, returns default.
- """
- try:
- meth = getattr(self._servlet, methodName)
- except AttributeError:
- return default
- else:
- return meth(*args, **kw)
-
- def handleExceptions(self):
- return self._handleExceptions
-
- def handleExceptionEvent(self, exc):
- for handled in self.handleExceptions():
- if type(handled) is type(""):
- handled = eval(handled)
- if isinstance(exc, handled):
- meth = getattr(self, '%sEvent' % handled.__name__)
- if not meth(exc):
- return 0
- return 1
-
- def htmlEncode(self, v):
- return Funcs.htmlEncode(v)
-
- def urlEncode(self, v):
- return Funcs.urlEncode(v)
-
- # Some null, standard event handlers:
- awakeEvent = None
- sleepEvent = None
- exceptionEvent = None
-
-def InstallInWebKit(appServer):
- pass
Added: Component/component.py
===================================================================
--- Component/component.py 2004-04-22 02:58:59 UTC (rev 94)
+++ Component/component.py 2004-04-22 03:01:39 UTC (rev 95)
@@ -0,0 +1,154 @@
+from WebUtils import Funcs
+
+class Component:
+
+ """
+ Subclasses of Component are the public view of components,
+ i.e., the objects that go in the CPage.components class
+ variable.
+
+ However, CPage instances actually work with ServletComponents,
+ which are bound to a specific servlet. So in most cases this
+ factory class need only be used like::
+
+ class SomeServletComponent(ServletComponent):
+ # real work...
+
+ class SomeComponent(Component):
+ _componentClass = SomeServletComponent
+ """
+
+ def __init__(self, *args, **kw):
+ self._args = args
+ self._kw = kw
+
+ def componentFor(self, servlet):
+ return self.createComponent()
+
+ def createComponent(self):
+ return self._componentClass(*self._args, **self._kw)
+
+
+class ServletComponent:
+
+ """
+ The real workhorse of the component system are the subclasses
+ of ServletComponent. These are where you implement your
+ component functionality.
+
+ To hook your class to the servlet, you may wish to define:
+
+ ``*Event`` methods:
+ Events are fired by name, such as the 'awake' event (fired
+ in the awake() method). Appending 'Event' gives the
+ method name for that event, e.g., 'awakeEvent'. If the
+ class defines an appropriate method, then it will be
+ automatically called. Different events take different
+ arguments.
+
+ ``_servletMethods``:
+ Class variable, a list. The names of methods which should
+ be added to the servlet. E.g.::
+
+ class BrowserServletComponent(ServletComponent):
+ _servletMethods = ['browser']
+
+ def browser(self):
+ req = self.servlet().request()
+ # ... code that returns an object encapsulating
+ # browser compatibility information ...
+
+ Then servlets that used this component would have a method
+ ``self.browser()``. self is still bound to the
+ ServletComponent instance, not the servlet instance.
+
+ ``_handleExceptions``:
+ Class variable, a list. The exceptions (or names of
+ exceptions) that this class handles. E.g.::
+
+ class SearchOn404(ServletComponent):
+ _handleExceptions = ['HTTPNotFound']
+
+ def exceptionHTTPNotFoundEvent(self, exc):
+ self.servlet().write('...')
+ # returning 'break' means the exception has been
+ # handled and needn't be propagated up:
+ return 'break'
+
+ Actual exceptions are simply fired as 'exception' events,
+ i.e., calling exceptionEvent. By using _handleExceptions
+ you can catch subclasses of these exceptions, and ignore
+ other exceptions.
+
+ In your methods, you'll probably want to take advantage of
+ these useful methods:
+
+ ``servlet()``:
+ The servlet this instance is bound to.
+ ``optionalMethod(methodName, defaultValue, *args, **kw)``:
+ Call the method `methodName` of our servlet, with
+ *args and **kw. If the servlet does not define such
+ a method, return `defaultValue`.
+ """
+
+ def __init__(self):
+ if self.handleExceptions():
+ self.exceptionEvent = self.handleExceptionEvent
+
+ _servletMethods = []
+ _handleExceptions = []
+
+ def addComponentTo(self, servlet):
+ """
+ Modify the servlet in some way specific to this component.
+ General hook for the component to add functionality
+ and methods to the servlet. By default it adds any
+ methods named in the _servletMethods attribute to the
+ servlet.
+ """
+ self._servlet = servlet
+ for method in self._servletMethods:
+ if not getattr(servlet, method, None):
+ setattr(servlet, method, getattr(self, method))
+
+ def actions(self):
+ return []
+
+ def servlet(self):
+ return self._servlet
+
+ def optionalMethod(self, methodName, default, *args, **kw):
+ """
+ Calls a method of the servlet. If the method does
+ not exist, returns default.
+ """
+ try:
+ meth = getattr(self._servlet, methodName)
+ except AttributeError:
+ return default
+ else:
+ return meth(*args, **kw)
+
+ def handleExceptions(self):
+ return self._handleExceptions
+
+ def handleExceptionEvent(self, exc):
+ for handled in self.handleExceptions():
+ if type(handled) is type(""):
+ handled = eval(handled)
+ if isinstance(exc, handled):
+ meth = getattr(self, '%sEvent' % handled.__name__)
+ if not meth(exc):
+ return 0
+ return 1
+
+ def htmlEncode(self, v):
+ return Funcs.htmlEncode(v)
+
+ def urlEncode(self, v):
+ return Funcs.urlEncode(v)
+
+ # Some null, standard event handlers:
+ awakeEvent = None
+ sleepEvent = None
+ exceptionEvent = None
Copied: Component/cpage.py (from rev 94, Component/__init__.py)
===================================================================
--- Component/__init__.py 2004-04-22 02:58:59 UTC (rev 94)
+++ Component/cpage.py 2004-04-22 03:01:39 UTC (rev 95)
@@ -0,0 +1,229 @@
+from WebKit.Page import Page
+from WebKit.HTTPExceptions import *
+
+class CPage(Page):
+
+ """
+ CPage is an alternative to WebKit.Page, which adds support
+ for Components.
+
+ Components can contain functionality like user logins,
+ widgets and layout generation, template handling... whatever.
+
+ Components for a servlet are listed in the components
+ class variable, like::
+
+ class SitePage(CPage):
+ components = [UserComponent(), OtherFancyComponent()]
+
+ You can also run ``servlet.addComponent(component)``.
+
+ Components can respond to events, and add methods to the
+ servlet. See the ServletComponent class for more about writing
+ components.
+
+ To fire your own event use callEvent, like::
+
+ self.callEvent('eventname', ...)
+
+ Use whatever arguments you want. Interested components
+ will implement a method eventnameEvent(), which will be
+ passed those arguments. callEvent will return a false
+ value if a component wants to abort this event (because
+ the component deals with the event on its own).
+ """
+
+ # Events listed in _standardEvents will be run a bit faster,
+ # as CPage keeps track of these events specially. You can
+ # add your custom events here.
+ _standardEvents = ['awake', 'sleep', 'exception']
+
+ def __init__(self):
+ Page.__init__(self)
+ self._instanceComponents = []
+ self._standardEventHandlers = {}
+ for eventName in self._standardEvents:
+ self._standardEventHandlers[eventName] = []
+ for componentFactory in self.components:
+ self.addComponent(componentFactory)
+
+ def actions(self):
+ return []
+
+ def addComponent(self, componentFactory):
+ component = componentFactory.componentFor(self)
+ if not component:
+ return
+ component.addComponentTo(self)
+ self._instanceComponents.append(component)
+ for name in self._standardEventHandlers.keys():
+ if getattr(component, '%sEvent' % name, None):
+ self._standardEventHandlers[name].append(getattr(component, '%sEvent' % name))
+
+ def callEvent(self, eventName, *args, **kw):
+ """
+ Fire an event, to interested components.
+
+ @@: maybe this should be replaced with PyDispatcher:
+ http://pydispatcher.sourceforge.net/
+ """
+ if self._standardEventHandlers.has_key(eventName):
+ for handler in self._standardEventHandlers[eventName]:
+ if not handler(*args, **kw):
+ return 0
+ else:
+ for component in self._instanceComponents:
+ meth = getattr(component, "%sEvent" % eventName, None)
+ if meth and not meth(*args, **kw):
+ return 0
+ return 1
+
+ def awake(self, trans):
+ Page.awake(self, trans)
+ self._title = self.__class__.__name__
+ self.setView('writeContent')
+ self.callEvent('awake', trans)
+
+ def sleep(self, trans):
+ self.callEvent('sleep', trans)
+ self._title = None
+ self._view = None
+ Page.sleep(self, trans)
+
+ def runTransaction(self, trans):
+ try:
+ try:
+ self.awake(trans)
+ self.respond(trans)
+ except Exception, e:
+ if self.handleException(e) == 'break':
+ return
+ for component in self._instanceComponents:
+ if component.handleExceptionEvent(e) == 'break':
+ return
+ raise
+ finally:
+ self.sleep(trans)
+
+ def handleException(self, exc):
+ pass
+
+ def servletLink(self, name, absolute=False, extraURLPath=None,
+ args=None):
+ """
+ Links to the named servlet; or use 'path/to/servlet'; do not
+ include a leading /
+ """
+ assert not name.startswith('/'), 'The link name must not start with a / (%r)' % name
+ url = ''
+ req = self.request()
+ env = req.environ()
+ if absolute:
+ # @@: Should detect HTTPS
+ url = 'http://%s' % env.get('HTTP_HOST', env['SERVER_NAME'])
+ port = env.get('SERVER_PORT', '80')
+ if port != '80':
+ url = url + ':' + port
+ url = url + req.adapterName() + '/' + name
+ if extraURLPath:
+ if not extraURLPath.startswith('/'):
+ extraURLPath = '/' + extraURLPath
+ url = url + extraURLPath
+ if args:
+ fields = []
+ if isinstance(args, dict):
+ args = args.items()
+ for name, value in args:
+ fields.append('%s=%s' % (self.urlEncode(str(name)),
+ self.urlEncode(str(value))))
+ url = url + '?' + '&'.join(fields)
+ return url
+
+ def linkToSelf(self, absolute=False, extraURLPath=None, args=None):
+ # @@: should test for default context
+ return self.servletLink(
+ self.request().contextName() + '/' + self.__class__.__name__,
+ absolute=absolute,
+ extraURLPath=extraURLPath, args=args)
+
+ ############################################################
+ ## Reorganized action system:
+ ############################################################
+
+ def writeHeader(self):
+ pass
+
+ def writeFooter(self):
+ pass
+
+ def title(self):
+ return self._title
+
+ def viewMethod(self):
+ if type(self._view) in (type(""), type(u"")):
+ return getattr(self, self._view)
+ else:
+ return self._view
+
+ def setView(self, view):
+ self._view = view
+
+ def writeBodyParts(self):
+ self.writeHeader()
+ self.viewMethod()()
+ self.writeFooter()
+
+ def _respond(self, transaction):
+ """
+ Handles actions if an ``_action_`` or ``_action_XXX``
+ field is defined, otherwise invokes `writeHTML`.
+ Invoked by both `respondToGet` and `respondToPost`.
+
+ Copied with slight modification from Page._respond
+ """
+ req = transaction.request()
+
+ # Support old style actions from 0.5.x and below.
+ # Use setting OldStyleActions in Application.config
+ # to use this.
+ if self.transaction().application().setting('OldStyleActions', ) \
+ and req.hasField('_action_'):
+ action = self.methodNameForAction(req.field('_action_'))
+ actions = self._actionSet()
+ if actions.has_key(action):
+ self.preAction(action)
+ apply(getattr(self, action), (transaction,))
+ self.postAction(action)
+ return
+ else:
+ raise PageError, "Action '%s' is not in the public list of actions, %s, for %s." % (action, actions.keys(), self)
+
+ # Check for actions
+ # @@: This is the only change for CPage:
+ for action in self._actionSet().keys():
+ if req.hasField('_action_%s' % action) or \
+ req.field('_action_', None) == action or \
+ (req.hasField('_action_%s.x' % action) and \
+ req.hasField('_action_%s.y' % action)):
+ self.handleAction(action)
+ return
+
+ self.defaultAction()
+
+ def _actionSet(self):
+ if not hasattr(self, '_actionDict'):
+ self._actionDict = {}
+ for action in self.actions():
+ self._actionDict[action] = 1
+ for component in self._instanceComponents:
+ for action in component.actions():
+ self._actionDict[action] = 1
+ return self._actionDict
+
+ def preAction(self, actionName):
+ pass
+
+ def postAction(self, actionName):
+ pass
+
+ components = []
|