Merge lp:~scott-armitage/pyng/uri-pattern into lp:pyng

Proposed by Scott Armitage
Status: Merged
Approved by: Scott Armitage
Approved revision: 17
Merged at revision: not available
Proposed branch: lp:~scott-armitage/pyng/uri-pattern
Merge into: lp:pyng
Diff against target: None lines
To merge this branch: bzr merge lp:~scott-armitage/pyng/uri-pattern
Reviewer Review Type Date Requested Status
Scott Armitage Approve
Review via email: mp+6787@code.launchpad.net

Commit message

Added URI handling and basic exception definitions.

To post a comment you must log in.
Revision history for this message
Scott Armitage (scott-armitage) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'PyngPyng/__init__.py' (properties changed: +x to -x)
--- PyngPyng/__init__.py 2009-05-24 23:57:05 +0000
+++ PyngPyng/__init__.py 2009-05-26 02:25:17 +0000
@@ -16,6 +16,7 @@
1616
17# Extension modules -----------------------------------------------------------17# Extension modules -----------------------------------------------------------
18from PyngPyng.pages import Page, ErrorPage18from PyngPyng.pages import Page, ErrorPage
19from PyngPyng import exceptions as exc
19from PyngPyng import version20from PyngPyng import version
2021
21# Module function -------------------------------------------------------------22# Module function -------------------------------------------------------------
@@ -53,9 +54,9 @@
53 # Run the requested page54 # Run the requested page
54 try:55 try:
55 page = Page(environ)56 page = Page(environ)
56 page.parse_request()57 page.do_it()
57 page.execute()58 if not page.content:
58 page.composite()59 raise exc.NoContentException('Expected page content to be generated. Perhaps the page compositor has not been implemented?')
59 start_response(page.status,page.headers)60 start_response(page.status,page.headers)
60 return page.content61 return page.content
61 except:62 except:
6263
=== modified file 'PyngPyng/exceptions.py'
--- PyngPyng/exceptions.py 2009-05-25 03:11:31 +0000
+++ PyngPyng/exceptions.py 2009-05-26 02:09:15 +0000
@@ -14,6 +14,12 @@
14# Exception class -------------------------------------------------------------14# Exception class -------------------------------------------------------------
15class Pyngception(Exception):15class Pyngception(Exception):
16 """An internal PyngPyng exception occured."""16 """An internal PyngPyng exception occured."""
17 http_code = '500 Internal Server Error'
18
19
20# Exception class -------------------------------------------------------------
21class NoContentException(Pyngception):
22 """The page content is empty or None."""
17 pass23 pass
1824
1925
2026
=== modified file 'PyngPyng/pages.py'
--- PyngPyng/pages.py 2009-05-25 03:11:31 +0000
+++ PyngPyng/pages.py 2009-05-26 02:25:17 +0000
@@ -12,22 +12,58 @@
1212
13# Extension modules -----------------------------------------------------------13# Extension modules -----------------------------------------------------------
14from PyngPyng import version14from PyngPyng import version
15from PyngPyng import exceptions as exc
16
17# Class factory ---------------------------------------------------------------
18def Page(environ):
19 """
20 Create a Page object (of appropriate subclass) based on the request URI.
21
22 Parameters
23 ----------
24 environ : dict
25 The WSGI environment variable is a dictionary object containing CGI-
26 style environment variables. See PEP333 for specification. It also
27 contains the pre-parsed URI and ARGS parameters.
28
29 Returns
30 -------
31 page : PageBase
32 The PageBase (or PageBase-subclass) object associated with the request.
33
34 """
35 pagename = environ['URI'][0]
36 if pagename == '': # we are at the application root
37 return RootPage(environ)
38 elif pagename == 'rules': # we are at the rules static-ish page
39 return RulesPage(environ)
40 elif pagename == 'retired': # we are looking at retired players
41 return RetiredPage(environ)
42 elif pagename == '+game': # we are adding a game
43 return GameAction(environ)
44 elif pagename == '+user': # we are adding a user
45 return UserAction(environ)
46 elif pagename == '+retire': # we are retiring a user
47 return RetireAction(environ)
48 else: # we expect uri[0] to be a {username}
49 return FilterPage(environ)
1550
1651
17# Module class ----------------------------------------------------------------52# Module class ----------------------------------------------------------------
18class Page(object):53class PageBase(object):
19 54
20 """55 """
21 A Page object is resonsible for processing content, applying themes, and56 A PageBase object is resonsible for processing content, applying themes,
22 returning the XHTML to the user via HTTP.57 and returning the XHTML to the user via HTTP. This is a base class that
58 should be subclassed for specific functionality.
23 59
24 """60 """
25 61
26 # Class initializer -------------------------------------------------------62 # Class initializer -------------------------------------------------------
27 def __init__(self,environ):63 def __init__(self,environ):
28 """64 """
29 Initialize the Page instance. This is a lean operation in that the page65 Initialize the PageBase instance. This is a lean operation in that the
30 content is not generated until required.66 page content is not generated until required.
31 67
32 Parameters68 Parameters
33 ----------69 ----------
@@ -44,13 +80,17 @@
44 # Set status and headers (assume OK; if not, these will get changed)80 # Set status and headers (assume OK; if not, these will get changed)
45 self.status = '200 OK'81 self.status = '200 OK'
46 self.headers = [('Content-Type','text/html')]82 self.headers = [('Content-Type','text/html')]
47 self.template = 'PyngPyng/templates/pyng.page'83 self.template = 'PyngPyng/templates/pyng.tpl'
48 # Copy environment parameters84 # Copy environment parameters
49 self.script_name = environ.get('SCRIPT_NAME','')85 self.script_name = environ.get('SCRIPT_NAME','')
50 self.request_method = environ.get('REQUEST_METHOD',None)86 self.request_method = environ.get('REQUEST_METHOD',None)
51 self.args = environ.get('ARGS',None)87 self.args = environ['ARGS'] # If args or uri are not set, something is messed up
52 self.uri = environ.get('URI',None)88 self.uri = environ['URI']
53 # Set initial page attributes89 # Set initial page attributes
90 self.template_parameters = {
91 'uri' : self.uri
92 }
93 self.is_action = False
54 self.is_composited = False94 self.is_composited = False
55 self.content = None95 self.content = None
56 self.page = None96 self.page = None
@@ -70,8 +110,11 @@
70 None110 None
71 111
72 """112 """
73 pass113 if self.request_method == 'POST' and not self.is_action:
74 114 raise exc.HTTPMethodNotAllowedError('POST methods are only allowed for ''action'' resources, indicated by a ''+''.')
115 elif self.request_method != 'GET':
116 raise exc.HTTPMethodNotAllowedError('Only GET and POST methods are allowed at this time; POST methods are only allowed on ''action'' resources, indicated by a ''+''.')
117
75 # Class function ----------------------------------------------------------118 # Class function ----------------------------------------------------------
76 def execute(self):119 def execute(self):
77 """120 """
@@ -106,23 +149,66 @@
106 None149 None
107 150
108 """151 """
109 self.page = '\n'.join([152 pass
110 'Hello, world!',153
111 'How are you today?',154 # Class function ----------------------------------------------------------
112 'I am fine, thank you!'155 def do_it(self):
113 ])156 self.parse_request()
114 template_parameters = {157 self.execute()
115 'title' : 'PyngPyng games ladder',158 self.composite()
116 'page' : self.page,159
117 'uri' : self.uri160
118 }161# Module class ----------------------------------------------------------------
162class ActionBase(PageBase):
163 def __init__(self,environ):
164 PageBase.__init__(self,environ)
165 self.is_action = self.request_method == 'POST'
166
167
168# Module class ----------------------------------------------------------------
169class RootPage(PageBase):
170 pass
171
172
173# Module class ----------------------------------------------------------------
174class RulesPage(PageBase):
175 def composite(self):
176 self.template_parameters['title'] = 'PyngPyng games ladder'
177 with open('PyngPyng/templates/rules.page','r') as rules:
178 self.page = rules.read()
119 with open(self.template,'r') as template:179 with open(self.template,'r') as template:
120 self.content = template.read() % template_parameters180 self.template_parameters['page'] = self.page
181 self.content = template.read() % self.template_parameters
121 self.is_composited = True182 self.is_composited = True
122183
123184
124# Module class ----------------------------------------------------------------185# Module class ----------------------------------------------------------------
125class ErrorPage(Page):186class RetiredPage(PageBase):
187 pass
188
189
190# Module class ----------------------------------------------------------------
191class GameAction(ActionBase):
192 pass
193
194
195# Module class ----------------------------------------------------------------
196class UserAction(ActionBase):
197 pass
198
199
200# Module class ----------------------------------------------------------------
201class RetireAction(ActionBase):
202 pass
203
204
205# Module class ----------------------------------------------------------------
206class FilterPage(PageBase):
207 pass
208
209
210# Module class ----------------------------------------------------------------
211class ErrorPage(PageBase):
126 212
127 """213 """
128 An ErrorPage object is responsible for reporting application errors to the214 An ErrorPage object is responsible for reporting application errors to the
@@ -133,14 +219,26 @@
133 # Class function ----------------------------------------------------------219 # Class function ----------------------------------------------------------
134 def __init__(self,environ,exc_info):220 def __init__(self,environ,exc_info):
135 """221 """
136 Initialize the ErrorPage instance.222 Initialize the ErrorPage instance. This is generates the output
223 immediately.
224
225 Parameters
226 ----------
227 environ : dict
228 The WSGI environment variable is a dictionary object containing CGI-
229 style environment variables. See PEP333 for specification. It also
230 contains the pre-parsed URI and ARGS parameters.
231
232 Returns
233 -------
234 None
137 235
138 """236 """
139 import traceback237 import traceback
140 Page.__init__(self,environ)238 PageBase.__init__(self,environ)
141 # Copy exception information239 # Copy exception information
142 self.etype, self.evalue, self.etrace = exc_info240 self.etype, self.evalue, self.etrace = exc_info
143 self.template = 'PyngPyng/templates/error.page'241 self.template = 'PyngPyng/templates/error.tpl'
144 # Set default error status and headers (can be changed later to242 # Set default error status and headers (can be changed later to
145 # customize for particular error conditions)243 # customize for particular error conditions)
146 try:244 try:
147245
=== removed file 'PyngPyng/templates/error.page'
--- PyngPyng/templates/error.page 2009-05-24 19:57:14 +0000
+++ PyngPyng/templates/error.page 1970-01-01 00:00:00 +0000
@@ -1,34 +0,0 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
3<html xmlns="http://www.w3.org/1999/xhtml">
4<head profile="http://gmpg.org/xfn/11">
5 <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
6 <meta name="robots" content="none" />
7 <title>%(title)s</title>
8 <style type="text/css">
9 body { font-family:Verdana; font-size:10pt; }
10 h1 { font-weight:normal; font-size:18pt; color:red; }
11 h2 { font-weight:normal; font-style:italic; font-size:14pt; color:maroon; }
12 div#trace { background-color:#FFFFCC; margin-top:-0.75em; }
13 div#version { color:gray; }
14 </style>
15</head>
16
17<body>
18 <h1>Server Error at '%(request_uri)s' in %(app_name)s.</h1>
19 <hr width="100%%" size=1 color="silver" />
20 <h2>%(exc_type)s &raquo; %(exc_details)s</h2>
21
22 <b>Description:</b>&nbsp;%(exc_description)s<br/><br/>
23 <b>Exception Details:</b>&nbsp;%(exc_type)s: %(exc_details)s<br/><br/>
24
25 <b>Stack Trace:</b>
26 <div id="trace">
27 <code><pre>%(exc_trace)s</code></pre>
28 </div>
29 <hr width="100%%" size=1 color="silver" />
30 <div id="version">
31 <b>Version Information:</b>&nbsp;%(version)s
32 </div>
33</body>
34</html>
350
=== added file 'PyngPyng/templates/error.tpl'
--- PyngPyng/templates/error.tpl 1970-01-01 00:00:00 +0000
+++ PyngPyng/templates/error.tpl 2009-05-25 18:49:00 +0000
@@ -0,0 +1,34 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
3<html xmlns="http://www.w3.org/1999/xhtml">
4<head profile="http://gmpg.org/xfn/11">
5 <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
6 <meta name="robots" content="none" />
7 <title>%(title)s</title>
8 <style type="text/css">
9 body { font-family:Verdana; font-size:10pt; }
10 h1 { font-weight:normal; font-size:18pt; color:red; }
11 h2 { font-weight:normal; font-style:italic; font-size:14pt; color:maroon; }
12 div#trace { background-color:#FFFFCC; margin-top:-0.75em; }
13 div#version { color:gray; }
14 </style>
15</head>
16
17<body>
18 <h1>Server Error at '%(request_uri)s' in %(app_name)s.</h1>
19 <hr width="100%%" size=1 color="silver" />
20 <h2>%(exc_type)s &raquo; %(exc_details)s</h2>
21
22 <b>Description:</b>&nbsp;%(exc_description)s<br/><br/>
23 <b>Exception Details:</b>&nbsp;%(exc_type)s: %(exc_details)s<br/><br/>
24
25 <b>Stack Trace:</b>
26 <div id="trace">
27 <code><pre>%(exc_trace)s</code></pre>
28 </div>
29 <hr width="100%%" size=1 color="silver" />
30 <div id="version">
31 <b>Version Information:</b>&nbsp;%(version)s
32 </div>
33</body>
34</html>
035
=== removed file 'PyngPyng/templates/pyng.page'
--- PyngPyng/templates/pyng.page 2009-05-25 03:11:31 +0000
+++ PyngPyng/templates/pyng.page 1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
3<html xmlns="http://www.w3.org/1999/xhtml">
4<head profile="http://gmpg.org/xfn/11">
5 <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
6 <meta name="distribution" content="global" />
7 <meta name="robots" content="index,follow" />
8 <meta name="language" content="en, sv" />
9 <title>%(title)s</title>
10 <!--<link rel="stylesheet" type="text/css" charset="utf-8" media="all" href="http://localhost:8080/static/default.css" />-->
11</head>
12
13<body>
14 <div id="header">
15 %(uri)s
16 </div>
17 <div id="page">
18 %(page)s
19 </div>
20 <div id="footer">
21 <div id="xhtml">Valid <a href="http://validator.w3.org/check/referer">XHTML</a> and <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a></div>
22 </div>
23</body>
24</html>
250
=== added file 'PyngPyng/templates/pyng.tpl'
--- PyngPyng/templates/pyng.tpl 1970-01-01 00:00:00 +0000
+++ PyngPyng/templates/pyng.tpl 2009-05-25 18:49:00 +0000
@@ -0,0 +1,24 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2
3<html xmlns="http://www.w3.org/1999/xhtml">
4<head profile="http://gmpg.org/xfn/11">
5 <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
6 <meta name="distribution" content="global" />
7 <meta name="robots" content="index,follow" />
8 <meta name="language" content="en, sv" />
9 <title>%(title)s</title>
10 <!--<link rel="stylesheet" type="text/css" charset="utf-8" media="all" href="http://localhost:8080/static/default.css" />-->
11</head>
12
13<body>
14 <div id="header">
15 %(uri)s
16 </div>
17 <div id="page">
18 %(page)s
19 </div>
20 <div id="footer">
21 <div id="xhtml">Valid <a href="http://validator.w3.org/check/referer">XHTML</a> and <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a></div>
22 </div>
23</body>
24</html>
025
=== added file 'PyngPyng/templates/rules.page'
--- PyngPyng/templates/rules.page 1970-01-01 00:00:00 +0000
+++ PyngPyng/templates/rules.page 2009-05-25 18:49:00 +0000
@@ -0,0 +1,13 @@
1<ol id="rules">
2 <li>All matches are to be best of three games.</li>
3 <li>All games are to be played to 21 points.</li>
4 <li>A game weighting is to be decided on before the game. It must be an integer from 1 to 10 (inclusive).</li>
5 <li>The higher the weight of the game the more points the winners can win (and the losers can lose).</li>
6 <li>If no game weight is chosen, the default game weight is 4.</li>
7 <li>Both singles and doubles games count towards the SFL Ping Pong ladder.</li>
8 <li>We salute those SFL Ping Pongers that have come before us.</li>
9 <li>By default assume that Grant is cheating and take appropriate action.</li>
10 <li>Let Mark win sometimes, his score is pathetic.</li>
11 <li>Honour Chris for creating this magical software.</li>
12 <li>If Guy is going to smash, for safety's sake get as close to the table as possible, because the ball is not going anywhere near it.</li>
13</ol>
014
=== modified file 'PyngPyng/version.py' (properties changed: -x to +x)
--- PyngPyng/version.py 2009-05-24 23:57:05 +0000
+++ PyngPyng/version.py 2009-05-25 12:12:54 +0000
@@ -10,7 +10,7 @@
10# Version information ---------------------------------------------------------10# Version information ---------------------------------------------------------
11project = 'PyngPyng'11project = 'PyngPyng'
12release = '0'12release = '0'
13revision = 'lp:pyng (trunk)'13revision = 'lp:~scott-armitage/pyng/uri-pattern'
14agent = ' '.join((project,release,revision))14agent = ' '.join((project,release,revision))
1515
16# Script body -----------------------------------------------------------------16# Script body -----------------------------------------------------------------

Subscribers

People subscribed via source and target branches

to all changes: