Skip to content

Commit

Permalink
Reworks the inheritence ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
stumpylog committed Jan 11, 2024
1 parent 4730e25 commit f3df0d1
Show file tree
Hide file tree
Showing 16 changed files with 408 additions and 142 deletions.
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ dependencies = [
"coverage[toml] >= 7.3",
"pytest >= 7.4",
"pytest-sugar",
"pytest-env",
"pytest-httpx ~= 0.26; python_version >= '3.9'",
"pytest-httpx ~= 0.22; python_version < '3.9'",
"pikepdf",
Expand Down Expand Up @@ -233,6 +234,9 @@ minversion = "7.0"
testpaths = ["tests"]
addopts = "--pythonwarnings=all"

[tool.pytest_env]
#SAVE_TEST_OUTPUT = 1

[tool.coverage.run]
source_pkgs = ["gotenberg_client", "tests"]
branch = true
Expand Down
186 changes: 61 additions & 125 deletions src/gotenberg_client/_convert/chromium.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,35 @@
# SPDX-FileCopyrightText: 2023-present Trenton H <[email protected]>
#
# SPDX-License-Identifier: MPL-2.0
import json
import logging
from pathlib import Path
from typing import Dict
from typing import Final
from typing import Iterable
from typing import List
from typing import Literal
from typing import Protocol
from typing import Union
from warnings import warn

from gotenberg_client._base import BaseApi
from gotenberg_client._convert.common import ConvertBaseRoute
from gotenberg_client._base import BaseRoute
from gotenberg_client._convert.common import ConsoleExceptionMixin
from gotenberg_client._convert.common import CustomHTTPHeaderMixin
from gotenberg_client._convert.common import EmulatedMediaMixin
from gotenberg_client._convert.common import HeaderFooterMixin
from gotenberg_client._convert.common import InvalidStatusCodesMixin
from gotenberg_client._convert.common import PagePropertiesMixin
from gotenberg_client._convert.common import PerformanceModeMixin
from gotenberg_client._convert.common import RenderControlMixin
from gotenberg_client._typing_compat import Self
from gotenberg_client.options import EmulatedMediaType
from gotenberg_client.options import Margin
from gotenberg_client.options import PageSize
from gotenberg_client._utils import FORCE_MULTIPART
from gotenberg_client._utils import ForceMultipartDict

logger = logging.getLogger()


# See https://github.com/psf/requests/issues/1081#issuecomment-428504128
class ForceMultipartDict(Dict):
def __bool__(self) -> bool:
return True


class HasFormDataProtocol(Protocol):
_form_data: Dict[str, str]


FORCE_MULTIPART: Final = ForceMultipartDict()


class PageSizeMixin:
pass


class ChromiumBaseRoute(ConvertBaseRoute):
"""
https://gotenberg.dev/docs/routes#convert-with-chromium
"""

def header(self, header: Path) -> Self:
self._add_file_map(header, "header.html")
class _FileBasedRoute(BaseRoute):
def index(self, index: Path) -> Self:
self._add_file_map(index, "index.html")
return self

def footer(self, footer: Path) -> Self:
self._add_file_map(footer, "footer.html")
return self

class _RouteWithResources(BaseRoute):
def resource(self, resource: Path) -> Self:
self._add_file_map(resource)
return self
Expand All @@ -62,97 +39,22 @@ def resources(self, resources: List[Path]) -> Self:
self.resource(x)
return self

def size(self, size: PageSize) -> Self:
self._form_data.update(size.to_form())
return self

page_size = size

def margins(self, margins: Margin) -> Self:
self._form_data.update(margins.to_form())
return self

def prefer_css_page_size(self) -> Self:
self._form_data.update({"preferCssPageSize": "true"})
return self

def prefer_set_page_size(self) -> Self:
self._form_data.update({"preferCssPageSize": "false"})
return self

def background_graphics(self) -> Self:
self._form_data.update({"printBackground": "true"})
return self

def no_background_graphics(self) -> Self:
self._form_data.update({"printBackground": "false"})
return self

def hide_background(self) -> Self:
self._form_data.update({"omitBackground": "true"})
return self

def show_background(self) -> Self:
self._form_data.update({"omitBackground": "false"})
return self

def scale(self, scale: Union[int, float]) -> Self:
self._form_data.update({"scale": str(scale)})
return self

def render_wait(self, wait: Union[int, float]) -> Self:
self._form_data.update({"waitDelay": str(wait)})
return self

def render_expr(self, expr: str) -> Self:
self._form_data.update({"waitForExpression": expr})
return self

def media_type(self, media_type: EmulatedMediaType) -> Self:
self._form_data.update(media_type.to_form())
return self

def user_agent(self, agent: str) -> Self:
warn("The Gotenberg userAgent field is deprecated", DeprecationWarning, stacklevel=2)
self._form_data.update({"userAgent": agent})
return self

def headers(self, headers: Dict[str, str]) -> Self:
json_str = json.dumps(headers)
# TODO: Need to check this
self._form_data.update({"extraHttpHeaders": json_str})
return self

def fail_on_exceptions(self) -> Self:
self._form_data.update({"failOnConsoleExceptions": "true"})
return self

def dont_fail_on_exceptions(self) -> Self:
self._form_data.update({"failOnConsoleExceptions": "false"})
return self

def fail_on_status_codes(self, codes: Iterable[int]) -> Self:
if not codes:
logger.warning("fail_on_status_codes was given not codes, ignoring")
return self
codes_str = ",".join([str(x) for x in codes])
self._form_data.update({"failOnHttpStatusCodes": f"[{codes_str}]"})
return self


class _FileBasedRoute(ChromiumBaseRoute):
def index(self, index: Path) -> Self:
self._add_file_map(index, "index.html")
return self


class HtmlRoute(_FileBasedRoute):
class HtmlRoute(PagePropertiesMixin, HeaderFooterMixin, RenderControlMixin, _RouteWithResources, _FileBasedRoute):
"""
https://gotenberg.dev/docs/routes#html-file-into-pdf-route
"""


class UrlRoute(ChromiumBaseRoute):
class UrlRoute(
PagePropertiesMixin,
HeaderFooterMixin,
RenderControlMixin,
ConsoleExceptionMixin,
EmulatedMediaMixin,
CustomHTTPHeaderMixin,
BaseRoute,
):
"""
https://gotenberg.dev/docs/routes#url-into-pdf-route
"""
Expand All @@ -165,7 +67,7 @@ def _get_files(self) -> ForceMultipartDict:
return FORCE_MULTIPART


class MarkdownRoute(_FileBasedRoute):
class MarkdownRoute(PagePropertiesMixin, HeaderFooterMixin, _RouteWithResources, _FileBasedRoute):
"""
https://gotenberg.dev/docs/routes#markdown-files-into-pdf-route
"""
Expand All @@ -180,7 +82,15 @@ def markdown_files(self, markdown_files: List[Path]) -> Self:
return self


class ScreenshotRoute(ChromiumBaseRoute):
class ScreenshotRoute(
RenderControlMixin,
EmulatedMediaMixin,
CustomHTTPHeaderMixin,
InvalidStatusCodesMixin,
ConsoleExceptionMixin,
PerformanceModeMixin,
BaseRoute,
):
"""
https://gotenberg.dev/docs/routes#screenshots-route
"""
Expand Down Expand Up @@ -211,6 +121,23 @@ def optimize_size(self) -> Self:
return self


class ScreenshotRouteUrl(ScreenshotRoute):
def url(self, url: str) -> Self:
self._form_data.update({"url": url})
return self

def _get_files(self) -> ForceMultipartDict:
return FORCE_MULTIPART


class ScreenshotRouteHtml(_FileBasedRoute, _RouteWithResources, ScreenshotRoute):
pass


class ScreenshotRouteMarkdown(_FileBasedRoute, _RouteWithResources, ScreenshotRoute):
pass


class ChromiumApi(BaseApi):
_URL_CONVERT_ENDPOINT = "/forms/chromium/convert/url"
_HTML_CONVERT_ENDPOINT = "/forms/chromium/convert/html"
Expand All @@ -227,3 +154,12 @@ def url_to_pdf(self) -> UrlRoute:

def markdown_to_pdf(self) -> MarkdownRoute:
return MarkdownRoute(self._client, self._MARKDOWN_CONVERT_ENDPOINT)

def screenshot_url(self) -> ScreenshotRouteUrl:
return ScreenshotRouteUrl(self._client, self._SCREENSHOT_URL)

def screenshot_html(self) -> ScreenshotRouteHtml:
return ScreenshotRouteHtml(self._client, self._SCREENSHOT_HTML)

def screenshot_markdown(self) -> ScreenshotRouteMarkdown:
return ScreenshotRouteMarkdown(self._client, self._SCREENSHOT_MARK_DOWN)
Loading

0 comments on commit f3df0d1

Please sign in to comment.