Merge lp:~thumper/wikkid/script-name into lp:wikkid

Proposed by Tim Penhey on 2012-05-17
Status: Merged
Approved by: Tim Penhey on 2012-05-17
Approved revision: 85
Merged at revision: 70
Proposed branch: lp:~thumper/wikkid/script-name
Merge into: lp:wikkid
Diff against target: 622 lines (+193/-80)
15 files modified
bin/wikkid-serve (+5/-1)
setup.py (+2/-1)
wikkid/app.py (+35/-19)
wikkid/context.py (+13/-4)
wikkid/skin/default/base.html (+4/-4)
wikkid/tests/factory.py (+2/-2)
wikkid/tests/test_app.py (+40/-12)
wikkid/tests/views/test_breadcrumbs.py (+13/-0)
wikkid/tests/views/test_root.py (+33/-2)
wikkid/tests/views/test_urls.py (+22/-17)
wikkid/view/base.py (+13/-9)
wikkid/view/directory.py (+5/-5)
wikkid/view/edit.py (+1/-1)
wikkid/view/root.py (+2/-0)
wikkid/view/urls.py (+3/-3)
To merge this branch: bzr merge lp:~thumper/wikkid/script-name
Reviewer Review Type Date Requested Status
Tim Penhey Approve on 2012-05-17
Review via email: mp+106141@code.launchpad.net

Description of the change

Allow wikkid-serve to specify a script-name. This is the assumed to be the start of any request for a wikkid served page. If not, a 404 is returned.

Styling and links are updated to use the script-name.

To post a comment you must log in.
Tim Penhey (thumper) wrote :

I approve :-)

review: Approve
lp:~thumper/wikkid/script-name updated on 2012-05-17
86. By Tim Penhey on 2012-05-17

