[cig-commits] r7784 - in cs/pythia/trunk: cig/web/seismo/events opal/components opal/conf/urls opal/core/handlers opal/db opal/views

leif at geodynamics.org leif at geodynamics.org
Tue Aug 7 20:37:44 PDT 2007


Author: leif
Date: 2007-08-07 20:37:43 -0700 (Tue, 07 Aug 2007)
New Revision: 7784

Added:
   cs/pythia/trunk/cig/web/seismo/events/components.py
   cs/pythia/trunk/cig/web/seismo/events/parsers.py
Removed:
   cs/pythia/trunk/cig/web/seismo/events/urls.py
   cs/pythia/trunk/cig/web/seismo/events/views.py
   cs/pythia/trunk/opal/conf/urls/defaults.py
Modified:
   cs/pythia/trunk/opal/components/WebComponent.py
   cs/pythia/trunk/opal/components/__init__.py
   cs/pythia/trunk/opal/core/handlers/base.py
   cs/pythia/trunk/opal/db/queries.py
   cs/pythia/trunk/opal/views/defaults.py
Log:
Using 'events' as a guiding example, I began replacing Django's
"module oriented" application interface with something more
object-oriented, so that I can avoid global variables/functions and
use novel things like inheritance and polymorphism.

Simplified 'queries': collapsed the Query class cluster into a single
class, and added the factory class Inquirer.


