aboutsummaryrefslogtreecommitdiffstats
path: root/tagit/config/utils.py
blob: 948f53abbfab2dfd8dd8fcb973d306b668909c49 (plain)
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
"""Configuration system utilities.

Part of the tagit module.
A copy of the license is provided with the project.
Author: Matthias Baumgartner, 2022
"""
# standard imports
import typing

# tagit imports
from tagit.utils import import_all

# inner-module imports
from . import types

# exports
__all__: typing.Sequence[str] = (
    'key_starts_with',
    'schema_key_sort',
    'schema_to_rst',
    'subkey_of',
    'superkey_of',
    )


## code ##

def key_starts_with(key, prefix):
    """Return whether a config *key* starts with (is a subclass of) *prefix*."""
    return key[:len(prefix)] == prefix

def subkey_of(key, pool):
    """Return True if *key* is at a lower level than some key in *pool*.
    Example: session.debug is a subkey of session.
    """
    for sup in pool:
        if key_starts_with(key, sup):
            return True
    return False

def superkey_of(key, pool):
    """Return True if *key* is at a higher level than some key in *pool*.
    Example: session is a superkey of session.debug.
    """
    for sub in pool:
        if key_starts_with(sub, key):
            return True
    return False

def schema_key_sort(schema):
    """Return a comparison function for sorting schema config or title keys.
    To be used in sorted or sort as key function.

    >>> sorted(schema.keys(titles=True), key=schema_keys_sort(schema))

    """
    def cmp(key):
        """Return an unambiguous representation of schema config or title keys."""
        return ('.'.join(key[:-1]) + '..' + key[-1]) \
               if not schema.is_title(key) \
               else ('.'.join(key) + '..')

    return cmp

def schema_to_rst(schema, print_modules=False, no_import=False):
    """Creates a documentation page in ReST of the config schema.
    Calling this method with *no_import* set to False imports all
    tagit submodules.
    """
    # import all modules
    if not no_import:
        import tagit
        import_all(tagit, exclude={'.*\.external'})

    header = '=-^~"'

    known_sections = set()
    for key in sorted(schema.keys(titles=True), key=schema_key_sort(schema)):
        # print headings
        for idx, sec in enumerate(key):
            heading = '.'.join(key[:idx+1])
            if heading not in known_sections:
                print('')
                print(heading)
                print(header[idx] * len(heading))
                known_sections.add(heading)

        if schema.is_title(key):
            print(schema.get_title(key).description + '\n')

        else:
            print(schema[key].description + '\n')

            print(f':Format: {str(schema[key].type)} ({schema[key].example})')
            print(f':Default: {schema[key].default}')

            if isinstance(schema[key].type, types.Enum):
                print(f':Options: {schema[key].type.options}')

            if print_modules:
                modules = ', '.join(f'`{str(m)}`_' for m in schema[key].modules)
                print(f':Modules: {modules}')

## EOF ##