Skip to content

Commit

Permalink
More documentation and links to GT documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
stumpylog committed Oct 14, 2023
1 parent d3684ab commit 8762505
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 50 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ from gotenberg_client.options import PdfAFormat

with GotenbergClient("http://localhost:3000") as client:
with client.chromium.html_to_pdf() as route:
response = route.index("my-index.html").resource("image.png").resource("style.css").pdf_format(PdfAFormat.A1a).run()
response = route.index("my-index.html").resources(["image.png", "style.css"]).pdf_format(PdfAFormat.A1a).run()
Path("my-index.pdf").write_bytes(response.content)
```

Expand Down
25 changes: 1 addition & 24 deletions src/gotenberg_client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# SPDX-License-Identifier: MPL-2.0
import logging
from contextlib import ExitStack
from importlib.util import find_spec
from pathlib import Path
from types import TracebackType
from typing import Dict
Expand All @@ -15,6 +14,7 @@
from httpx._types import RequestFiles

from gotenberg_client.options import PdfAFormat
from gotenberg_client.utils import guess_mime_type

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -119,26 +119,3 @@ class BaseApi:

def __init__(self, client: Client) -> None:
self._client = client


def guess_mime_type_stdlib(url: Path) -> Optional[str]:
"""
Uses the standard library to guess a mimetype
"""
import mimetypes

mime_type, _ = mimetypes.guess_type(url)
return mime_type


def guess_mime_type_magic(url: Path) -> Optional[str]:
"""
Uses libmagic to guess the mimetype
"""
import magic # type: ignore

return magic.from_file(url, mime=True) # type: ignore


# Use the best option
guess_mime_type = guess_mime_type_magic if find_spec("magic") is not None else guess_mime_type_stdlib
16 changes: 15 additions & 1 deletion src/gotenberg_client/convert/chromium.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def __bool__(self) -> bool:


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

def header(self, header: Path) -> "ChromiumBaseRoute":
self._add_file_map(header, "header.html")
return self
Expand Down Expand Up @@ -140,10 +144,16 @@ def index(self, index: Path) -> "_FileBasedRoute":


class HtmlRoute(_FileBasedRoute):
pass
"""
https://gotenberg.dev/docs/routes#html-file-into-pdf-route
"""


class UrlRoute(ChromiumBaseRoute):
"""
https://gotenberg.dev/docs/routes#url-into-pdf-route
"""

def url(self, url: str) -> "UrlRoute":
self._form_data["url"] = url
return self
Expand All @@ -153,6 +163,10 @@ def get_files(self) -> ForceMultipartDict:


class MarkdownRoute(_FileBasedRoute):
"""
https://gotenberg.dev/docs/routes#markdown-files-into-pdf-route
"""

def markdown_file(self, markdown_file: Path) -> "MarkdownRoute":
self._add_file_map(markdown_file)
return self
Expand Down
31 changes: 13 additions & 18 deletions src/gotenberg_client/convert/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
#
# SPDX-License-Identifier: MPL-2.0
import logging
from functools import lru_cache
from typing import Dict
from typing import Optional
from typing import Union

from gotenberg_client.base import BaseRoute
from gotenberg_client.options import PageOrientation
Expand All @@ -14,22 +10,21 @@


class ConvertBaseRoute(BaseRoute):
def orient(self, orient: PageOrientation) -> "BaseRoute":
"""
All 3 convert routes provide control over orientation and page ranges
"""

def orient(self, orient: PageOrientation) -> "ConvertBaseRoute":
"""
Sets the page orientation, either Landscape or portrait
"""
self._form_data.update(orient.to_form())
return self

def page_ranges(self, ranges: str) -> "BaseRoute":
def page_ranges(self, ranges: str) -> "ConvertBaseRoute":
"""
Sets the page range string, allowing either some range or just a
few pages
"""
self._form_data.update({"nativePageRanges": ranges})
return self


@lru_cache # type: ignore
def optional_to_form(value: Optional[Union[bool, int, float, str]], name: str) -> Dict[str, str]:
"""
Quick helper to convert an optional type into a form data field
with the given name or no changes if the value is None
"""
if value is None:
return {}
else:
return {name: str(value).lower()}
20 changes: 20 additions & 0 deletions src/gotenberg_client/convert/libre_office.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,37 @@


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

def convert(self, file_path: Path) -> "LibreOfficeConvertRoute":
"""
Adds a single file to be converted to PDF. Can be called multiple times,
resulting in a ZIP of the PDFs, unless merged
"""
self._add_file_map(file_path)
return self

def convert_files(self, file_paths: List[Path]) -> "LibreOfficeConvertRoute":
"""
Adds all provided files for conversion
"""
for x in file_paths:
self.convert(x)
return self

def merge(self) -> "LibreOfficeConvertRoute":
"""
Merge the resulting PDFs into one
"""
self._form_data.update({"merge": "true"})
return self

def no_merge(self) -> "LibreOfficeConvertRoute":
"""
Don't merge the resulting PDFs
"""
self._form_data.update({"merge": "false"})
return self

Expand All @@ -31,4 +48,7 @@ class LibreOfficeApi(BaseApi):
_CONVERT_ENDPOINT = "/forms/libreoffice/convert"

def to_pdf(self) -> LibreOfficeConvertRoute:
"""
Returns the LibreOffice conversion route
"""
return LibreOfficeConvertRoute(self._client, self._CONVERT_ENDPOINT)
7 changes: 7 additions & 0 deletions src/gotenberg_client/convert/pdfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@


class PdfAConvertRoute(ConvertBaseRoute):
"""
https://gotenberg.dev/docs/routes#convert-into-pdfa-route
"""

def convert(self, file_path: Path) -> "PdfAConvertRoute":
"""
Convert a single PDF into the provided PDF/A format
"""
self._add_file_map(file_path)
return self

Expand Down
6 changes: 3 additions & 3 deletions src/gotenberg_client/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import Optional
from typing import Union

from gotenberg_client.convert.common import optional_to_form
from gotenberg_client.utils import optional_to_form


@enum.unique
Expand All @@ -30,12 +30,12 @@ def to_form(self) -> Dict[str, str]:
@enum.unique
class PageOrientation(enum.Enum):
Landscape = enum.auto()
Potrait = enum.auto()
Portrait = enum.auto()

def to_form(self) -> Dict[str, str]:
if self.value == PageOrientation.Landscape.value:
return {"landscape": "true"}
elif self.value == PageOrientation.Potrait.value:
elif self.value == PageOrientation.Portrait.value:
return {"landscape": "false"}
else: # pragma: no cover
raise NotImplementedError(self.value)
Expand Down
42 changes: 42 additions & 0 deletions src/gotenberg_client/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-FileCopyrightText: 2023-present Trenton H <[email protected]>
#
# SPDX-License-Identifier: MPL-2.0
from importlib.util import find_spec
from pathlib import Path
from typing import Dict
from typing import Optional
from typing import Union


def optional_to_form(value: Optional[Union[bool, int, float, str]], name: str) -> Dict[str, str]:
"""
Quick helper to convert an optional type into a form data field
with the given name or no changes if the value is None
"""
if value is None:
return {}
else:
return {name: str(value).lower()}


def guess_mime_type_stdlib(url: Path) -> Optional[str]:
"""
Uses the standard library to guess a mimetype
"""
import mimetypes

mime_type, _ = mimetypes.guess_type(url)
return mime_type


def guess_mime_type_magic(url: Path) -> Optional[str]:
"""
Uses libmagic to guess the mimetype
"""
import magic # type: ignore

return magic.from_file(url, mime=True) # type: ignore


# Use the best option
guess_mime_type = guess_mime_type_magic if find_spec("magic") is not None else guess_mime_type_stdlib
2 changes: 1 addition & 1 deletion tests/test_convert_chromium_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def test_convert_render_control(self, client: GotenbergClient, httpx_mock: HTTPX

@pytest.mark.parametrize(
("orientation"),
[PageOrientation.Landscape, PageOrientation.Potrait],
[PageOrientation.Landscape, PageOrientation.Portrait],
)
def test_convert_orientation(
self,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_convert_libre_office.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import pytest
from httpx import codes

from gotenberg_client.base import guess_mime_type_stdlib
from gotenberg_client.client import GotenbergClient
from gotenberg_client.options import PdfAFormat
from gotenberg_client.utils import guess_mime_type_stdlib
from tests.conftest import SAMPLE_DIR
from tests.conftest import SAVE_DIR
from tests.conftest import SAVE_OUTPUTS
Expand Down Expand Up @@ -86,7 +86,7 @@ def test_libre_office_convert_multiples_format_merged(self, client: GotenbergCli
(SAVE_DIR / "test_libre_office_convert_multiples_format.zip").write_bytes(resp.content)

def test_libre_office_convert_std_lib_mime(self, client: GotenbergClient):
with patch("gotenberg_client.base.guess_mime_type") as mocked_guess_mime_type:
with patch("gotenberg_client.utils.guess_mime_type") as mocked_guess_mime_type:
mocked_guess_mime_type.side_effect = guess_mime_type_stdlib
with client.libre_office.to_pdf() as route:
resp = route.convert_files([SAMPLE_DIR / "sample.docx", SAMPLE_DIR / "sample.odt"]).no_merge().run()
Expand Down

0 comments on commit 8762505

Please sign in to comment.