File: js_helpers.py

package info (click to toggle)
python-stone 3.3.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,956 kB
  • sloc: python: 21,786; objc: 498; sh: 29; makefile: 11
file content (127 lines) | stat: -rw-r--r-- 3,299 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
import json

from stone.backends.helpers import (
    fmt_camel,
    fmt_pascal,
)
from stone.ir import (
    Boolean,
    Bytes,
    Float32,
    Float64,
    Int32,
    Int64,
    List,
    String,
    Timestamp,
    UInt32,
    UInt64,
    Void,
    is_list_type,
    is_struct_type,
    is_user_defined_type,
)

_base_type_table = {
    Boolean: 'boolean',
    Bytes: 'string',
    Float32: 'number',
    Float64: 'number',
    Int32: 'number',
    Int64: 'number',
    List: 'Array',
    String: 'string',
    UInt32: 'number',
    UInt64: 'number',
    Timestamp: 'Timestamp',
    Void: 'void',
}


def fmt_obj(o):
    if isinstance(o, str):
        # Prioritize single-quoted strings per JS style guides.
        return repr(o).lstrip('u')
    else:
        return json.dumps(o, indent=2)


def fmt_error_type(data_type, wrap_error_in=''):
    """
    Converts the error type into a JSDoc type.
    """
    return '{}.<{}>'.format(
        (wrap_error_in if (wrap_error_in != '') else 'Error'),
        fmt_type(data_type)
    )


def fmt_type_name(data_type):
    """
    Returns the JSDoc name for the given data type.
    (Does not attempt to enumerate subtypes.)
    """
    if is_user_defined_type(data_type):
        return fmt_pascal('{}{}'.format(data_type.namespace.name, data_type.name))
    else:
        fmted_type = _base_type_table.get(data_type.__class__, 'Object')
        if is_list_type(data_type):
            fmted_type += '.<' + fmt_type(data_type.data_type) + '>'
        return fmted_type


def fmt_type(data_type):
    """
    Returns a JSDoc annotation for a data type.
    May contain a union of enumerated subtypes.
    """
    if is_struct_type(data_type) and data_type.has_enumerated_subtypes():
        possible_types = []
        possible_subtypes = data_type.get_all_subtypes_with_tags()
        for _, subtype in possible_subtypes:
            possible_types.append(fmt_type_name(subtype))
        if data_type.is_catch_all():
            possible_types.append(fmt_type_name(data_type))
        return fmt_jsdoc_union(possible_types)
    else:
        return fmt_type_name(data_type)


def fmt_jsdoc_union(type_strings):
    """
    Returns a JSDoc union of the given type strings.
    """
    return '(' + '|'.join(type_strings) + ')' if len(type_strings) > 1 else type_strings[0]


def fmt_func(name, version):
    if version == 1:
        return fmt_camel(name)
    return fmt_camel(name) + 'V{}'.format(version)


def fmt_url(namespace_name, route_name, route_version):
    if route_version != 1:
        return '{}/{}_v{}'.format(namespace_name, route_name, route_version)
    else:
        return '{}/{}'.format(namespace_name, route_name)


def fmt_var(name):
    return fmt_camel(name)


def check_route_name_conflict(namespace):
    """
    Check name conflicts among generated route definitions. Raise a runtime exception when a
    conflict is encountered.
    """

    route_by_name = {}
    for route in namespace.routes:
        route_name = fmt_func(route.name, version=route.version)
        if route_name in route_by_name:
            other_route = route_by_name[route_name]
            raise RuntimeError(
                'There is a name conflict between {!r} and {!r}'.format(other_route, route))
        route_by_name[route_name] = route