Added: cs/pythia/trunk/cig/web/seismo/events/components.py
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/components.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/cig/web/seismo/events/components.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -0,0 +1,228 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                       cig.web.seismo.events
+#
+# Copyright (c) 2007, California Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#
+#    * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+#    * Redistributions in binary form must reproduce the above
+#    copyright notice, this list of conditions and the following
+#    disclaimer in the documentation and/or other materials provided
+#    with the distribution.
+#
+#    * Neither the name of the California Institute of Technology nor
+#    the names of its contributors may be used to endorse or promote
+#    products derived from this software without specific prior
+#    written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from models import Event, Source, DataSource, Region
+from parsers import HarvardCMTSearchResultsParser
+
+from cig.seismo.events import CMTSolution
+from opal import forms
+from opal.http import HttpResponseRedirect
+from opal.shortcuts import render_to_response
+from opal.template.context import RequestContext
+
+
+class EventBrowser(WebComponent):
+
+
+    models = [Event, Source, DataSource, Region]
+
+
+    def __init__(self, home):
+
+        self.home = home # '/specfem3dglobe/events/'
+        
+        self.urlpatterns = self.patterns(
+            (r'^$', self.eventList),
+            (r'^search/$', self.eventSearch),
+            (r'^add/$', self.addEvent),
+            (r'^upload/$', self.uploadEvent),
+            (r'^sources/(?P<object_id>\d+)/$', self.sourceDetail),
+            (r'^sources/(?P<object_id>\d+)/edit/$', self.editSource),
+            (r'^sources/(?P<object_id>\d+)/delete/$', self.deleteSource),
+            (r'^(?P<object_id>\d+)/$', self.eventDetail),
+            (r'^(?P<object_id>\d+)/edit/$', self.editEvent),
+            (r'^(?P<object_id>\d+)/delete/$', self.deleteEvent),
+            )
+        
+        return
+
+
+    # views
+
+    def eventList(self, request):
+        return self.genericObjectList(
+            request,
+            queryset = Event.user_objects.all(),
+            allow_empty = True,
+            )
+
+
+    def eventDetail(self, request):
+        return self.genericObjectDetail(
+            request,
+            queryset = Event.user_objects.all()
+            )
+
+
+    def editEvent(self, request):
+        return self.genericUpdateObject(
+            request,
+            model = Event,
+            post_save_redirect = self.home,
+            follow: { 'user': False },
+            )
+
+
+    def deleteEvent(self, request):
+        return self.genericDeleteObject(
+            request,
+            model: Event,
+            post_delete_redirect: self.home,
+            )
+
+
+    def eventSearch(self, request):
+        import urllib2
+
+        if request.method == 'GET':
+            return render_to_response('events/event_search.html',
+                                      {},
+                                      RequestContext(request, {})) 
+
+        # Simply forward the search request to Harvard.
+        query = request.POST.urlencode()
+        url = "http://www.seismology.harvard.edu/cgi-bin/CMT3/form?" + query
+        src = urllib2.urlopen(url)
+
+        # Parse the results.
+        parser = HarvardCMTSearchResultsParser()
+        parser.feed(src.read())
+
+        parser.close()
+        src.close()
+
+        # Make sure secondary objects exist in the database.
+        for event in parser.cmtList:
+            # The try-get()-except shouldn't be necessary, but simply
+            # using save() causes Django to die in the database backend.
+            try:
+                ds = DataSource.objects.get(name=event.dataSource)
+            except DataSource.DoesNotExist:
+                ds = DataSource(event.dataSource)
+                ds.save()
+            try:
+                ds = Region.objects.get(name=event.regionName)
+            except:
+                r = Region(event.regionName)
+                r.save()
+
+        return render_to_response('events/event_search_results.html',
+                                  {'event_list': parser.cmtList },
+                                  RequestContext(request, {})) 
+
+
+    def addEvent(self, request):
+        from forms import AddSingleSourceEventManipulator
+        from os.path import dirname
+
+        manipulator = AddSingleSourceEventManipulator()
+
+        if request.method == 'POST':
+            new_data = request.POST.copy()
+            errors = manipulator.get_validation_errors(new_data)
+            if not errors:
+                manipulator.do_html2python(new_data)
+                new_event = manipulator.save(new_data, request.user)
+                url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
+                return HttpResponseRedirect(url)
+        else:
+            errors = new_data = {}
+
+        form = forms.FormWrapper(manipulator, new_data, errors)
+        return render_to_response('events/single_source_event_form.html',
+                                  {'form': form},
+                                  RequestContext(request, {}))
+
+
+    def uploadEvent(self, request):
+        from forms import UploadEventManipulator
+        from os.path import dirname
+
+        manipulator = UploadEventManipulator()
+
+        if request.method == 'POST':
+            new_data = request.POST.copy()
+            new_data.update(request.FILES)
+            errors = manipulator.get_validation_errors(new_data)
+            if not errors:
+                manipulator.do_html2python(new_data)
+                new_event = manipulator.save(new_data, request.user)
+                url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
+                return HttpResponseRedirect(url)
+        else:
+            errors = new_data = {}
+
+        form = forms.FormWrapper(manipulator, new_data, errors)
+        return render_to_response('events/event_upload.html',
+                                  {'form': form},
+                                  RequestContext(request, {}))
+
+
+    # views -- sources
+
+    def sourceDetail(self, request):
+        return self.genericObjectDetail(
+            request,
+            queryset = Source.objects.all()
+            )
+
+
+    def editSource(self, request):
+        return self.genericUpdateObject(
+            request,
+            model = Source,
+            post_save_redirect = self.home,
+            follow: { 'user': False },
+            )
+
+
+    def deleteSource(self, request):
+        return self.genericDeleteObject(
+            request,
+            model: Source,
+            post_delete_redirect: self.home,
+            )
+
+
+# end of file

Copied: cs/pythia/trunk/cig/web/seismo/events/parsers.py (from rev 7782, cs/pythia/trunk/cig/web/seismo/events/views.py)
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/views.py	2007-08-07 21:45:19 UTC (rev 7782)
+++ cs/pythia/trunk/cig/web/seismo/events/parsers.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                       cig.web.seismo.events
+#
+# Copyright (c) 2006, California Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#
+#    * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+#    * Redistributions in binary form must reproduce the above
+#    copyright notice, this list of conditions and the following
+#    disclaimer in the documentation and/or other materials provided
+#    with the distribution.
+#
+#    * Neither the name of the California Institute of Technology nor
+#    the names of its contributors may be used to endorse or promote
+#    products derived from this software without specific prior
+#    written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from HTMLParser import HTMLParser
+
+
+class HarvardCMTSearchResultsParser(HTMLParser):
+
+    def __init__(self):
+        HTMLParser.__init__(self)
+        self.state = 0
+        self.cmtList = None
+        
+    def handle_starttag(self, tag, attrs):
+        if self.state == 0:
+            if tag == 'body':
+                self.state = 1
+        elif self.state == 2:
+            if tag == 'pre':
+                self.state = 3
+        return
+
+    def handle_endtag(self, tag):
+        if tag == 'body':
+            self.state = 0
+        elif self.state == 3:
+            if tag == 'pre':
+                self.state = 1
+        return
+
+    def handle_data(self, data):
+        if self.state == 1:
+            if data.find('Output in CMTSOLUTION format') != -1:
+                self.state = 2
+        elif self.state == 3:
+            self.cmtList = CMTSolution.parse(data)
+        return
+
+
+# end of file

