From 1186abcfe4b5fa54ec54020ff33616706489b403 Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Bernal Date: Tue, 5 Apr 2022 19:59:50 +0800 Subject: [PATCH] add an alternative constructor from_anystr() in HttpRequestBody This reverts commit 109a67081c2a6a2de83f14d2b9ecc5b4771a4293. --- docs/advanced/additional-requests.rst | 15 +++++++++------ tests/test_requests.py | 10 +++++----- web_poet/requests.py | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/docs/advanced/additional-requests.rst b/docs/advanced/additional-requests.rst index 1ce67e5c..8f901639 100644 --- a/docs/advanced/additional-requests.rst +++ b/docs/advanced/additional-requests.rst @@ -47,7 +47,7 @@ a generic HTTP Request: :class:`~.HttpRequest`. Here's an example: "Page": page_num, "ProductID": product_id, } - ).encode("utf-8"), + ), ) print(request.url) # https://www.api.example.com/product-pagination/ @@ -73,9 +73,12 @@ There are a few things to take note here: * ``body`` is represented by the :class:`~.HttpRequestBody` class which is simply a subclass of the ``bytes`` class. Using the ``body`` param of - :class:`~.HttpRequest` needs to have an input argument in ``bytes``. In our - code example, we've converted it from ``str`` to ``bytes`` using the ``encode()`` - string method. + :class:`~.HttpRequest` supports converting it from ``str`` to ``bytes`` + using **utf-8** as the default encoding. + + * Note that the :meth:`~.HttpRequestBody.from_anystr` alternative constructor + for :class:`~.HttpRequestBody` can also be used to support instantiation of + ``str`` to ``bytes`` using any type of encoding (`default is` **utf-8**). Most of the time though, what you'll be defining would be ``GET`` requests. Thus, it's perfectly fine to define them as: @@ -211,7 +214,7 @@ Thus, additional requests inside the Page Object are typically needed for it: "Page": 2, "ProductID": item["product_id"], } - ).encode("utf-8"), + ), ) item["related_product_ids"].extend(self.parse_related_product_ids(response)) return item @@ -293,7 +296,7 @@ list of :class:`~.HttpRequest` to be executed in batch using the "Page": page_num, "ProductID": item["product_id"], } - ).encode("utf-8"), + ), ) @staticmethod diff --git a/tests/test_requests.py b/tests/test_requests.py index bdc967d6..b2b5cadd 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -37,9 +37,9 @@ def test_http_request_body_bytes_api(): assert b"ent" in http_body -def test_http_request_body_str_api(): - with pytest.raises(TypeError): - HttpRequestBody("string content") +def test_http_request_body_from_anystr(): + http_body = HttpRequestBody.from_anystr("originally string") + assert http_body == b"originally string" def test_http_request_bytes_body(): @@ -49,8 +49,8 @@ def test_http_request_bytes_body(): def test_http_request_body_conversion_str(): - with pytest.raises(TypeError): - HttpRequest("http://example.com", body="content") + request = HttpRequest("http://example.com", body="content") + assert request.body == b"content" def test_http_request_body_validation_None(): diff --git a/web_poet/requests.py b/web_poet/requests.py index 547ee03f..a3649334 100644 --- a/web_poet/requests.py +++ b/web_poet/requests.py @@ -42,7 +42,17 @@ class RequestBackendError(Exception): class HttpRequestBody(bytes): """A container for holding the raw HTTP request body in bytes format.""" - pass + @classmethod + def from_anystr( + cls: Type[T_body], value: AnyStr, encoding: str = "utf-8" + ) -> T_body: + """An alternative constructor to handle both ``str`` and ``bytes`` types + of input argument. + """ + + if isinstance(value, str): + return cls(value, encoding=encoding) + return cls(value) class HttpRequestHeaders(CIMultiDict): @@ -93,7 +103,7 @@ class HttpRequest: factory=HttpRequestHeaders, converter=HttpRequestHeaders ) body: HttpRequestBody = attrs.field( - factory=HttpRequestBody, converter=HttpRequestBody + factory=HttpRequestBody, converter=HttpRequestBody.from_anystr # type: ignore )