from datetime import timedelta, tzinfo import pytest from webob.request import Request from webob.util import text_ class GMT(tzinfo): """UTC""" ZERO = timedelta(0) def utcoffset(self, dt): return self.ZERO def tzname(self, dt): return "UTC" def dst(self, dt): return self.ZERO class MockDescriptor: _val = "avalue" def __get__(self, obj, type=None): return self._val def __set__(self, obj, val): self._val = val def __delete__(self, obj): self._val = None def test_environ_getter_docstring(): from webob.descriptors import environ_getter desc = environ_getter("akey") assert desc.__doc__ == "Gets and sets the ``akey`` key in the environment." def test_environ_getter_nodefault_keyerror(): from webob.descriptors import environ_getter req = Request.blank("/") desc = environ_getter("akey") with pytest.raises(KeyError): desc.fget(req) def test_environ_getter_nodefault_fget(): from webob.descriptors import environ_getter req = Request.blank("/") desc = environ_getter("akey") desc.fset(req, "bar") assert req.environ["akey"] == "bar" def test_environ_getter_nodefault_fdel(): from webob.descriptors import environ_getter desc = environ_getter("akey") assert desc.fdel is None def test_environ_getter_default_fget(): from webob.descriptors import environ_getter req = Request.blank("/") desc = environ_getter("akey", default="the_default") assert desc.fget(req) == "the_default" def test_environ_getter_default_fset(): from webob.descriptors import environ_getter req = Request.blank("/") desc = environ_getter("akey", default="the_default") desc.fset(req, "bar") assert req.environ["akey"] == "bar" def test_environ_getter_default_fset_none(): from webob.descriptors import environ_getter req = Request.blank("/") desc = environ_getter("akey", default="the_default") desc.fset(req, "baz") desc.fset(req, None) assert "akey" not in req.environ def test_environ_getter_default_fdel(): from webob.descriptors import environ_getter req = Request.blank("/") desc = environ_getter("akey", default="the_default") desc.fset(req, "baz") assert "akey" in req.environ desc.fdel(req) assert "akey" not in req.environ def test_environ_getter_rfc_section(): from webob.descriptors import environ_getter desc = environ_getter("HTTP_X_AKEY", rfc_section="14.3") assert ( desc.__doc__ == "Gets and sets the ``X-Akey`` header " "(`HTTP spec section 14.3 " "`_)." ) def test_upath_property_fget(): from webob.descriptors import upath_property req = Request.blank("/") desc = upath_property("akey") assert desc.fget(req) == "" def test_upath_property_fset(): from webob.descriptors import upath_property req = Request.blank("/") desc = upath_property("akey") desc.fset(req, "avalue") assert desc.fget(req) == "avalue" def test_header_getter_doc(): from webob.descriptors import header_getter desc = header_getter("X-Header", "14.3") assert ( "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3" in desc.__doc__ ) assert "``X-Header`` header" in desc.__doc__ def test_header_getter_fget(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") assert desc.fget(resp) is None def test_header_getter_fset(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, "avalue") assert desc.fget(resp) == "avalue" def test_header_getter_fset_none(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, "avalue") desc.fset(resp, None) assert desc.fget(resp) is None def test_header_getter_fset_text(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, text_("avalue")) assert desc.fget(resp) == "avalue" def test_header_getter_fset_text_control_chars(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") with pytest.raises(ValueError): desc.fset(resp, text_("\n")) def test_header_getter_fset_non_text(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") with pytest.raises(ValueError): desc.fset(resp, b"test") def test_header_getter_fdel(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, "avalue2") desc.fdel(resp) assert desc.fget(resp) is None def test_header_getter_unicode_fget_none(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") assert desc.fget(resp) is None def test_header_getter_unicode_fget(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, "avalue") assert desc.fget(resp) == "avalue" def test_header_getter_unicode_fset_none(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, None) assert desc.fget(resp) is None def test_header_getter_unicode_fset(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, "avalue2") assert desc.fget(resp) == "avalue2" def test_header_getter_unicode_fdel(): from webob import Response from webob.descriptors import header_getter resp = Response("aresp") desc = header_getter("AHEADER", "14.3") desc.fset(resp, "avalue3") desc.fdel(resp) assert desc.fget(resp) is None def test_converter_not_prop(): from webob.descriptors import converter, parse_int_safe, serialize_int with pytest.raises(AssertionError): converter( ("CONTENT_LENGTH", None, "14.13"), parse_int_safe, serialize_int, "int" ) def test_converter_with_name_docstring(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) desc = converter( environ_getter("CONTENT_LENGTH", "666", "14.13"), parse_int_safe, serialize_int, "int", ) assert ( "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13" in desc.__doc__ ) assert "``Content-Length`` header" in desc.__doc__ def test_converter_with_name_fget(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) req = Request.blank("/") desc = converter( environ_getter("CONTENT_LENGTH", "666", "14.13"), parse_int_safe, serialize_int, "int", ) assert desc.fget(req) == 666 def test_converter_with_name_fset(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) req = Request.blank("/") desc = converter( environ_getter("CONTENT_LENGTH", "666", "14.13"), parse_int_safe, serialize_int, "int", ) desc.fset(req, "999") assert desc.fget(req) == 999 def test_converter_without_name_fget(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) req = Request.blank("/") desc = converter( environ_getter("CONTENT_LENGTH", "666", "14.13"), parse_int_safe, serialize_int ) assert desc.fget(req) == 666 def test_converter_without_name_fset(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) req = Request.blank("/") desc = converter( environ_getter("CONTENT_LENGTH", "666", "14.13"), parse_int_safe, serialize_int ) desc.fset(req, "999") assert desc.fget(req) == 999 def test_converter_none_for_wrong_type(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) req = Request.blank("/") desc = converter( environ_getter("CONTENT_LENGTH", "sixsixsix", "14.13"), parse_int_safe, serialize_int, "int", ) assert desc.fget(req) is None def test_converter_delete(): from webob.descriptors import ( converter, environ_getter, parse_int_safe, serialize_int, ) req = Request.blank("/") desc = converter( environ_getter("CONTENT_LENGTH", "666", "14.13"), parse_int_safe, serialize_int, "int", ) with pytest.raises(KeyError): desc.fdel(req) def test_list_header(): from webob.descriptors import list_header desc = list_header("CONTENT_LENGTH", "14.13") assert type(desc) == property def test_parse_list_single(): from webob.descriptors import parse_list result = parse_list("avalue") assert result == ("avalue",) def test_parse_list_multiple(): from webob.descriptors import parse_list result = parse_list("avalue,avalue2") assert result == ("avalue", "avalue2") def test_parse_list_none(): from webob.descriptors import parse_list result = parse_list(None) assert result is None def test_parse_list_unicode_single(): from webob.descriptors import parse_list result = parse_list("avalue") assert result == ("avalue",) def test_parse_list_unicode_multiple(): from webob.descriptors import parse_list result = parse_list("avalue,avalue2") assert result == ("avalue", "avalue2") def test_serialize_list(): from webob.descriptors import serialize_list result = serialize_list(("avalue", "avalue2")) assert result == "avalue, avalue2" def test_serialize_list_string(): from webob.descriptors import serialize_list result = serialize_list("avalue") assert result == "avalue" def test_serialize_list_unicode(): from webob.descriptors import serialize_list result = serialize_list("avalue") assert result == "avalue" def test_converter_date(): import datetime from webob.descriptors import converter_date, environ_getter req = Request.blank("/") UTC = GMT() desc = converter_date( environ_getter("HTTP_DATE", "Tue, 15 Nov 1994 08:12:31 GMT", "14.8") ) assert desc.fget(req) == datetime.datetime(1994, 11, 15, 8, 12, 31, tzinfo=UTC) def test_converter_date_docstring(): from webob.descriptors import converter_date, environ_getter desc = converter_date( environ_getter("HTTP_DATE", "Tue, 15 Nov 1994 08:12:31 GMT", "14.8") ) assert ( "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8" in desc.__doc__ ) assert "``Date`` header" in desc.__doc__ def test_date_header_fget_none(): from webob import Response from webob.descriptors import date_header resp = Response("aresponse") desc = date_header("HTTP_DATE", "14.8") assert desc.fget(resp) is None def test_date_header_fset_fget(): import datetime from webob import Response from webob.descriptors import date_header resp = Response("aresponse") UTC = GMT() desc = date_header("HTTP_DATE", "14.8") desc.fset(resp, "Tue, 15 Nov 1994 08:12:31 GMT") assert desc.fget(resp) == datetime.datetime(1994, 11, 15, 8, 12, 31, tzinfo=UTC) def test_date_header_fdel(): from webob import Response from webob.descriptors import date_header resp = Response("aresponse") desc = date_header("HTTP_DATE", "14.8") desc.fset(resp, "Tue, 15 Nov 1994 08:12:31 GMT") desc.fdel(resp) assert desc.fget(resp) is None def test_deprecated_property(): from webob.descriptors import deprecated_property class Foo: pass Foo.attr = deprecated_property("attr", "attr", "whatever", "1.2") foo = Foo() with pytest.raises(DeprecationWarning): getattr(foo, "attr") with pytest.raises(DeprecationWarning): setattr(foo, "attr", {}) with pytest.raises(DeprecationWarning): delattr(foo, "attr") def test_parse_etag_response(): from webob.descriptors import parse_etag_response etresp = parse_etag_response("etag") assert etresp == "etag" def test_parse_etag_response_quoted(): from webob.descriptors import parse_etag_response etresp = parse_etag_response('"etag"') assert etresp == "etag" def test_parse_etag_response_is_none(): from webob.descriptors import parse_etag_response etresp = parse_etag_response(None) assert etresp is None def test_serialize_etag_response(): from webob.descriptors import serialize_etag_response etresp = serialize_etag_response("etag") assert etresp == '"etag"' def test_serialize_if_range_string(): from webob.descriptors import serialize_if_range val = serialize_if_range("avalue") assert val == "avalue" def test_serialize_if_range_unicode(): from webob.descriptors import serialize_if_range val = serialize_if_range("avalue") assert val == "avalue" def test_serialize_if_range_datetime(): import datetime from webob.descriptors import serialize_if_range UTC = GMT() val = serialize_if_range(datetime.datetime(1994, 11, 15, 8, 12, 31, tzinfo=UTC)) assert val, "Tue == 15 Nov 1994 08:12:31 GMT" def test_serialize_if_range_other(): from webob.descriptors import serialize_if_range val = serialize_if_range(123456) assert val == "123456" def test_parse_range_none(): from webob.descriptors import parse_range assert parse_range(None) is None def test_parse_range_type(): from webob.byterange import Range from webob.descriptors import parse_range val = parse_range("bytes=1-500") assert type(val) is type(Range.parse("bytes=1-500")) # noqa: E701 def test_parse_range_values(): from webob.byterange import Range range = Range.parse("bytes=1-500") assert range.start == 1 assert range.end == 501 def test_serialize_range_none(): from webob.descriptors import serialize_range val = serialize_range(None) assert val is None def test_serialize_range(): from webob.descriptors import serialize_range val = serialize_range((1, 500)) assert val == "bytes=1-499" def test_parse_int_none(): from webob.descriptors import parse_int val = parse_int(None) assert val is None def test_parse_int_emptystr(): from webob.descriptors import parse_int val = parse_int("") assert val is None def test_parse_int(): from webob.descriptors import parse_int val = parse_int("123") assert val == 123 def test_parse_int_invalid(): from webob.descriptors import parse_int with pytest.raises(ValueError): parse_int("abc") def test_parse_int_safe_none(): from webob.descriptors import parse_int_safe assert parse_int_safe(None) is None def test_parse_int_safe_emptystr(): from webob.descriptors import parse_int_safe assert parse_int_safe("") is None def test_parse_int_safe(): from webob.descriptors import parse_int_safe assert parse_int_safe("123") == 123 def test_parse_int_safe_invalid(): from webob.descriptors import parse_int_safe assert parse_int_safe("abc") is None def test_serialize_int(): from webob.descriptors import serialize_int assert serialize_int is str def test_parse_content_range_none(): from webob.descriptors import parse_content_range assert parse_content_range(None) is None def test_parse_content_range_emptystr(): from webob.descriptors import parse_content_range assert parse_content_range(" ") is None def test_parse_content_range_length(): from webob.byterange import ContentRange from webob.descriptors import parse_content_range val = parse_content_range("bytes 0-499/1234") assert val.length == ContentRange.parse("bytes 0-499/1234").length def test_parse_content_range_start(): from webob.byterange import ContentRange from webob.descriptors import parse_content_range val = parse_content_range("bytes 0-499/1234") assert val.start == ContentRange.parse("bytes 0-499/1234").start def test_parse_content_range_stop(): from webob.byterange import ContentRange from webob.descriptors import parse_content_range val = parse_content_range("bytes 0-499/1234") assert val.stop == ContentRange.parse("bytes 0-499/1234").stop def test_serialize_content_range_none(): from webob.descriptors import serialize_content_range assert serialize_content_range(None) == "None" # XXX: Seems wrong def test_serialize_content_range_emptystr(): from webob.descriptors import serialize_content_range assert serialize_content_range("") is None def test_serialize_content_range_invalid(): from webob.descriptors import serialize_content_range with pytest.raises(ValueError): serialize_content_range((1,)) def test_serialize_content_range_asterisk(): from webob.descriptors import serialize_content_range assert serialize_content_range((0, 500)) == "bytes 0-499/*" def test_serialize_content_range_defined(): from webob.descriptors import serialize_content_range assert serialize_content_range((0, 500, 1234)) == "bytes 0-499/1234" def test_parse_auth_params_leading_capital_letter(): from webob.descriptors import parse_auth_params val = parse_auth_params("Basic Realm=WebOb") assert val == {"ealm": "WebOb"} def test_parse_auth_params_trailing_capital_letter(): from webob.descriptors import parse_auth_params val = parse_auth_params("Basic realM=WebOb") assert val == {} def test_parse_auth_params_doublequotes(): from webob.descriptors import parse_auth_params val = parse_auth_params('Basic realm="Web Object"') assert val == {"realm": "Web Object"} def test_parse_auth_params_multiple_values(): from webob.descriptors import parse_auth_params val = parse_auth_params("foo='blah &&234', qop=foo, nonce='qwerty1234'") assert val == {"nonce": "'qwerty1234'", "foo": "'blah &&234'", "qop": "foo"} def test_parse_auth_params_truncate_on_comma(): from webob.descriptors import parse_auth_params val = parse_auth_params("Basic realm=WebOb,this_will_truncate") assert val == {"realm": "WebOb"} def test_parse_auth_params_emptystr(): from webob.descriptors import parse_auth_params assert parse_auth_params("") == {} def test_parse_auth_params_bad_whitespace(): from webob.descriptors import parse_auth_params assert parse_auth_params('a= "2 ", b =3, c=4 ') == {"a": "2 ", "b": "3", "c": "4"} def test_authorization2(): from webob.descriptors import parse_auth_params for s, d in [ ("x=y", {"x": "y"}), ('x="y"', {"x": "y"}), ("x=y,z=z", {"x": "y", "z": "z"}), ("x=y, z=z", {"x": "y", "z": "z"}), ('x="y",z=z', {"x": "y", "z": "z"}), ('x="y", z=z', {"x": "y", "z": "z"}), ('x="y,x", z=z', {"x": "y,x", "z": "z"}), ]: assert parse_auth_params(s) == d def test_parse_auth_none(): from webob.descriptors import parse_auth assert parse_auth(None) is None def test_parse_auth_emptystr(): from webob.descriptors import parse_auth assert parse_auth("") == ("", "") def test_parse_auth_bearer(): from webob.descriptors import parse_auth assert parse_auth("Bearer token").authtype == "Bearer" assert parse_auth("Bearer token").params == "token" def test_parse_auth_unknown_nospace(): from webob.descriptors import parse_auth assert parse_auth("NoSpace") == ("NoSpace", "") def test_parse_auth_known_nospace(): from webob.descriptors import parse_auth assert parse_auth("Digest") == ("Digest", {}) def test_parse_auth_basic(): from webob.descriptors import parse_auth assert parse_auth("Basic realm=WebOb") == ("Basic", "realm=WebOb") def test_parse_auth_basic_quoted(): from webob.descriptors import parse_auth assert parse_auth('Basic realm="Web Ob"') == ("Basic", {"realm": "Web Ob"}) def test_parse_auth_basic_quoted_multiple_unknown(): from webob.descriptors import parse_auth assert parse_auth("foo='blah &&234', qop=foo, nonce='qwerty1234'") == ( "foo='blah", "&&234', qop=foo, nonce='qwerty1234'", ) def test_parse_auth_basic_quoted_known_multiple(): from webob.descriptors import parse_auth assert parse_auth("Basic realm='blah &&234', qop=foo, nonce='qwerty1234'") == ( "Basic", "realm='blah &&234', qop=foo, nonce='qwerty1234'", ) def test_serialize_auth_none(): from webob.descriptors import serialize_auth assert serialize_auth(None) is None def test_serialize_auth_emptystr(): from webob.descriptors import serialize_auth assert serialize_auth("") == "" def test_serialize_auth_str(): from webob.descriptors import serialize_auth assert serialize_auth("some string") == "some string" def test_serialize_auth_parsed_emptystr(): from webob.descriptors import serialize_auth assert serialize_auth(("", "")) == " " def test_serialize_auth_parsed_unknown_nospace(): from webob.descriptors import serialize_auth assert serialize_auth(("NoSpace", "")) == "NoSpace " def test_serialize_auth_parsed_known_nospace(): from webob.descriptors import serialize_auth assert serialize_auth(("Digest", {})) == "Digest " def test_serialize_auth_basic_quoted(): from webob.descriptors import serialize_auth val = serialize_auth(("Basic", 'realm="WebOb"')) assert val == 'Basic realm="WebOb"' def test_serialize_auth_digest_multiple(): from webob.descriptors import serialize_auth val = serialize_auth(("Digest", 'realm="WebOb", nonce=abcde12345, qop=foo')) flags = val[len("Digest") :] result = sorted(x.strip() for x in flags.split(",")) assert result == ["nonce=abcde12345", "qop=foo", 'realm="WebOb"'] def test_serialize_auth_digest_tuple(): from webob.descriptors import serialize_auth val = serialize_auth( ("Digest", {"realm": '"WebOb"', "nonce": "abcde12345", "qop": "foo"}) ) flags = val[len("Digest") :] result = sorted(x.strip() for x in flags.split(",")) assert result == ['nonce="abcde12345"', 'qop="foo"', 'realm=""WebOb""'] _nodefault = object() class _TestEnvironDecoder: def _callFUT(self, key, default=_nodefault, rfc_section=None, encattr=None): from webob.descriptors import environ_decoder if default is _nodefault: return environ_decoder(key, rfc_section=rfc_section, encattr=encattr) else: return environ_decoder( key, default=default, rfc_section=rfc_section, encattr=encattr ) def test_docstring(self): desc = self._callFUT("akey") assert desc.__doc__ == "Gets and sets the ``akey`` key in the environment." def test_nodefault_keyerror(self): req = self._makeRequest() desc = self._callFUT("akey") with pytest.raises(KeyError): desc.fget(req) def test_nodefault_fget(self): req = self._makeRequest() desc = self._callFUT("akey") desc.fset(req, "bar") assert req.environ["akey"] == "bar" def test_nodefault_fdel(self): desc = self._callFUT("akey") assert desc.fdel is None def test_default_fget(self): req = self._makeRequest() desc = self._callFUT("akey", default="the_default") assert desc.fget(req) == "the_default" def test_default_fset(self): req = self._makeRequest() desc = self._callFUT("akey", default="the_default") desc.fset(req, "bar") assert req.environ["akey"] == "bar" def test_default_fset_none(self): req = self._makeRequest() desc = self._callFUT("akey", default="the_default") desc.fset(req, "baz") desc.fset(req, None) assert "akey" not in req.environ def test_default_fdel(self): req = self._makeRequest() desc = self._callFUT("akey", default="the_default") desc.fset(req, "baz") assert "akey" in req.environ desc.fdel(req) assert "akey" not in req.environ def test_rfc_section(self): desc = self._callFUT("HTTP_X_AKEY", rfc_section="14.3") assert ( desc.__doc__ == "Gets and sets the ``X-Akey`` header " "(`HTTP spec section 14.3 " "`_)." ) def test_fset_nonascii(self): desc = self._callFUT("HTTP_X_AKEY", encattr="url_encoding") req = self._makeRequest() desc.fset(req, text_(b"\xc3\xab", "utf-8")) assert req.environ["HTTP_X_AKEY"] == str(b"\xc3\xab", "latin-1") class TestEnvironDecoder(_TestEnvironDecoder): def _makeRequest(self): from webob.request import BaseRequest req = BaseRequest.blank("/") return req def test_fget_nonascii(self): desc = self._callFUT("HTTP_X_AKEY", encattr="url_encoding") req = self._makeRequest() req.environ["HTTP_X_AKEY"] = str(b"\xc3\xab", "latin-1") result = desc.fget(req) assert result == text_(b"\xc3\xab", "utf-8")