Deleted: cs/pythia/trunk/cig/web/seismo/events/urls.py
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/urls.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/cig/web/seismo/events/urls.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-#                       cig.web.seismo.events
-#
-# Copyright (c) 2006, California Institute of Technology
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#
-#    * Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-#
-#    * Redistributions in binary form must reproduce the above
-#    copyright notice, this list of conditions and the following
-#    disclaimer in the documentation and/or other materials provided
-#    with the distribution.
-#
-#    * Neither the name of the California Institute of Technology nor
-#    the names of its contributors may be used to endorse or promote
-#    products derived from this software without specific prior
-#    written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-
-
-from opal.conf.urls.defaults import *
-from models import Event, Source
-
-
-event_list_detail_args = {
-    'queryset': Event.user_objects.all(),
-    'allow_empty': True,
-}
-
-event_detail_args = {
-    'queryset': Event.user_objects.all(),
-}
-
-event_create_update_args = {
-    'model': Event,
-    'post_save_redirect': '/specfem3dglobe/events/',
-    'follow': { 'user': False },
-    }
-
-event_delete_args = {
-    'model': Event,
-    'post_delete_redirect': '/specfem3dglobe/events/',
-    }
-
-source_detail_args = {
-    'queryset': Source.objects.all(),
-}
-
-source_create_update_args = {
-    'model': Source,
-    'post_save_redirect': '/specfem3dglobe/events/',
-    }
-
-source_delete_args = {
-    'model': Source,
-    'post_delete_redirect': '/specfem3dglobe/events/',
-    }
-
-
-urlpatterns = patterns('',
-    (r'^$', 'opal.views.generic.list_detail.object_list', event_list_detail_args),
-    (r'^search/$', 'cig.web.seismo.events.views.search'),
-    (r'^add/$', 'cig.web.seismo.events.views.add'),
-    (r'^upload/$', 'cig.web.seismo.events.views.upload'),
-    (r'^sources/(?P<object_id>\d+)/$', 'opal.views.generic.list_detail.object_detail', source_detail_args),
-    (r'^sources/(?P<object_id>\d+)/edit/$', 'opal.views.generic.create_update.update_object', source_create_update_args),
-    (r'^sources/(?P<object_id>\d+)/delete/$', 'opal.views.generic.create_update.delete_object', source_delete_args),
-    (r'^(?P<object_id>\d+)/$', 'opal.views.generic.list_detail.object_detail', event_detail_args),
-    (r'^(?P<object_id>\d+)/edit/$', 'opal.views.generic.create_update.update_object', event_create_update_args),
-    (r'^(?P<object_id>\d+)/delete/$', 'opal.views.generic.create_update.delete_object', event_delete_args),
-)
-
-
-# end of file

