Skip to content

Commit

Permalink
Switch to Click
Browse files Browse the repository at this point in the history
Click is far more popular and maintained than docopt.
  • Loading branch information
jmaupetit committed Jan 22, 2024
1 parent 6c21560 commit 265d1b2
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 92 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ $ md2pdf README.md README.pdf
Optionally, you may load an external style (restricted to CSS2):

```bash
$ md2pdf --css tests/resources/input.css README.md README.pdf
$ md2pdf --css tests/assets/input.css README.md README.pdf
```

### As a library
Expand Down
38 changes: 4 additions & 34 deletions md2pdf/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,8 @@
Options:
--css=STYLE.CSS
"""
import os
import sys
from importlib.metadata import version
from . import cli

from docopt import docopt

from md2pdf.core import md2pdf


def main(argv=None):
"""md2pdf main script."""
__version__ = version("md2pdf")

# Parse command line arguments
arguments = docopt(
__doc__,
version=f"md2pdf {__version__}"
)

# Paths
md_file_path = arguments.get('INPUT.MD')
pdf_file_path = arguments.get('OUTPUT.PDF')
css_file_path = arguments.get('--css', None)
base_url = os.getcwd()

md2pdf(pdf_file_path,
md_file_path=md_file_path,
css_file_path=css_file_path,
base_url=base_url)

return 0


if __name__ == '__main__':
sys.exit(main())
if __name__ == "__main__":
"""Run the CLI."""
cli.cli()
22 changes: 22 additions & 0 deletions md2pdf/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""md2pdf CLI."""
from importlib.metadata import version
from pathlib import Path

import click

from md2pdf.core import md2pdf


@click.command(name="md2pdf")
@click.argument("md_file_path", type=click.Path(exists=True))
@click.argument("pdf_file_path", type=click.Path())
@click.option("--css", "css_file_path", type=click.Path(exists=True))
@click.version_option(version=version("md2pdf"))
def cli(md_file_path, pdf_file_path, css_file_path):
"""md2pdf command line tool."""
md2pdf(
pdf_file_path,
md_file_path=md_file_path,
css_file_path=css_file_path,
base_url=Path.cwd(),
)
2 changes: 1 addition & 1 deletion md2pdf/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def md2pdf(pdf_file_path, md_content=None, md_file_path=None,
raise ValidationError('Input markdown seems empty')

# Weasyprint HTML object
html = HTML(string=raw_html, base_url=base_url)
html = HTML(string=raw_html, base_url=str(base_url))

# Get styles
css = []
Expand Down
62 changes: 33 additions & 29 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ exclude = [
]

[tool.poetry.scripts]
md2pdf = "md2pdf.__main__:main"
md2pdf = "md2pdf.__main__:cli.cli"

[tool.poetry.dependencies]
python = "^3.8"
weasyprint = "^60.2"
docopt = "^0.6.2"
markdown2 = "^2.4.12"
click = "^8.1.7"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.4"
Expand Down
File renamed without changes.
File renamed without changes.
7 changes: 4 additions & 3 deletions tests/defaults.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""md2pdf tests defaults."""
from pathlib import Path

# Test files paths
INPUT_CSS = 'tests/resources/input.css'
INPUT_MD = 'tests/resources/input.md'
OUTPUT_PDF = 'tests/resources/output.pdf'
INPUT_CSS = Path("tests/assets/input.css")
INPUT_MD = Path("tests/assets/input.md")
OUTPUT_PDF = Path("tests/assets/output.pdf")
55 changes: 33 additions & 22 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from os.path import exists
from subprocess import run

from click.testing import CliRunner

from md2pdf.cli import cli
from .defaults import INPUT_CSS, INPUT_MD, OUTPUT_PDF


Expand All @@ -15,47 +18,55 @@ def setup_function(function):

def test_print_usage_when_no_args():
"""Print usage when no arguments are passed."""
process = run(["md2pdf"], capture_output=True, check=False)
expected = b"Usage: md2pdf [options] INPUT.MD OUTPUT.PDF"
assert expected in process.stderr
runner = CliRunner()
result = runner.invoke(cli)
expected = "Usage: md2pdf [OPTIONS] MD_FILE_PATH PDF_FILE_PATH"
assert result.exit_code == 2
assert expected in result.output


def test_print_usage_when_partial_args():
"""Print usage when required arguments are missing."""
process = run(["md2pdf", "input.md"], capture_output=True, check=False)
expected = b"Usage: md2pdf [options] INPUT.MD OUTPUT.PDF"
assert expected in process.stderr
runner = CliRunner()
result = runner.invoke(cli, ["input.md"])
expected = "Usage: md2pdf [OPTIONS] MD_FILE_PATH PDF_FILE_PATH"
assert result.exit_code == 2
assert expected in result.output


def test_raise_IOError_when_markdown_input_file_does_not_exists():
"""Raise an I/O error when markdown input file does not exist."""
process = run(
["md2pdf", "input.md", "output.pdf"], capture_output=True, check=False
runner = CliRunner()
result = runner.invoke(cli, ["input.md", "output.pdf"])
expected = (
"Error: Invalid value for 'MD_FILE_PATH': Path 'input.md' does not exist."
)
expected = b"[Errno 2] No such file or directory: 'input.md'"
assert expected in process.stderr
assert result.exit_code == 2
assert expected in result.output


def test_raise_IOError_when_stylesheet_does_not_exists():
"""Raise an I/O error when CSS input file does not exist."""
process = run(
["md2pdf", "--css=styles.css", INPUT_MD, OUTPUT_PDF],
capture_output=True,
check=False,
runner = CliRunner()
result = runner.invoke(cli, ["--css=styles.css", str(INPUT_MD), str(OUTPUT_PDF)])
expected = (
"Error: Invalid value for '--css': Path 'styles.css' does not exist."
)
expected = b"[Errno 2] No such file or directory: 'styles.css'"
assert expected in process.stderr
assert result.exit_code == 2
assert expected in result.output


def test_generate_pdf_from_markdown_source_file():
"""Generate a PDF from a markdown file."""
assert not exists(OUTPUT_PDF)
run(["md2pdf", INPUT_MD, OUTPUT_PDF], check=False)
assert exists(OUTPUT_PDF)
assert not OUTPUT_PDF.exists()
runner = CliRunner()
runner.invoke(cli, [str(INPUT_MD), str(OUTPUT_PDF)])
assert OUTPUT_PDF.exists()


def test_generate_pdf_from_markdown_source_file_and_stylesheet():
"""Generate a PDF from a markdown and a CSS file."""
assert not exists(OUTPUT_PDF)
run(["md2pdf", f"--css={INPUT_CSS}", INPUT_MD, OUTPUT_PDF], check=False)
assert exists(OUTPUT_PDF)
assert not OUTPUT_PDF.exists()
runner = CliRunner()
runner.invoke(cli, [f"--css={INPUT_CSS}", str(INPUT_MD), str(OUTPUT_PDF)])
assert OUTPUT_PDF.exists()

0 comments on commit 265d1b2

Please sign in to comment.