File: config.py

package info (click to toggle)
pandoc-include 1.4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 448 kB
  • sloc: xml: 488; python: 456; ansic: 52; makefile: 17; cpp: 5
file content (132 lines) | stat: -rw-r--r-- 3,937 bytes parent folder | download
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import re
import ast
import os
import json

import panflute as pf


CONFIG_KEYS = {
    "startLine": int,
    "endLine": int,
    "snippetStart": str,
    "snippetEnd": str,
    "xslt": str,
    "includeSnippetDelimiters": bool,
    "incrementSection": int,
    "dedent": int,
    "format": str,
    "raw": str
}

# The temp filename should be fixed
# in order to be found by subprocesses
TEMP_FILE = '.temp.pandoc-include'

def parseBoolValue(val):
    # use 1 or 0 (otherwise default to true if not empty)
    return val and val != "0"

# Keys for env config
class Env:
    # Throw error when included file not found
    NotFoundError = False
    # Pandoc binary for parsing included files
    PandocBin = None

    def parse():
        Env.NotFoundError = parseBoolValue(os.environ.get("PANDOC_INCLUDE_NOT_FOUND_ERROR", "0"))
        Env.PandocBin = os.environ.get("PANDOC_BIN") or None


def parseConfig(text):
    regex = re.compile(
        r'''
            (?P<key>\w+)=      # Key consists of only alphanumerics
            (?P<quote>["'`]?)  # Optional quote character.
            (?P<value>.*?)     # Value is a non greedy match
            (?P=quote)         # Closing quote equals the first.
            ($|,)              # Entry ends with comma or end of string
        ''',
        re.VERBOSE
    )

    config = {}
    for match in regex.finditer(text):
        key = match.group('key')
        if key in CONFIG_KEYS:
            # Include the original quotes
            raw_value = f"{match.group('quote')}{match.group('value')}{match.group('quote')}"
            try:
                value = ast.literal_eval(raw_value)
            except:
                raise ValueError(f"Invalid config: {key}={raw_value}")
            if not isinstance(value, CONFIG_KEYS[key]):
                raise ValueError(f"Invalid value type: {key}={raw_value}")
            config[key] = value

        else:
            pf.debug("[Warn] Invalid config key: " + key)

    return config


defaultOptions = {
    "include-entry": {
        "path": ".",
        "entered": False
    },
    "current-path": ".",
    "include-resources": ".",
    "process-path": None,
    "include-order": "natural",
    "rewrite-path": True,
    "pandoc-options": ["--filter=pandoc-include"]
}

def parseOptions(doc):
    if os.path.isfile(TEMP_FILE):
        with open(TEMP_FILE, 'r') as f:
            # merge with default options to prevent missing keys
            options = { **defaultOptions, **json.load(f) }
    else:
        # entry file (default values)
        options = defaultOptions.copy()

    # include entry
    include_entry = doc.get_metadata('include-entry')
    if include_entry is not None:
        if not options["include-entry"]["entered"]:
            options['include-entry'] = dict(path=include_entry, entered=False)
        else:
            pf.debug("[WARN] include-entry specified multiple times")

    # pandoc options
    pandoc_options = doc.get_metadata('pandoc-options')
    if pandoc_options is not None:
        # Replace em-dash to double dashes in smart typography
        for i in range(len(pandoc_options)):
            pandoc_options[i] = pandoc_options[i].replace('\u2013', '--')
        options['pandoc-options'] = pandoc_options

    # order of included files (natural, alphabetical, shell_default)
    include_order = doc.get_metadata("include-order")
    if include_order is not None:
        options["include-order"] = include_order

    # rewrite path
    rewrite_path = doc.get_metadata("rewrite-path")
    if rewrite_path is not None:
        options["rewrite-path"] = rewrite_path

    # resource path
    resource_path = doc.get_metadata("include-resources")
    if resource_path is not None:
        options["include-resources"] = resource_path

    # process path
    process_path = os.getcwd()
    if options["process-path"] is None:
        options["process-path"] = process_path

    return options