Deleted: cs/pythia/trunk/cig/web/seismo/events/views.py
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/views.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/cig/web/seismo/events/views.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,178 +0,0 @@
-#!/usr/bin/env python
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-#                       cig.web.seismo.events
-#
-# Copyright (c) 2006, California Institute of Technology
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#
-#    * Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-#
-#    * Redistributions in binary form must reproduce the above
-#    copyright notice, this list of conditions and the following
-#    disclaimer in the documentation and/or other materials provided
-#    with the distribution.
-#
-#    * Neither the name of the California Institute of Technology nor
-#    the names of its contributors may be used to endorse or promote
-#    products derived from this software without specific prior
-#    written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-
-
-from cig.seismo.events import CMTSolution
-from opal import forms
-from opal.http import HttpResponseRedirect
-from opal.shortcuts import render_to_response
-from opal.template.context import RequestContext
-from HTMLParser import HTMLParser
-from models import DataSource, Region
-
-
-def search(request):
-    import urllib2
-
-    if request.method == 'GET':
-        return render_to_response('events/event_search.html',
-                                  {},
-                                  RequestContext(request, {})) 
-
-    # Simply forward the search request to Harvard.
-    query = request.POST.urlencode()
-    url = "http://www.seismology.harvard.edu/cgi-bin/CMT3/form?" + query
-    src = urllib2.urlopen(url)
-
-    # Parse the results.
-    parser = HarvardCMTSearchResultsParser()
-    parser.feed(src.read())
-    
-    parser.close()
-    src.close()
-
-    # Make sure secondary objects exist in the database.
-    for event in parser.cmtList:
-        # The try-get()-except shouldn't be necessary, but simply
-        # using save() causes Django to die in the database backend.
-        try:
-            ds = DataSource.objects.get(name=event.dataSource)
-        except DataSource.DoesNotExist:
-            ds = DataSource(event.dataSource)
-            ds.save()
-        try:
-            ds = Region.objects.get(name=event.regionName)
-        except:
-            r = Region(event.regionName)
-            r.save()
-    
-    return render_to_response('events/event_search_results.html',
-                              {'event_list': parser.cmtList },
-                              RequestContext(request, {})) 
-
-
-def add(request):
-    from forms import AddSingleSourceEventManipulator
-    from os.path import dirname
-    
-    manipulator = AddSingleSourceEventManipulator()
-    
-    if request.method == 'POST':
-        new_data = request.POST.copy()
-        errors = manipulator.get_validation_errors(new_data)
-        if not errors:
-            manipulator.do_html2python(new_data)
-            new_event = manipulator.save(new_data, request.user)
-            url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
-            return HttpResponseRedirect(url)
-    else:
-        errors = new_data = {}
-
-    form = forms.FormWrapper(manipulator, new_data, errors)
-    return render_to_response('events/single_source_event_form.html',
-                              {'form': form},
-                              RequestContext(request, {}))
-
-
-def upload(request):
-    from forms import UploadEventManipulator
-    from os.path import dirname
-    
-    manipulator = UploadEventManipulator()
-    
-    if request.method == 'POST':
-        new_data = request.POST.copy()
-        new_data.update(request.FILES)
-        errors = manipulator.get_validation_errors(new_data)
-        if not errors:
-            manipulator.do_html2python(new_data)
-            new_event = manipulator.save(new_data, request.user)
-            url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
-            return HttpResponseRedirect(url)
-    else:
-        errors = new_data = {}
-
-    form = forms.FormWrapper(manipulator, new_data, errors)
-    return render_to_response('events/event_upload.html',
-                              {'form': form},
-                              RequestContext(request, {}))
-
-
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# support code
-
-
-class HarvardCMTSearchResultsParser(HTMLParser):
-
-    def __init__(self):
-        HTMLParser.__init__(self)
-        self.state = 0
-        self.cmtList = None
-        
-    def handle_starttag(self, tag, attrs):
-        if self.state == 0:
-            if tag == 'body':
-                self.state = 1
-        elif self.state == 2:
-            if tag == 'pre':
-                self.state = 3
-        return
-
-    def handle_endtag(self, tag):
-        if tag == 'body':
-            self.state = 0
-        elif self.state == 3:
-            if tag == 'pre':
-                self.state = 1
-        return
-
-    def handle_data(self, data):
-        if self.state == 1:
-            if data.find('Output in CMTSOLUTION format') != -1:
-                self.state = 2
-        elif self.state == 3:
-            self.cmtList = CMTSolution.parse(data)
-        return
-
-
-# end of file

