Mercurial > public > mercurial-scm > hg-stable
diff mercurial/hgweb/request.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 6107d4549fcc |
children | 687b865b95ad |
line wrap: on
line diff
--- a/mercurial/hgweb/request.py Sat Oct 05 10:29:34 2019 -0400 +++ b/mercurial/hgweb/request.py Sun Oct 06 09:45:02 2019 -0400 @@ -8,17 +8,16 @@ from __future__ import absolute_import -#import wsgiref.validate +# import wsgiref.validate -from ..thirdparty import ( - attr, -) +from ..thirdparty import attr from .. import ( error, pycompat, util, ) + class multidict(object): """A dict like object that can store multiple values for a key. @@ -26,6 +25,7 @@ This is inspired by WebOb's class of the same name. """ + def __init__(self): self._items = {} @@ -76,6 +76,7 @@ def asdictoflists(self): return {k: list(v) for k, v in self._items.iteritems()} + @attr.s(frozen=True) class parsedrequest(object): """Represents a parsed WSGI request. @@ -124,6 +125,7 @@ # WSGI environment dict, unmodified. rawenv = attr.ib() + def parserequestfromenv(env, reponame=None, altbaseurl=None, bodyfh=None): """Parse URL components from environment variables. @@ -153,7 +155,7 @@ # We first validate that the incoming object conforms with the WSGI spec. # We only want to be dealing with spec-conforming WSGI implementations. # TODO enable this once we fix internal violations. - #wsgiref.validate.check_environ(env) + # wsgiref.validate.check_environ(env) # PEP-0333 states that environment keys and values are native strings # (bytes on Python 2 and str on Python 3). The code points for the Unicode @@ -161,8 +163,10 @@ # in Mercurial, so mass convert string keys and values to bytes. if pycompat.ispy3: env = {k.encode('latin-1'): v for k, v in env.iteritems()} - env = {k: v.encode('latin-1') if isinstance(v, str) else v - for k, v in env.iteritems()} + env = { + k: v.encode('latin-1') if isinstance(v, str) else v + for k, v in env.iteritems() + } # Some hosting solutions are emulating hgwebdir, and dispatching directly # to an hgweb instance using this environment variable. This was always @@ -255,16 +259,19 @@ raise error.ProgrammingError('reponame requires PATH_INFO') if not env['PATH_INFO'].startswith(repoprefix): - raise error.ProgrammingError('PATH_INFO does not begin with repo ' - 'name: %s (%s)' % (env['PATH_INFO'], - reponame)) + raise error.ProgrammingError( + 'PATH_INFO does not begin with repo ' + 'name: %s (%s)' % (env['PATH_INFO'], reponame) + ) - dispatchpath = env['PATH_INFO'][len(repoprefix):] + dispatchpath = env['PATH_INFO'][len(repoprefix) :] if dispatchpath and not dispatchpath.startswith('/'): - raise error.ProgrammingError('reponame prefix of PATH_INFO does ' - 'not end at path delimiter: %s (%s)' % - (env['PATH_INFO'], reponame)) + raise error.ProgrammingError( + 'reponame prefix of PATH_INFO does ' + 'not end at path delimiter: %s (%s)' + % (env['PATH_INFO'], reponame) + ) apppath = apppath.rstrip('/') + repoprefix dispatchparts = dispatchpath.strip('/').split('/') @@ -295,9 +302,10 @@ headers = [] for k, v in env.iteritems(): if k.startswith('HTTP_'): - headers.append((k[len('HTTP_'):].replace('_', '-'), v)) + headers.append((k[len('HTTP_') :].replace('_', '-'), v)) - from . import wsgiheaders # avoid cycle + from . import wsgiheaders # avoid cycle + headers = wsgiheaders.Headers(headers) # This is kind of a lie because the HTTP header wasn't explicitly @@ -313,24 +321,30 @@ if bodyfh is None: bodyfh = env['wsgi.input'] if 'Content-Length' in headers: - bodyfh = util.cappedreader(bodyfh, - int(headers['Content-Length'] or '0')) + bodyfh = util.cappedreader( + bodyfh, int(headers['Content-Length'] or '0') + ) - return parsedrequest(method=env['REQUEST_METHOD'], - url=fullurl, baseurl=baseurl, - advertisedurl=advertisedfullurl, - advertisedbaseurl=advertisedbaseurl, - urlscheme=env['wsgi.url_scheme'], - remoteuser=env.get('REMOTE_USER'), - remotehost=env.get('REMOTE_HOST'), - apppath=apppath, - dispatchparts=dispatchparts, dispatchpath=dispatchpath, - reponame=reponame, - querystring=querystring, - qsparams=qsparams, - headers=headers, - bodyfh=bodyfh, - rawenv=env) + return parsedrequest( + method=env['REQUEST_METHOD'], + url=fullurl, + baseurl=baseurl, + advertisedurl=advertisedfullurl, + advertisedbaseurl=advertisedbaseurl, + urlscheme=env['wsgi.url_scheme'], + remoteuser=env.get('REMOTE_USER'), + remotehost=env.get('REMOTE_HOST'), + apppath=apppath, + dispatchparts=dispatchparts, + dispatchpath=dispatchpath, + reponame=reponame, + querystring=querystring, + qsparams=qsparams, + headers=headers, + bodyfh=bodyfh, + rawenv=env, + ) + class offsettrackingwriter(object): """A file object like object that is append only and tracks write count. @@ -345,6 +359,7 @@ a WSGI ``start_response()`` function. Since ``write()`` is a callable and not a file object, it doesn't implement other file object methods. """ + def __init__(self, writefn): self._write = writefn self._offset = 0 @@ -363,6 +378,7 @@ def tell(self): return self._offset + class wsgiresponse(object): """Represents a response to a WSGI request. @@ -389,7 +405,8 @@ self._startresponse = startresponse self.status = None - from . import wsgiheaders # avoid cycle + from . import wsgiheaders # avoid cycle + self.headers = wsgiheaders.Headers([]) self._bodybytes = None @@ -399,8 +416,11 @@ self._bodywritefn = None def _verifybody(self): - if (self._bodybytes is not None or self._bodygen is not None - or self._bodywillwrite): + if ( + self._bodybytes is not None + or self._bodygen is not None + or self._bodywillwrite + ): raise error.ProgrammingError('cannot define body multiple times') def setbodybytes(self, b): @@ -450,8 +470,11 @@ if not self.status: raise error.ProgrammingError('status line not defined') - if (self._bodybytes is None and self._bodygen is None - and not self._bodywillwrite): + if ( + self._bodybytes is None + and self._bodygen is None + and not self._bodywillwrite + ): raise error.ProgrammingError('response body not defined') # RFC 7232 Section 4.1 states that a 304 MUST generate one of @@ -469,20 +492,30 @@ # Strictly speaking, this is too strict. But until it causes # problems, let's be strict. - badheaders = {k for k in self.headers.keys() - if k.lower() not in ('date', 'etag', 'expires', - 'cache-control', - 'content-location', - 'content-security-policy', - 'vary')} + badheaders = { + k + for k in self.headers.keys() + if k.lower() + not in ( + 'date', + 'etag', + 'expires', + 'cache-control', + 'content-location', + 'content-security-policy', + 'vary', + ) + } if badheaders: raise error.ProgrammingError( - 'illegal header on 304 response: %s' % - ', '.join(sorted(badheaders))) + 'illegal header on 304 response: %s' + % ', '.join(sorted(badheaders)) + ) if self._bodygen is not None or self._bodywillwrite: - raise error.ProgrammingError("must use setbodybytes('') with " - "304 responses") + raise error.ProgrammingError( + "must use setbodybytes('') with " "304 responses" + ) # Various HTTP clients (notably httplib) won't read the HTTP response # until the HTTP request has been sent in full. If servers (us) send a @@ -531,10 +564,11 @@ if not chunk: break - strheaders = [(pycompat.strurl(k), pycompat.strurl(v)) for - k, v in self.headers.items()] - write = self._startresponse(pycompat.sysstr(self.status), - strheaders) + strheaders = [ + (pycompat.strurl(k), pycompat.strurl(v)) + for k, v in self.headers.items() + ] + write = self._startresponse(pycompat.sysstr(self.status), strheaders) if self._bodybytes: yield self._bodybytes @@ -566,17 +600,22 @@ raise error.ProgrammingError('must call setbodywillwrite() first') if not self._started: - raise error.ProgrammingError('must call sendresponse() first; did ' - 'you remember to consume it since it ' - 'is a generator?') + raise error.ProgrammingError( + 'must call sendresponse() first; did ' + 'you remember to consume it since it ' + 'is a generator?' + ) assert self._bodywritefn return offsettrackingwriter(self._bodywritefn) + def wsgiapplication(app_maker): '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir() can and should now be used as a WSGI application.''' application = app_maker() + def run_wsgi(env, respond): return application(env, respond) + return run_wsgi