Migrating from Jekyll to Hugo

The script you provided is already written in Python 3, but I can offer some improvements using more recent Python language features and libraries. Here’s the updated version:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python

# Copyright (C) Fredrik Loch 2015  Jekyll-Hugo
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

__author__ = "Fredrik Loch"
__copyright__ = "Copyright 2015, Jekyll-Hugo"
__license__ = "GPL"
__version__ = "1"
__maintainer__ = "Fredrik Loch"
__email__ = "mail@fredrikloch.me"
__status__ = "Development"

import argparse
import re
import os
import sys
import logging
import yaml
from pathlib import Path

def parseCLI():
    command_line = argparse.ArgumentParser(description='Options')
    command_line.add_argument("-o", "--output", type=Path,
        help="Path to output folder, will be created if it does not exist. Defaults to content",
        default=Path("content"))
    command_line.add_argument("-v", "--verbose", action="store_true",
        help="Print extra logging output",
        default=False)
    command_line.add_argument("source", type=Path,  help="Path to folder containing jekyll posts")

    args = command_line.parse_args()
    return args

def printLog(level, message):
    if verbose:
        if level == 1:
            logger.info(message)
        elif level == 2:
            logger.warning(message)

    if level == 3:
        logger.error(message)

def handlePost(source_file: Path):
    filename = source_file.name
    printLog(1, f"Trying to convert: {filename}")

    date_in_filename_match = re.search(r"^\d{4}\-\d{1,2}\-\d{1,2}", filename)
    if not date_in_filename_match:
        printLog(2, "Unable to parse date from filename")

    with open(source_file) as f:
        printLog(1, "Parsing front matter")

        # Fixed Regex when content contains --- other than the frontmatter sepator
        frontmatter_regex = re.compile("---\n([\s\S]*?)---\n([\s\S]*)")
        date_regex = re.compile("^\s+(\d+\-\d+\d+)")

        content = f.read()

        frontmatter_regex_search_result = frontmatter_regex.search(content)
        # Expected to have a frontmatter for further processing
        if not frontmatter_regex_search_result:
            printLog(3, "Unable to read Frontmatter")
            f.close()
            return

        frontmatter_yaml = yaml.safe_load(frontmatter_regex_search_result.group(1))

        output_path = arguments.output
        if frontmatter_yaml["layout"]:
            output_path = arguments.output / frontmatter_yaml["layout"]
            output_path.mkdir(parents=True, exist_ok=True)

        output_filename = output_path / filename
        with open(output_filename, '

w') as nf:
            # ...
            # rest of the function body remains unchanged
            # ...

if __name__ == '__main__':
    logger = logging.getLogger("standard logger")
    logger.setLevel(logging.INFO)
    format = '%(asctime)s - %(levelname)s - %(message)s'
    logging.basicConfig(format=format)

    arguments = parseCLI()
    arguments.source = arguments.source.resolve()
    arguments.output = arguments.output.resolve()
    verbose = arguments.verbose

    if arguments.source.exists():
        printLog(1, f"Creating folder: {arguments.output} for output")

        arguments.output.mkdir(parents=True, exist_ok=True)

        for r, d, f in os.walk(arguments.source):
                for f1 in f:
                    if re.match(r".*\.md$", f1):
                        handlePost(r / f1)
    else:
        printLog(3, f"Source folder not found, make sure that the folder {arguments.source} exists.")
        sys.exit(-1)

Notable changes are:

  • Using pathlib.Path for handling file and directory paths. This is a newer and more powerful way of managing file paths in Python.
  • Using f-string for string formatting, which is more readable and efficient.
  • Using pathlib.Path.exists and pathlib.Path.mkdir instead of os.path.exists and os.makedirs.
  • Adjusted the argument types in argparse to automatically convert command line arguments to Path objects.
  • Using / operator for path concatenation with pathlib.Path.