Modified: cs/pythia/trunk/opal/components/WebComponent.py
===================================================================
--- cs/pythia/trunk/opal/components/WebComponent.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/components/WebComponent.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -12,16 +12,103 @@
 
 
 from pyre.components import Component
+import opal.views as views
+import opal.controllers as controllers
 
+from opal.template import Context, RequestContext, loader
+from opal import http
 
 class WebComponent(Component):
 
 
-    children = {}
+    models = []
+    urlpatterns = []
 
 
-    def view(self):
-        return self.DefaultViewClass(self)
+    # urlpatterns support
 
+    include = lambda urlconf_module: [urlconf_module]
 
+    def patterns(self, *tuples):
+        from opal.core.urlresolvers import RegexURLPattern, RegexURLResolver
+        pattern_list = []
+        for t in tuples:
+            regex, view_or_include = t[:2]
+            default_kwargs = t[2:]
+            if type(view_or_include) == list:
+                include = view_or_include[0]
+                pattern_list.append(RegexURLResolver(regex, include, *default_kwargs))
+            else:
+                view = view_or_include
+                pattern_list.append(RegexURLPattern(regex, view, *default_kwargs))
+        return pattern_list
+
+
+    # generic views
+
+    def genericObjectList(request, **kwds):
+        view = views.ListView(**kwds)
+        return view.response(request)
+
+
+    def genericObjectDetail(request, **kwds):
+        view = views.DetailView(**kwds)
+        return view.response(request)
+
+
+    # generic views -- CRUD
+
+    def genericCreateObject(request, post_save_redirect=None, follow=None, **kwds):
+        controller = controllers.CreationController(
+            post_redirect = post_save_redirect,
+            follow = follow,
+            )
+        view = views.DetailView(controller = controller, **kwds)
+        return view.response(request)
+
+
+    def genericUpdateObject(request, post_save_redirect=None, follow=None, **kwds):
+        controller = controllers.UpdateController(
+            post_redirect = post_save_redirect,
+            follow = follow,
+            )
+        view = views.DetailView(controller = controller, **kwds)
+        return view.response(request)
+
+
+    def genericDeleteObject(request, post_delete_redirect, **kwds):
+        controller = controllers.DeletionController(
+            post_redirect = post_delete_redirect,
+            )
+        view = views.DetailView(controller = controller, **kwds)
+        return view.response(request)
+
+
+    # errors
+
+    def handler404(request, template_name='404.html'):
+        """
+        Default 404 handler, which looks for the requested URL in the redirects
+        table, redirects if found, and displays 404 page if not redirected.
+
+        Templates: `404.html`
+        Context:
+            request_path
+                The path of the requested URL (e.g., '/app/pages/bad_page/')
+        """
+        t = loader.get_template(template_name) # You need to create a 404.html template.
+        return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path})))
+
+
+    def handler500(request, template_name='500.html'):
+        """
+        500 error handler.
+
+        Templates: `500.html`
+        Context: None
+        """
+        t = loader.get_template(template_name) # You need to create a 500.html template.
+        return http.HttpResponseServerError(t.render(Context({})))
+
+
 # end of file

Modified: cs/pythia/trunk/opal/components/__init__.py
===================================================================
--- cs/pythia/trunk/opal/components/__init__.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/components/__init__.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -12,6 +12,9 @@
 #
 
 
+from WebComponent import WebComponent
+
+
 def actor(name):
     from GenericActor import GenericActor
     return GenericActor(name)

Deleted: cs/pythia/trunk/opal/conf/urls/defaults.py
===================================================================
--- cs/pythia/trunk/opal/conf/urls/defaults.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/conf/urls/defaults.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,19 +0,0 @@
-from opal.core.urlresolvers import RegexURLPattern, RegexURLResolver
-
-__all__ = ['handler404', 'handler500', 'include', 'patterns']
-
-handler404 = 'opal.views.defaults.page_not_found'
-handler500 = 'opal.views.defaults.server_error'
-
-include = lambda urlconf_module: [urlconf_module]
-
-def patterns(prefix, *tuples):
-    pattern_list = []
-    for t in tuples:
-        regex, view_or_include = t[:2]
-        default_kwargs = t[2:]
-        if type(view_or_include) == list:
-            pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
-        else:
-            pattern_list.append(RegexURLPattern(regex, prefix and (prefix + '.' + view_or_include) or view_or_include, *default_kwargs))
-    return pattern_list