Have the views use their own canonical_url function that uses the request object.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/wikkid-serve'
2--- bin/wikkid-serve 2011-03-09 21:34:46 +0000
3+++ bin/wikkid-serve 2012-05-17 11:13:18 +0000
4@@ -58,12 +58,16 @@
5 '--default-format', type='string', default=DEFAULT_FORMAT,
6 help=("Specify the default wiki format to use. Defaults to %r"
7 % DEFAULT_FORMAT))
8+ parser.add_option(
9+ '--script-name',
10+ help=('The SCRIPT_NAME for the environment. This is the prefix for the URLs'))
11 options, args = parser.parse_args(sys.argv[1:])
12
13 execution_context = ExecutionContext(
14 host=options.host,
15 port=options.port,
16- default_format=options.default_format)
17+ default_format=options.default_format,
18+ script_name=options.script_name)
19
20 if len(args) == 0:
21 print "No branch location specified.\n"
22
23=== modified file 'setup.py'
24--- setup.py 2011-06-29 09:21:55 +0000
25+++ setup.py 2012-05-17 11:13:18 +0000
26@@ -31,7 +31,8 @@
27 'zope.interface',
28 ],
29 test_requires=[
30- 'beautifulsoup',
31+ 'bs4',
32+ 'bzrlib.tests',
33 'testtools',
34 ],
35 test_suite='wikkid.tests',
36
37=== modified file 'wikkid/app.py'
38--- wikkid/app.py 2010-11-22 00:00:31 +0000
39+++ wikkid/app.py 2012-05-17 11:13:18 +0000
40@@ -11,6 +11,7 @@
41 import mimetypes
42 import os.path
43 import urllib
44+from wsgiref.util import shift_path_info
45
46 from bzrlib import urlutils
47 from webob import Request, Response
48@@ -59,35 +60,50 @@
49 self.skin = Skin(skin_name)
50 self.logger = logging.getLogger('wikkid')
51
52- def __call__(self, environ, start_response):
53- """The WSGI bit."""
54+ def process_call(self, environ):
55+ """The actual implementation of dealing with the call."""
56+ # TODO: reject requests that aren't GET or POST
57 request = Request(environ)
58-
59- # TODO: reject requests that aren't GET or POST
60 path = urllib.unquote(request.path)
61+ script_name = self.execution_context.script_name
62+ if not path.startswith(script_name + '/'):
63+ return HTTPNotFound()
64+
65+ shifted_prefix = ''
66+ while shifted_prefix != script_name:
67+ shifted = shift_path_info(environ)
68+ shifted_prefix = '{0}/{1}'.format(shifted_prefix, shifted)
69+ # Now we are just interested in the path_info having ignored the
70+ # script name.
71+ path = urllib.unquote(request.path_info)
72+
73 if path == '/favicon.ico':
74 if self.skin.favicon is not None:
75- response = serve_file(self.skin.favicon)
76+ return serve_file(self.skin.favicon)
77 else:
78- response = HTTPNotFound()
79- elif path.startswith('/static/'):
80+ return HTTPNotFound()
81+
82+ if path.startswith('/static/'):
83 if self.skin.static_dir is not None:
84 static_dir = self.skin.static_dir.rstrip(os.sep) + os.sep
85 static_file = os.path.abspath(
86 urlutils.joinpath(static_dir, path[8:]))
87 if static_file.startswith(static_dir):
88- response = serve_file(static_file)
89+ return serve_file(static_file)
90 else:
91- response = HTTPNotFound()
92+ return HTTPNotFound()
93 else:
94- response = HTTPNotFound()
95- else:
96- resource_path, action = parse_url(path)
97- model = self.resource_factory.get_resource_at_path(resource_path)
98- try:
99- view = get_view(model, action, request, self.execution_context)
100- response = view.render(self.skin)
101- except HTTPException, e:
102- response = e
103-
104+ return HTTPNotFound()
105+
106+ resource_path, action = parse_url(path)
107+ model = self.resource_factory.get_resource_at_path(resource_path)
108+ try:
109+ view = get_view(model, action, request, self.execution_context)
110+ return view.render(self.skin)
111+ except HTTPException, e:
112+ return e
113+
114+ def __call__(self, environ, start_response):
115+ """The WSGI bit."""
116+ response = self.process_call(environ)
117 return response(environ, start_response)
118
119=== modified file 'wikkid/context.py'
120--- wikkid/context.py 2010-11-22 00:00:31 +0000
121+++ wikkid/context.py 2012-05-17 11:13:18 +0000
122@@ -1,6 +1,6 @@
123 # -*- coding: utf-8 -*-
124 #
125-# Copyright (C) 2010 Wikkid Developers.
126+# Copyright (C) 2010-2012 Wikkid Developers.
127 #
128 # This software is licensed under the GNU Affero General Public License
129 # version 3 (see the file LICENSE).
130@@ -13,9 +13,13 @@
131
132
133 class ExecutionContext(object):
134- """Store run-time execution context data."""
135-
136- def __init__(self, host=None, port=None, default_format=None):
137+ """Store run-time execution context data.
138+
139+ This is the Encapsulate Context pattern.
140+ """
141+
142+ def __init__(self, host=None, port=None, default_format=None,
143+ script_name=None):
144 """Create an execution context for the application.
145
146 :param host: The hostname that content is being served from.
147@@ -32,3 +36,8 @@
148 self.host = host
149 self.port = port
150 self.default_format = default_format
151+ # TODO: make sure the script_name if set starts with a slash and
152+ # doesn't finish with one.
153+ if script_name is None:
154+ script_name = ''
155+ self.script_name = script_name
156
157=== modified file 'wikkid/skin/default/base.html'
158--- wikkid/skin/default/base.html 2010-07-13 12:49:52 +0000
159+++ wikkid/skin/default/base.html 2012-05-17 11:13:18 +0000
160@@ -5,14 +5,14 @@
161 <title>{% block title %}{% endblock %} - Wikkid</title>
162
163 <link type="text/css" rel="stylesheet" media="screen, print"
164- href="/static/default.css" />
165- <link rel="shortcut icon" href="/favicon.ico" />
166+ href="{{ request.script_name }}/static/default.css" />
167+ <link rel="shortcut icon" href="{{ request.script_name }}/favicon.ico" />
168 {% endblock %}
169 </head>
170 <body>
171 <div id="container">
172 <div id="header">
173- <div class="wikkidlogo"><a href="/"><strong>Wikkid Wiki</strong></a></div>
174+ <div class="wikkidlogo"><a href="{{ request.script_name }}/"><strong>Wikkid Wiki</strong></a></div>
175 <div id="logged">
176 {% if view.user %}
177
178@@ -44,7 +44,7 @@
179 </div>
180 {% block footer %}{% endblock %}
181 <div id="footer">
182- &copy; 2010
183+ &copy; 2010-2012
184 <a href="https://launchpad.net/~wikkid">Wikkid Hackers</a>,
185 All rights reserved.
186 </div>
187
188=== modified file 'wikkid/tests/factory.py'
189--- wikkid/tests/factory.py 2010-06-15 09:05:29 +0000
190+++ wikkid/tests/factory.py 2012-05-17 11:13:18 +0000
191@@ -26,7 +26,7 @@
192 class ViewTestCase(FactoryTestCase):
193 """A factory test case that can create views."""
194
195- def get_view(self, factory, path, name=None):
196+ def get_view(self, factory, path, name=None, base_url=None):
197 info = factory.get_resource_at_path(path)
198- request = Request.blank(path)
199+ request = Request.blank(path, base_url=base_url)
200 return get_view(info, name, request)
201
202=== modified file 'wikkid/tests/test_app.py'
203--- wikkid/tests/test_app.py 2011-04-23 08:18:58 +0000
204+++ wikkid/tests/test_app.py 2012-05-17 11:13:18 +0000
205@@ -11,25 +11,28 @@
206 from webob.request import environ_from_url
207
208 from wikkid.app import WikkidApp
209+from wikkid.context import ExecutionContext
210 from wikkid.filestore.volatile import FileStore
211 from wikkid.tests import TestCase
212
213
214 class TestApp(TestCase):
215
216+ def assert_not_found(self, status, headers):
217+ self.assertEqual("404 Not Found", status)
218+
219+ def assert_ok(self, status, headers):
220+ self.assertEqual("200 OK", status)
221+
222 def test_traverse_above_static_not_possible_with_relative_path(self):
223 """
224 Traversal above the static folder, by forging a malicious request with
225 a relative path for example, is not possible.
226 """
227 environ = environ_from_url("/static/../page.html")
228-
229- def start_response(status, headers):
230- self.assertEqual("404 Not Found", status)
231-
232 filestore = FileStore()
233 app = WikkidApp(filestore)
234- app(environ, start_response)
235+ app(environ, self.assert_not_found)
236
237 def test_traverse_above_static_not_possible_with_absolute_path(self):
238 """
239@@ -38,10 +41,35 @@
240 """
241 this_file = os.path.abspath(__file__)
242 environ = environ_from_url("/static/" + this_file)
243-
244- def start_response(status, headers):
245- self.assertEqual("404 Not Found", status)
246-
247- filestore = FileStore()
248- app = WikkidApp(filestore)
249- app(environ, start_response)
250+ filestore = FileStore()
251+ app = WikkidApp(filestore)
252+ app(environ, self.assert_not_found)
253+
254+ def test_getting_static_style_css_works(self):
255+
256+ environ = environ_from_url("/static/default.css")
257+ filestore = FileStore()
258+ app = WikkidApp(filestore)
259+ app(environ, self.assert_ok)
260+
261+ def test_getting_static_style_css_works_with_script_name(self):
262+
263+ environ = environ_from_url("/test/static/default.css")
264+ filestore = FileStore()
265+ context = ExecutionContext(script_name="/test")
266+ app = WikkidApp(filestore, execution_context=context)
267+ app(environ, self.assert_ok)
268+
269+ def test_getting_static_style_css_works_with_script_name_multiple_segments(self):
270+ environ = environ_from_url("/p/project-name/wiki/static/default.css")
271+ filestore = FileStore()
272+ context = ExecutionContext(script_name="/p/project-name/wiki")
273+ app = WikkidApp(filestore, execution_context=context)
274+ app(environ, self.assert_ok)
275+
276+ def test_getting_anything_outside_script_name_fails(self):
277+ environ = environ_from_url("/foo/bar")
278+ filestore = FileStore()
279+ context = ExecutionContext(script_name="/test")
280+ app = WikkidApp(filestore, execution_context=context)
281+ app(environ, self.assert_not_found)
282
283=== modified file 'wikkid/tests/views/test_breadcrumbs.py'
284--- wikkid/tests/views/test_breadcrumbs.py 2010-06-15 09:05:29 +0000
285+++ wikkid/tests/views/test_breadcrumbs.py 2012-05-17 11:13:18 +0000
286@@ -107,3 +107,16 @@
287 ('wiki root', '/+listing'),
288 ('SomePage', '/SomePage/+listing'),
289 ('SubPage', '/SomePage/SubPage')])
290+
291+ def test_directory_breadcrumbs_nested_with_script_name(self):
292+ # For each directory after the root, a listing crumb is added.
293+ # Names are not wiki expanded.
294+ factory = self.make_factory([
295+ ('SomePage/SubPage/Nested.txt', 'some text')])
296+ view = self.get_view(factory, '/SomePage/SubPage', 'listing', '/p/wiki')
297+ self.assertBreadcrumbs(
298+ view,
299+ [('Home', '/p/wiki/Home'),
300+ ('wiki root', '/p/wiki/+listing'),
301+ ('SomePage', '/p/wiki/SomePage/+listing'),
302+ ('SubPage', '/p/wiki/SomePage/SubPage')])
303
304=== modified file 'wikkid/tests/views/test_root.py'
305--- wikkid/tests/views/test_root.py 2010-06-17 10:45:52 +0000
306+++ wikkid/tests/views/test_root.py 2012-05-17 11:13:18 +0000
307@@ -6,16 +6,19 @@
308
309 """Test views for the root object."""
310
311+from bs4 import BeautifulSoup
312+from testtools.matchers import Equals
313 from webob.exc import HTTPSeeOther
314
315+from wikkid.skin.loader import Skin
316 from wikkid.tests.factory import ViewTestCase
317
318
319 class TestRootViews(ViewTestCase):
320 """Test the views on the root object."""
321
322- def test_last_modified_by(self):
323- """Test that the last committer is displayed properly"""
324+ def test_root_redirects(self):
325+ """Going to / redirects to the Home page."""
326 factory = self.make_factory()
327 view = self.get_view(factory, '/')
328 error = self.assertRaises(
329@@ -23,3 +26,31 @@
330 view.render,
331 None)
332 self.assertEqual('/Home', error.headers['Location'])
333+
334+ def test_root_redirects_with_script_name(self):
335+ """Redirection works and respects the script name"""
336+ factory = self.make_factory()
337+ view = self.get_view(factory, '/', base_url='/p/test')
338+ error = self.assertRaises(
339+ HTTPSeeOther,
340+ view.render,
341+ None)
342+ self.assertEqual('/p/test/Home', error.headers['Location'])
343+
344+ def test_home_rendering(self):
345+ """Render the home page and test the elements."""
346+ factory = self.make_factory()
347+ view = self.get_view(factory, '/Home')
348+ content = view.render(Skin('default'))
349+ soup = BeautifulSoup(content.text)
350+ [style] = soup.find_all('link', {'rel':'stylesheet'})
351+ self.assertThat(style['href'], Equals('/static/default.css'))
352+
353+ def test_home_rendering_with_script_name(self):
354+ """Render the home page and test the elements."""
355+ factory = self.make_factory()
356+ view = self.get_view(factory, '/Home', base_url='/p/test')
357+ content = view.render(Skin('default'))
358+ soup = BeautifulSoup(content.text)
359+ [style] = soup.find_all('link', {'rel':'stylesheet'})
360+ self.assertThat(style['href'], Equals('/p/test/static/default.css'))
361
362=== modified file 'wikkid/tests/views/test_urls.py'
363--- wikkid/tests/views/test_urls.py 2010-06-16 10:29:35 +0000
364+++ wikkid/tests/views/test_urls.py 2012-05-17 11:13:18 +0000
365@@ -6,6 +6,9 @@
366
367 """Tests the edit views."""
368
369+from testtools.matchers import Equals
370+from webob import Request
371+
372 from wikkid.tests import TestCase
373 from wikkid.tests.factory import FactoryTestCase
374 from wikkid.view.urls import canonical_url, parse_url
375@@ -14,84 +17,86 @@
376 class TestCanonicalUrl(FactoryTestCase):
377 """Test the wikkid.view.base.canonical_url."""
378
379+ def assertUrl(self, resource, url, view_name=None, base_url=None):
380+ request = Request.blank('/', base_url=base_url)
381+ self.assertThat(canonical_url(resource, request, view_name),
382+ Equals(url))
383+
384 def test_root(self):
385 factory = self.make_factory()
386 root = factory.get_resource_at_path('/')
387- self.assertEqual('/', canonical_url(root))
388+ self.assertUrl(root, '/')
389
390 def test_root_listing(self):
391 factory = self.make_factory()
392 root = factory.get_resource_at_path('/')
393- self.assertEqual('/+listing', canonical_url(root, 'listing'))
394+ self.assertUrl(root, '/+listing', view_name='listing')
395
396 def test_default(self):
397 factory = self.make_factory([
398 ('Home.txt', 'Some content'),
399 ])
400 root = factory.get_resource_at_path('/')
401- self.assertEqual('/Home', canonical_url(root.default_resource))
402+ self.assertUrl(root.default_resource, '/Home')
403
404 def test_default_view(self):
405 factory = self.make_factory([
406 ('Home.txt', 'Some content'),
407 ])
408 root = factory.get_resource_at_path('/')
409- self.assertEqual(
410- '/Home/+edit',
411- canonical_url(root.default_resource, 'edit'))
412+ self.assertUrl(root.default_resource, '/Home/+edit', view_name='edit')
413
414 def test_wiki_page(self):
415 factory = self.make_factory([
416 ('SomeDir/SomePage.txt', 'Some content'),
417 ])
418 page = factory.get_resource_at_path('/SomeDir/SomePage')
419- self.assertEqual('/SomeDir/SomePage', canonical_url(page))
420+ self.assertUrl(page, '/SomeDir/SomePage')
421
422 def test_wiki_page_view(self):
423 factory = self.make_factory([
424 ('SomeDir/SomePage.txt', 'Some content'),
425 ])
426 page = factory.get_resource_at_path('/SomeDir/SomePage')
427- self.assertEqual(
428- '/SomeDir/SomePage/+edit', canonical_url(page, 'edit'))
429+ self.assertUrl(page, '/SomeDir/SomePage/+edit', view_name='edit')
430
431 def test_wiki_page_full_url(self):
432 factory = self.make_factory([
433 ('SomeDir.txt', 'Some content'),
434 ])
435 page = factory.get_resource_at_path('/SomeDir.txt')
436- self.assertEqual('/SomeDir', canonical_url(page))
437+ self.assertUrl(page, '/SomeDir')
438
439 def test_wiki_page_full_url_with_view(self):
440 factory = self.make_factory([
441 ('SomeDir.txt', 'Some content'),
442 ])
443 page = factory.get_resource_at_path('/SomeDir.txt')
444- self.assertEqual('/SomeDir/+edit', canonical_url(page, 'edit'))
445+ self.assertUrl(page, '/SomeDir/+edit', view_name='edit')
446
447 def test_other_file(self):
448 factory = self.make_factory([
449 ('simple.py', '#!/usr/bin/python'),
450 ])
451 page = factory.get_resource_at_path('/simple.py')
452- self.assertEqual('/simple.py', canonical_url(page))
453+ self.assertUrl(page, '/simple.py')
454
455 def test_other_file_view(self):
456 factory = self.make_factory([
457 ('simple.py', '#!/usr/bin/python'),
458 ])
459 page = factory.get_resource_at_path('/simple.py')
460- self.assertEqual('/simple.py/+edit', canonical_url(page, 'edit'))
461+ self.assertUrl(page, '/simple.py/+edit', view_name='edit')
462
463 def test_missing(self):
464 factory = self.make_factory()
465- root = factory.get_resource_at_path('/MissingPage')
466- self.assertEqual('/MissingPage', canonical_url(root))
467+ missing = factory.get_resource_at_path('/MissingPage')
468+ self.assertUrl(missing, '/MissingPage')
469
470 def test_missing_view(self):
471 factory = self.make_factory()
472- root = factory.get_resource_at_path('/MissingPage')
473- self.assertEqual('/MissingPage/+edit', canonical_url(root, 'edit'))
474+ missing = factory.get_resource_at_path('/MissingPage')
475+ self.assertUrl(missing, '/MissingPage/+edit', view_name='edit')
476
477
478 class TestParseUrl(TestCase):
479
480=== modified file 'wikkid/view/base.py'
481--- wikkid/view/base.py 2010-11-22 09:23:40 +0000
482+++ wikkid/view/base.py 2012-05-17 11:13:18 +0000
483@@ -29,8 +29,8 @@
484 class Breadcrumb(object):
485 """Breadcrumbs exist to give the user quick links up the path chain."""
486
487- def __init__(self, context, view=None, title=None):
488- self.path = canonical_url(context, view)
489+ def __init__(self, context, request, view=None, title=None):
490+ self.path = canonical_url(context, request, view)
491 if title is None:
492 self.title = title_for_filename(context.base_name)
493 else:
494@@ -54,14 +54,14 @@
495 self.logger = logging.getLogger('wikkid')
496
497 def _create_breadcrumbs(self):
498- crumbs = [Breadcrumb(self.context)]
499+ crumbs = [Breadcrumb(self.context, self.request)]
500 current = self.context.parent
501 while not IRootResource.providedBy(current):
502- crumbs.append(Breadcrumb(current))
503+ crumbs.append(Breadcrumb(current, self.request))
504 current = current.parent
505 # And add in the default page if the context isn't the default.
506 if not IDefaultPage.providedBy(self.context):
507- crumbs.append(Breadcrumb(current.default_resource))
508+ crumbs.append(Breadcrumb(current.default_resource, self.request))
509 return reversed(crumbs)
510
511 def initialize(self):
512@@ -89,6 +89,9 @@
513 def before_render(self):
514 """A hook to do things before rendering."""
515
516+ def canonical_url(self, context, view=None):
517+ return canonical_url(context, self.request, view)
518+
519 def template_args(self):
520 """Needs to be implemented in the derived classes.
521
522@@ -99,7 +102,7 @@
523 'user': self.user,
524 'context': self.context,
525 'request': self.request,
526- 'canonical_url': canonical_url,
527+ 'canonical_url': self.canonical_url,
528 }
529
530 def _render(self, skin):
531@@ -139,12 +142,13 @@
532 view = None
533 while not IRootResource.providedBy(current):
534 crumbs.append(Breadcrumb(
535- current, view, title=current.base_name))
536+ current, self.request, view, title=current.base_name))
537 current = current.parent
538 # Add listings to subsequent urls.
539 view = 'listing'
540 # Add in the root dir.
541- crumbs.append(Breadcrumb(current, 'listing', title='wiki root'))
542+ crumbs.append(Breadcrumb(current, self.request, 'listing',
543+ title='wiki root'))
544 # And add in the default page.
545- crumbs.append(Breadcrumb(current.default_resource))
546+ crumbs.append(Breadcrumb(current.default_resource, self.request))
547 return reversed(crumbs)
548
549=== modified file 'wikkid/view/directory.py'
550--- wikkid/view/directory.py 2010-06-23 10:57:14 +0000
551+++ wikkid/view/directory.py 2012-05-17 11:13:18 +0000
552@@ -14,9 +14,9 @@
553 class ListingItem(object):
554 """An item to be shown in the directory listing."""
555
556- def __init__(self, context, view, css_class, name=None):
557+ def __init__(self, context, request, view, css_class, name=None):
558 self.context = context
559- self.url = canonical_url(self.context, view)
560+ self.url = canonical_url(self.context, request, view)
561 if name is None:
562 name = context.base_name
563 self.name = name
564@@ -53,11 +53,11 @@
565 if self.context.path != '/':
566 parent = self.context.parent
567 items.append(
568- ListingItem(parent, 'listing', 'up', name='..'))
569+ ListingItem(parent, self.request, 'listing', 'up', name='..'))
570 for item in sorted(directories, key=sort_key):
571- items.append(ListingItem(item, 'listing', 'directory'))
572+ items.append(ListingItem(item, self.request, 'listing', 'directory'))
573 for item in sorted(files, key=sort_key):
574- items.append(ListingItem(item, None, 'file'))
575+ items.append(ListingItem(item, self.request, None, 'file'))
576 self.items = items
577
578 @property
579
580=== modified file 'wikkid/view/edit.py'
581--- wikkid/view/edit.py 2010-06-17 10:45:52 +0000
582+++ wikkid/view/edit.py 2012-05-17 11:13:18 +0000
583@@ -24,7 +24,7 @@
584 @property
585 def save_url(self):
586 """The link for the cancel button."""
587- return canonical_url(self.context, 'save')
588+ return canonical_url(self.context, self.request, 'save')
589
590 @property
591 def cancel_url(self):
592
593=== modified file 'wikkid/view/root.py'
594--- wikkid/view/root.py 2010-06-17 10:45:52 +0000
595+++ wikkid/view/root.py 2012-05-17 11:13:18 +0000
596@@ -23,4 +23,6 @@
597 """Redirect to Home (or the default page)."""
598 default_resource = self.context.default_resource
599 preferred = default_resource.preferred_path
600+ if self.request.script_name:
601+ preferred = self.request.script_name + preferred
602 raise HTTPSeeOther(location=preferred)
603
604=== modified file 'wikkid/view/urls.py'
605--- wikkid/view/urls.py 2010-06-16 10:29:35 +0000
606+++ wikkid/view/urls.py 2012-05-17 11:13:18 +0000
607@@ -24,12 +24,12 @@
608 return (path, None)
609
610
611-def canonical_url(context, view=None):
612+def canonical_url(context, request, view=None):
613 """The one true URL for the context object."""
614 path = context.preferred_path
615 if view is None:
616- return path
617+ return '{0}{1}'.format(request.script_name, path)
618 else:
619 if path == '/':
620 path = ''
621- return '{0}/+{1}'.format(path, view)
622+ return '{0}{1}/+{2}'.format(request.script_name, path, view)

Subscribers

People subscribed via source and target branches