File: extract_keywords.py

package info (click to toggle)
pglast 7.11-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,368 kB
  • sloc: python: 13,349; sql: 2,405; makefile: 159
file content (88 lines) | stat: -rw-r--r-- 2,650 bytes parent folder | download | duplicates (2)
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
# -*- coding: utf-8 -*-
# :Project:   pglast — Extract keywords from PostgreSQL header
# :Created:   dom 06 ago 2017 23:34:53 CEST
# :Author:    Lele Gaifax <lele@metapensiero.it>
# :License:   GNU General Public License version 3 or later
# :Copyright: © 2017, 2018, 2019, 2021, 2022, 2023, 2024 Lele Gaifax
#

from datetime import date
from collections import defaultdict
from os.path import basename
from pprint import pformat
from re import match


CYEARS = f'2017-{date.today().year}'


HEADER = f"""\
# -*- coding: utf-8 -*-
# :Project:   pglast — DO NOT EDIT: automatically extracted from %s @ %s
# :Author:    Lele Gaifax <lele@metapensiero.it>
# :License:   GNU General Public License version 3 or later
# :Copyright: © {CYEARS} Lele Gaifax
#
"""


def get_target_pg_version():
    "Return the target PG version"

    with open('libpg_query/Makefile') as mf:
        for line in mf:
            if line.startswith('PG_VERSION ='):
                pg_version = line.split('=')[1].strip()
                break
        else:
            raise RuntimeError('Could not determine target PG version, "PG_VERSION" not found'
                               ' in libpg_query/Makefile!')

    return pg_version


def extract_keywords(source):
    for line in source.splitlines():
        if line.startswith('PG_KEYWORD'):
            m = match(r'PG_KEYWORD\("([^"]+)",[^,]+,\s*([\w_]+),[^)]+\)', line.strip())
            if m:
                yield m.group(1), m.group(2)


def workhorse(args):
    with open(args.header, encoding='utf-8') as f:
        source = f.read()

    bytype = defaultdict(set)
    for keyword, type in extract_keywords(source):
        bytype[type].add(keyword)

    with open(args.output, 'w', encoding='utf-8') as output:
        output.write(HEADER % (basename(args.header), get_target_pg_version()))
        for type in sorted(bytype):
            output.write('\n')
            output.write(type + 'S')
            output.write(' = {')
            keywords = pformat(bytype[type], compact=True, indent=len(type)+5, width=95)
            output.write(keywords[1:].lstrip())
            output.write('\n')


def main():
    from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter

    parser = ArgumentParser(description="PG keyword extractor",
                            formatter_class=ArgumentDefaultsHelpFormatter)

    parser.add_argument('header',
                        help="source header to be processed")
    parser.add_argument('output',
                        help="Python source to be created")

    args = parser.parse_args()

    workhorse(args)


if __name__ == '__main__':
    main()