Modified: cs/pythia/trunk/opal/core/handlers/base.py
===================================================================
--- cs/pythia/trunk/opal/core/handlers/base.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/core/handlers/base.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -60,9 +60,10 @@
             if response:
                 return response
 
+        site = settings
+        resolver = site.resolve
         try:
-            site = settings
-            callback, callback_args, callback_kwargs = site.resolve(request.path)
+            callback, callback_args, callback_kwargs = resolver.resolve(path)
 
             # Apply view middleware
             for middleware_method in self._view_middleware:

Modified: cs/pythia/trunk/opal/db/queries.py
===================================================================
--- cs/pythia/trunk/opal/db/queries.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/db/queries.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -13,49 +13,32 @@
 
 class Query(object):
 
+    def __init__(self, fieldName, key):
+        self.fieldName = fieldName
+        self.key = key
+
     def apply(self, queryset):
-        raise NotImplementedError()
+        return queryset.filter(**{self.fieldName: self.key})
 
     def get(self, queryset):
         queryset = self.apply(queryset)
         return queryset.get()
 
-
-class ObjectIdQuery(Query):
-
-    def __init__(self, object_id):
-        Query.__init__(self)
-        self.object_id = object_id
-
-    def apply(self, queryset):
-        return queryset.filter(pk=self.object_id)
-
     def __str__(self):
-        return "object_id=%s" % self.object_id
+        return "%s='%s'" % (self.fieldName, self.key)
 
 
-class ObjectSlugQuery(Query):
 
-    def __init__(self, slug, slug_field):
-        Query.__init__(self)
-        self.slug = slug
-        self.slug_field = slug_field
+class Inquirer(object):
+    
+    def newQuery(self, key):
+        return self.Query(fieldName, key)
 
-    def apply(self, queryset):
-        return queryset.filter(**{self.slug_field: self.slug})
+    def __init__(self, fieldName):
+        self.fieldName = fieldName
 
-    def __str__(self):
-        return "%s='%s'" % (self.slug_field, self.slug)
 
+primaryInquirer = Inquirer('pk')
 
-def objectQuery(object_id=None, slug=None, slug_field=None):
-    if object_id:
-        query = ObjectIdQuery(object_id)
-    elif slug and slug_field:
-        query = ObjectSlugQuery(slug, slug_field)
-    else:
-        raise AttributeError, "Object query must be created with either an object_id or a slug/slug_field."
-    return query
 
-
 # end of file

Modified: cs/pythia/trunk/opal/views/defaults.py
===================================================================
--- cs/pythia/trunk/opal/views/defaults.py	2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/views/defaults.py	2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,5 +1,4 @@
 from opal.core.exceptions import ObjectDoesNotExist
-from opal.template import Context, RequestContext, loader
 from opal.contrib.contenttypes.models import ContentType
 from opal.contrib.sites.models import Site
 from opal import http
@@ -65,25 +64,3 @@
     else:
         return http.HttpResponseRedirect(absurl)
 
-def page_not_found(request, template_name='404.html'):
-    """
-    Default 404 handler, which looks for the requested URL in the redirects
-    table, redirects if found, and displays 404 page if not redirected.
-
-    Templates: `404.html`
-    Context:
-        request_path
-            The path of the requested URL (e.g., '/app/pages/bad_page/')
-    """
-    t = loader.get_template(template_name) # You need to create a 404.html template.
-    return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path})))
-
-def server_error(request, template_name='500.html'):
-    """
-    500 error handler.
-
-    Templates: `500.html`
-    Context: None
-    """
-    t = loader.get_template(template_name) # You need to create a 500.html template.
-    return http.HttpResponseServerError(t.render(Context({})))



More information about the cig-commits mailing list