utils.rfc6266: Fix lint

This commit is contained in:
Florian Bruhin 2014-08-14 13:11:13 +02:00
parent 9cf80cf498
commit ef1035f2ba
3 changed files with 37 additions and 18 deletions

View File

@ -672,7 +672,8 @@ class CharacterSetTests(AttachmentTestCase):
The octet %82 does not represent a valid ISO-8859-1 code point, so the The octet %82 does not represent a valid ISO-8859-1 code point, so the
UA should really ignore the parameter. UA should really ignore the parameter.
""" """
self._check_ignored("attachment; iso-8859-1''foo-%c3%a4-%e2%82%ac.html") self._check_ignored("attachment; "
"iso-8859-1''foo-%c3%a4-%e2%82%ac.html")
def test_attwithfn2231iso_bad(self): def test_attwithfn2231iso_bad(self):
"""'attachment', specifying a filename of foo-ä.html. """'attachment', specifying a filename of foo-ä.html.

View File

@ -45,7 +45,7 @@ def parse_content_disposition(reply):
# os.path.basename later. # os.path.basename later.
try: try:
content_disposition = rfc6266.parse_headers( content_disposition = rfc6266.parse_headers(
bytes(reply.rawHeader('Content-Disposition')), relaxed=True) bytes(reply.rawHeader('Content-Disposition')))
filename = content_disposition.filename_unsafe filename = content_disposition.filename_unsafe
except UnicodeDecodeError as e: except UnicodeDecodeError as e:
logger.warning("Error while getting filename: {}: {}".format( logger.warning("Error while getting filename: {}: {}".format(

View File

@ -1,6 +1,26 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""pyPEG parsing for the RFC 6266 (Content-Disposition) header. """
import pypeg2 as peg import pypeg2 as peg
import os.path
from collections import namedtuple from collections import namedtuple
import urllib.parse import urllib.parse
import string import string
@ -37,6 +57,7 @@ token_chars = attr_chars + "*'%"
# which might include non-ascii octets. # which might include non-ascii octets.
token_re = '[{}]+'.format(re.escape(token_chars)) token_re = '[{}]+'.format(re.escape(token_chars))
class Token(str): class Token(str):
"""A token (RFC 2616, Section 2.2).""" """A token (RFC 2616, Section 2.2)."""
@ -61,6 +82,7 @@ qdtext_re = r'[^"{}]'.format(re.escape(ctl_chars))
quoted_pair_re = r'\\[{}]'.format(re.escape( quoted_pair_re = r'\\[{}]'.format(re.escape(
''.join(chr(i) for i in range(128)))) ''.join(chr(i) for i in range(128))))
class QuotedString(str): class QuotedString(str):
"""A quoted string (RFC 2616, Section 2.2).""" """A quoted string (RFC 2616, Section 2.2)."""
@ -120,6 +142,7 @@ class ExtValue(peg.List):
grammar = peg.contiguous(Charset, "'", peg.optional(Language), "'", grammar = peg.contiguous(Charset, "'", peg.optional(Language), "'",
ValueChars) ValueChars)
class ExtToken(peg.Symbol): class ExtToken(peg.Symbol):
"""A token introducing an extended value (RFC 6266, Section 4.1).""" """A token introducing an extended value (RFC 6266, Section 4.1)."""
@ -206,7 +229,7 @@ class ContentDisposition:
in the download case. in the download case.
""" """
def __init__(self, disposition='inline', assocs=None, location=None): def __init__(self, disposition='inline', assocs=None):
"""This constructor is used internally after parsing the header. """This constructor is used internally after parsing the header.
Instances should generally be created from a factory Instances should generally be created from a factory
@ -216,7 +239,6 @@ class ContentDisposition:
self.disposition = 'inline' self.disposition = 'inline'
else: else:
self.disposition = disposition[0] self.disposition = disposition[0]
self.location = location
if assocs is None: if assocs is None:
self.assocs = {} self.assocs = {}
else: else:
@ -228,11 +250,7 @@ class ContentDisposition:
@property @property
def filename_unsafe(self): def filename_unsafe(self):
"""The filename from the Content-Disposition header. """The filename from the Content-Disposition header or None.
If a location was passed at instanciation, the basename
from that may be used as a fallback. Otherwise, this may
be the None value.
On safety: On safety:
This property records the intent of the sender. This property records the intent of the sender.
@ -249,8 +267,6 @@ class ContentDisposition:
elif 'filename' in self.assocs: elif 'filename' in self.assocs:
# XXX Reject non-ascii (parsed via qdtext) here? # XXX Reject non-ascii (parsed via qdtext) here?
return self.assocs['filename'] return self.assocs['filename']
elif self.location is not None:
return os.path.basename(self.location_path.rstrip('/'))
@property @property
def is_inline(self): def is_inline(self):
@ -263,8 +279,8 @@ class ContentDisposition:
return self.disposition.lower() == 'inline' return self.disposition.lower() == 'inline'
def __repr__(self): def __repr__(self):
return 'ContentDisposition(%r, %r, %r)' % ( return 'ContentDisposition(%r, %r)' % (
self.disposition, self.assocs, self.location) self.disposition, self.assocs)
def normalize_ws(text): def normalize_ws(text):
@ -272,8 +288,9 @@ def normalize_ws(text):
return ' '.join(text.split()) return ' '.join(text.split())
def parse_headers(content_disposition, location=None, relaxed=False): def parse_headers(content_disposition):
"""Build a ContentDisposition from header values.""" """Build a ContentDisposition from header values."""
# pylint: disable=maybe-no-member
# We allow non-ascii here (it will only be parsed inside of qdtext, and # We allow non-ascii here (it will only be parsed inside of qdtext, and
# rejected by the grammar if it appears in other places), although parsing # rejected by the grammar if it appears in other places), although parsing
# it can be ambiguous. Parsing it ensures that a non-ambiguous filename* # it can be ambiguous. Parsing it ensures that a non-ambiguous filename*
@ -292,9 +309,10 @@ def parse_headers(content_disposition, location=None, relaxed=False):
try: try:
parsed = peg.parse(content_disposition, ContentDispositionValue) parsed = peg.parse(content_disposition, ContentDispositionValue)
except (SyntaxError, DuplicateParamError, InvalidISO8859Error): except (SyntaxError, DuplicateParamError, InvalidISO8859Error):
return ContentDisposition(location=location) return ContentDisposition()
return ContentDisposition( else:
disposition=parsed.dtype, assocs=parsed.params, location=location) return ContentDisposition(disposition=parsed.dtype,
assocs=parsed.params)
def parse_ext_value(val): def parse_ext_value(val):