about summary refs log tree commit diff
path: root/universe/ac_types/parse.py
blob: 872f3f0c3fcce02a35619dfffc0e610816735a52 (plain) (blame)
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
133
134
135
136
137
138
import re
import string
from test_utils import simple_assert


def if_empty(x, parser):
    """If the field is empty, use `x`, otherwise, call `parser` on it."""
    def fn(y):
        if y == "":
            return x
        else:
            return parser(y)

    return fn


# nullable :: Parser -> Parser
def nullable(parser):
    def fn(x):
        if x == "":
            return None
        else:
            return parser(x)

    return fn


def required(column_name, parser):
    def fn(x):
        if x == "":
            raise Exception(
                "\"{}\" is a required field and cannot be empty".format(
                    column_name))
        else:
            return parser(x)

    return fn


def apply_parser(parser, row):
    """Calls each value in `parser` on the corresponding field in the
    dictionary, `row`."""
    result = {}
    for k, fn in parser.items():
        result[k] = fn(row[k])
    return result


def raise_parse_error(x, expected):
    """Raises a generic `Exception` when `x` is not a member of the `expected`
    set."""
    raise Exception("\"{}\" is none of the following: \"{}\"".format(
        x, ", ".join(expected)))


def as_hours(x):
    match = re.search(r'(\d+) hours', x)
    if match:
        try:
            return int(match[1])
        except:
            raise Exception('Failed to parse {} as an int'.format(match[1]))
    else:
        raise Exception('Failed to parse {} as hours'.format(x))


actual = as_hours('24 hours')
expected = 24
simple_assert(actual, expected, name='as_hours')


def as_mapping(mapping):
    def fn(x):
        if mapping[x]:
            return mapping[x]
        else:
            raise_parse_error(x, set(mapping.keys()))

    return fn


# as_yes_no :: String -> Boolean
def as_yes_no(x):
    """Attempt to parse `x`, a Yes or No value, into a boolean."""
    if x == "Yes":
        return True
    elif x == "No":
        return False
    else:
        raise_parse_error(x, {"Yes", "No"})


# as_data_source_type :: String -> String
def as_data_source_type(x):
    """Attempt to parse `x` as the Data Source Type column, which is an enum
    defined in the go/consult-types-authwf-auto-consult sheet."""
    acceptable = {"Hard-Code", "N/A", "Atlas", "Form"}
    if x not in acceptable:
        raise_parse_error(x, acceptable)
    return x


# as_type :: String -> String
def as_type(x):
    """Attempt to parse `x` as the Type column, which is an enum defined in the
    go/consult-types-authwf-auto-consult sheet."""
    acceptable = {
        "Parent Routing FRD", "Consult Parameter", "Consult Routing FRD",
        "Input", "Return Routing FRD"
    }
    if x not in acceptable:
        raise_parse_error(x, acceptable)
    return x


def as_int(x):
    return int(x)


def as_union_type(x):
    if " or " in x:
        return [string.trim_surrounding('"', x) for x in x.split(" or ")]
    else:
        return [x]


simple_assert(as_union_type('Non-Union'), ['Non-Union'], name='as_union_type')

simple_assert(as_union_type(
    '"Germany" or "Netherlands" or "Spain" or "Check Republic" or "United Kingdom"'
), ['Germany', 'Netherlands', 'Spain', 'Check Republic', 'United Kingdom'],
              name='as_union_type')


# identity :: a -> a
def identity(x):
    """Returns `x` unchanged."""
    return x