Skip to content
Browse files

Upgrade to Pylons 0.9.7.

  • Loading branch information...
1 parent 8f03eda commit 7a81779ad7d87edb87619dde66a3aa8da0f00e20 @spladug spladug committed Jan 11, 2013
View
5 r2/r2/config/environment.py
@@ -52,6 +52,11 @@ def load_environment(global_conf={}, app_conf={}, setup_globals=True):
config.init_app(global_conf, app_conf, package='r2',
template_engine='mako', paths=paths)
+ # don't put action arguments onto c automatically
+ config['pylons.c_attach_args'] = False
+ # when accessing non-existent attributes on c, return "" instead of dying
+ config['pylons.strict_c'] = False
+
g = config['pylons.g'] = Globals(global_conf, app_conf, paths)
if setup_globals:
g.setup()
View
35 r2/r2/config/middleware.py
@@ -32,26 +32,27 @@
from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool
from pylons import config, response
-from pylons.error import error_template
-from pylons.middleware import ErrorDocuments, ErrorHandler, StaticJavascripts
-from pylons.wsgiapp import PylonsApp, PylonsBaseWSGIApp
+from pylons.middleware import ErrorDocuments, ErrorHandler
+from pylons.wsgiapp import PylonsApp
+from routes.middleware import RoutesMiddleware
from r2.config.environment import load_environment
from r2.config.rewrites import rewrites
from r2.config.extensions import extension_mapping, set_extension
from r2.lib.utils import is_subdomain
-# hack in Paste support for HTTP 429 "Too Many Requests"
-from paste import httpexceptions, wsgiwrappers
+# patch in WebOb support for HTTP 429 "Too Many Requests"
+import webob.exc
+import webob.util
-class HTTPTooManyRequests(httpexceptions.HTTPClientError):
+class HTTPTooManyRequests(webob.exc.HTTPClientError):
code = 429
title = 'Too Many Requests'
explanation = ('The server has received too many requests from the client.')
-httpexceptions._exceptions[429] = HTTPTooManyRequests
-wsgiwrappers.STATUS_CODE_TEXT[429] = HTTPTooManyRequests.title
+webob.exc.status_map[429] = HTTPTooManyRequests
+webob.util.status_reasons[429] = HTTPTooManyRequests.title
#from pylons.middleware import error_mapper
def error_mapper(code, message, environ, global_conf=None, **kw):
@@ -288,7 +289,7 @@ def __call__(self, environ, start_response):
if environ['HTTP_HOST'] == self.domain:
environ['PATH_INFO'] = self.static_path.rstrip('/') + environ['PATH_INFO']
return self.app(environ, start_response)
- raise httpexceptions.HTTPNotFound()
+ raise webob.exc.HTTPNotFound()
class LimitUploadSize(object):
"""
@@ -301,7 +302,8 @@ def __init__(self, app, max_size=1024*500):
def __call__(self, environ, start_response):
cl_key = 'CONTENT_LENGTH'
- if environ['REQUEST_METHOD'] == 'POST':
+ is_error = environ.get("pylons.error_call", False)
+ if not is_error and environ['REQUEST_METHOD'] == 'POST':
if cl_key not in environ:
start_response("411 Length Required", [])
return ['<html><body>length required</body></html>']
@@ -354,8 +356,8 @@ def custom_start_response(status, headers, exc_info = None):
return start_response(status, fixed, exc_info)
return self.app(environ, custom_start_response)
-#god this shit is disorganized and confusing
-class RedditApp(PylonsBaseWSGIApp):
+
+class RedditApp(PylonsApp):
def __init__(self, *args, **kwargs):
super(RedditApp, self).__init__(*args, **kwargs)
self._loading_lock = Lock()
@@ -403,7 +405,8 @@ def make_app(global_conf, full_stack=True, **app_conf):
g = config['pylons.g']
# The Pylons WSGI app
- app = PylonsApp(base_wsgi_app=RedditApp)
+ app = RedditApp()
+ app = RoutesMiddleware(app, config["routes.map"])
# CUSTOM MIDDLEWARE HERE (filtered by the error handling middlewares)
@@ -423,8 +426,7 @@ def make_app(global_conf, full_stack=True, **app_conf):
if asbool(full_stack):
# Handle Python exceptions
- app = ErrorHandler(app, global_conf, error_template=error_template,
- **config['pylons.errorware'])
+ app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
# Display error documents for 401, 403, 404 status codes (and 500 when
# debug is disabled)
@@ -434,9 +436,8 @@ def make_app(global_conf, full_stack=True, **app_conf):
app = RegistryManager(app)
# Static files
- javascripts_app = StaticJavascripts()
static_app = StaticURLParser(config['pylons.paths']['static_files'])
- static_cascade = [static_app, javascripts_app, app]
+ static_cascade = [static_app, app]
if config['r2.plugins'] and g.config['uncompressedJS']:
plugin_static_apps = Cascade([StaticURLParser(plugin.static_dir)
View
8 r2/r2/controllers/error.py
@@ -26,7 +26,7 @@
import pylons
-from paste.httpexceptions import HTTPFound, HTTPMovedPermanently
+from webob.exc import HTTPFound, HTTPMovedPermanently
from pylons.i18n import _
from pylons import c, g, request, response
@@ -165,7 +165,11 @@ def GET_document(self):
code = 404
srname = request.GET.get('srname', '')
takedown = request.GET.get('takedown', "")
-
+
+ # StatusBasedRedirect will override this anyway, but we need this
+ # here for pagecache to see.
+ response.status_int = code
+
if srname:
c.site = Subreddit._by_name(srname)
View
2 r2/r2/controllers/mediaembed.py
@@ -56,7 +56,7 @@ def GET_mediaembed(self, link):
class AdController(MinimalController):
def request_key(self):
- return make_key('request_',
+ return make_key('request',
c.lang,
c.content_langs,
request.host,
View
39 r2/r2/controllers/reddit_base.py
@@ -104,8 +104,8 @@
)
-NEVER = 'Thu, 31 Dec 2037 23:59:59 GMT'
-DELETE = 'Thu, 01-Jan-1970 00:00:01 GMT'
+NEVER = datetime(2037, 12, 31, 23, 59, 59)
+DELETE = datetime(1970, 01, 01, 0, 0, 1)
cache_affecting_cookies = ('reddit_first', 'over18', '_options')
@@ -537,10 +537,6 @@ def set_cnameframe():
or not request.host.split(":")[0].endswith(g.domain)):
c.cname = True
request.environ['REDDIT_CNAME'] = 1
- if request.params.has_key(utils.UrlParser.cname_get):
- del request.params[utils.UrlParser.cname_get]
- if request.get.has_key(utils.UrlParser.cname_get):
- del request.get[utils.UrlParser.cname_get]
c.frameless_cname = request.environ.get('frameless_cname', False)
if hasattr(c.site, 'domain'):
c.authorized_cname = request.environ.get('authorized_cname', False)
@@ -696,7 +692,7 @@ def request_key(self):
except CookieError:
cookies_key = ''
- return make_key('request_',
+ return make_key('request',
c.lang,
c.content_langs,
request.host,
@@ -751,33 +747,24 @@ def try_pagecache(self):
if r:
r, c.cookies = r
response.headers = r.headers
- response.content = r.content
-
- for x in r.cookies.keys():
- if x in cache_affecting_cookies:
- cookie = r.cookies[x]
- response.set_cookie(key=x,
- value=cookie.value,
- domain=cookie.get('domain', None),
- expires=cookie.get('expires', None),
- path=cookie.get('path', None),
- secure=cookie.get('secure', False),
- httponly=cookie.get('httponly', False))
-
- response.status_code = r.status_code
+ response.body = r.body
+ response.status_int = r.status_int
+
request.environ['pylons.routes_dict']['action'] = 'cached_response'
c.request_timer.name = request_timer_name("cached_response")
- # make sure to carry over the content type
- response.content_type = r.headers['content-type']
c.used_cache = True
# response wrappers have already been applied before cache write
c.response_wrapper = None
def post(self):
c.request_timer.intermediate("action")
- if c.response_wrapper:
+ # if the action raised an HTTPException (i.e. it aborted) then pylons
+ # will have replaced response with the exception itself.
+ is_exception_response = getattr(response, "_exception", False)
+
+ if c.response_wrapper and not is_exception_response:
content = "".join(_force_utf8(x)
for x in tup(response.content) if x)
wrapped_content = c.response_wrapper(content)
@@ -795,7 +782,8 @@ def post(self):
and request.method.upper() == 'GET'
and (not c.user_is_loggedin or c.allow_loggedin_cache)
and not c.used_cache
- and response.status_code not in (429, 503)):
+ and response.status_int not in (429, 503)
+ and not is_exception_response):
try:
g.pagecache.set(self.request_key(),
(response._current_obj(), c.cookies),
@@ -899,7 +887,6 @@ def enable_admin_mode(user, first_login=None):
def remember_otp(user):
cookie = user.make_otp_cookie()
expiration = datetime.utcnow() + timedelta(seconds=g.OTP_COOKIE_TTL)
- expiration = expiration.strftime("%a, %d %b %Y %H:%M:%S GMT")
set_user_cookie(g.otp_cookie,
cookie,
secure=True,
View
22 r2/r2/lib/base.py
@@ -25,9 +25,9 @@
import sqlalchemy.exc
from pylons import c, g, request, session, config, response
-from pylons.controllers import WSGIController, Controller
+from pylons.controllers import WSGIController
from pylons.i18n import N_, _, ungettext, get_lang
-from paste import httpexceptions
+from webob.exc import HTTPException, status_map
from r2.lib.filters import spaceCompress, _force_unicode
from r2.lib.template_helpers import get_domain
from utils import storify, string2js, read_http_date
@@ -62,20 +62,23 @@ def is_local_address(ip):
# TODO: support the /20 and /24 private networks? make this configurable?
return ip.startswith('10.')
-def abort(code_or_exception=None, detail="", headers=None, comment=None):
+def abort(code_or_exception=None, detail="", headers=None, comment=None,
+ **kwargs):
"""Raise an HTTPException and save it in environ for use by error pages."""
# Pylons 0.9.6 makes it really hard to get your raised HTTPException,
# so this helper implements it manually using a familiar syntax.
# FIXME: when we upgrade Pylons, we can replace this with raise
# and access environ['pylons.controller.exception']
- if isinstance(code_or_exception, httpexceptions.HTTPException):
+ # NOTE: when we say "upgrade Pylons" we mean to 0.10+
+ if isinstance(code_or_exception, HTTPException):
exc = code_or_exception
else:
- if type(code_or_exception) is type and issubclass(code_or_exception, httpexceptions.HTTPException):
+ if type(code_or_exception) is type and issubclass(code_or_exception,
+ HTTPException):
exc_cls = code_or_exception
else:
- exc_cls = httpexceptions.get_exception(code_or_exception)
- exc = exc_cls(detail, headers, comment)
+ exc_cls = status_map[code_or_exception]
+ exc = exc_cls(detail, headers, comment, **kwargs)
request.environ['r2.controller.exception'] = exc
raise exc
@@ -114,7 +117,6 @@ def __call__(self, environ, start_response):
request.get = storify(request.GET)
request.post = storify(request.POST)
request.referer = environ.get('HTTP_REFERER')
- request.path = environ.get('PATH_INFO')
request.user_agent = environ.get('HTTP_USER_AGENT')
request.fullpath = environ.get('FULLPATH', request.path)
request.port = environ.get('request_port')
@@ -210,7 +212,7 @@ def intermediate_redirect(cls, form_path):
path = add_sr(cls.format_output_url(form_path) +
query_string(params))
- abort(302, path)
+ abort(302, location=path)
@classmethod
def redirect(cls, dest, code = 302):
@@ -219,7 +221,7 @@ def redirect(cls, dest, code = 302):
sends the user to that location with the provided HTTP code.
"""
dest = cls.format_output_url(dest or "/")
- response.status_code = code
+ response.status_int = code
response.headers['Location'] = dest
class EmbedHandler(urllib2.BaseHandler, urllib2.HTTPHandler,
View
2 r2/r2/lib/errors.py
@@ -20,7 +20,7 @@
# Inc. All Rights Reserved.
###############################################################################
-from paste.httpexceptions import HTTPBadRequest, HTTPForbidden, HTTPError
+from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPError
from r2.lib.utils import Storage, tup
from pylons import request
from pylons.i18n import _
View
9 r2/r2/lib/template_helpers.py
@@ -33,14 +33,9 @@
import random
import urlparse
import calendar
-from pylons import g, c
+from pylons import g, c, request
from pylons.i18n import _, ungettext
-from paste.util.mimeparse import desired_matches
-def is_encoding_acceptable(encoding_to_check):
- "Check if a content encoding is acceptable to the user agent."
- header = request.headers.get('Accept-Encoding', '')
- return 'gzip' in desired_matches(['gzip'], header)
static_text_extensions = {
'.js': 'js',
@@ -59,7 +54,7 @@ def static(path, allow_gzip=True):
dirname, filename = os.path.split(path)
extension = os.path.splitext(filename)[1]
is_text = extension in static_text_extensions
- can_gzip = is_text and is_encoding_acceptable('gzip')
+ can_gzip = is_text and 'gzip' in request.accept_encoding
should_gzip = allow_gzip and can_gzip
path_components = []
View
7 r2/setup.py
@@ -72,9 +72,10 @@
name="r2",
version="",
install_requires=[
- "Routes<=1.8",
- "Pylons==0.9.6.2",
- "webhelpers==0.6.4",
+ "webob==1.0.8",
+ "Pylons==0.9.7",
+ "Routes==1.11",
+ "mako>=0.5",
"boto >= 2.0",
"pytz",
"pycrypto",

0 comments on commit 7a81779

Please sign in to comment.
Something went wrong with that request. Please try again.