main()   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
dl 0
loc 17
rs 9.2
1
"""
2
Usage:
3
  rapidpro-pull --flow-runs --api-token=<api-token> [--address=<address>]
4
                            [--before=<before> --after=<after>]
5
                            [--with-contacts --with-flows]
6
                            [--cache=<database-url>]
7
  rapidpro-pull --flows --api-token=<api-token> [--address=<address>]
8
                            [--before=<before> --after=<after>]
9
                            [--uuid=<uuid> ...]
10
                            [--cache=<database-url>]
11
  rapidpro-pull --contacts --api-token=<api-token> [--address=<address>]
12
                            [--before=<before> --after=<after>]
13
                            [--uuid=<uuid> ...]
14
                            [--cache=<database-url>]
15
  rapidpro-pull --help
16
17
Options:
18
  --flow-runs                        download flow runs
19
  --flows                            download flows
20
  --contacts                         download contacts
21
  -a, --address=<address>            a RapidPro server [default: rapidpro.io]
22
  -t, --api-token=<api-token>        a RapidPro API token
23
24
  -h, --help                         display this help and exit
25
26
  --before=<before>                  download all older than ISO 8601 date/time
27
  --after=<after>                    download all newer than ISO 8601 date/time
28
29
  --uuid=<uuid>                      fetch objects matching UUID(s) (repeatable)
30
31
  --with-flows                       download associated flows, too
32
  --with-contacts                    download associated contacts, too
33
34
  --cache=<database-url>             use database-url as cache (store retrieved
35
                                     objects in cache; retrieve objects from
36
                                     cache instead of downloading from RapidPro
37
                                     when possible)
38
"""
39
from __future__ import print_function
40
import sys
41
import json
42
43
import temba_client.v1
44
import temba_client.exceptions
45
import docopt
46
47
import rapidpropull.download
48
49
__author__ = 'Tomasz J. Kotarba <[email protected]>'
50
__copyright__ = 'Copyright (c) 2016, Tomasz J. Kotarba. All rights reserved.'
51
__maintainer__ = 'Tomasz J. Kotarba'
52
__email__ = '[email protected]'
53
__version__ = 'rapidpro-pull 1.0.0'
54
55
56
class ArgumentProcessor(object):
57
    """
58
    A problem domain specific processor of command-line arguments for the
59
    rapidpro-pull program.  Sanitises arguments and can be queried to provide
60
    domain relevant information to clients (e.g. to instances of the
61
    DownloadTask class).
62
    It depends on a definition in a format compatible with docopt and specified
63
    in __doc__.
64
    """
65
    ENDPOINT_SELECTORS = [
66
        '--flow-runs',
67
        '--flows',
68
        '--contacts'
69
    ]
70
71
    def __init__(self, argv=None):
72
        """
73
        Initialise and interact with docopt to process arguments given in argv
74
        (or sys.argv if argv not provided).
75
        """
76
        if argv is None:
77
            argv = sys.argv[1:]
78
        self.arguments = docopt.docopt(__doc__, argv=argv, version=__version__)
79
80
    def get_address(self):
81
        """Return the address of a RapidPro service to be used."""
82
        return self.arguments['--address']
83
84
    def get_api_token(self):
85
        """Return a RapidPro API token provided by the user."""
86
        return self.arguments['--api-token']
87
88
    def get_endpoint_selector(self):
89
        """
90
        Return an endpoint selector (see: the RapidPro API). The endpoint
91
        selector determines which of the endpoints publicly exposed by the
92
        RapidPro web API will be used to pull data.
93
        """
94
        filtered = filter(lambda s: self.arguments.get(s),
95
                          self.ENDPOINT_SELECTORS)
96
        if filtered:
97
            return filtered[0]
98
        else:
99
            return None
100
101
    def get_endpoint_kwargs(self):
102
        """
103
        Return a dictionary of optional arguments the user has provided to
104
        modify a request to the user-selected endpoint.
105
        """
106
        kwargs = {}
107
        if self.arguments['--before'] is not None:
108
            kwargs['before'] = self.arguments['--before']
109
        if self.arguments['--after'] is not None:
110
            kwargs['after'] = self.arguments['--after']
111
        if self.arguments['--uuid']:
112
            kwargs['uuids'] = self.arguments['--uuid']
113
        return kwargs
114
115
    def get_selectors_of_requested_associations(self):
116
        """
117
        Return optional endpoint selector[s] to be used to query RapidPro for
118
        objects associated to the objects downloaded as a result of a request
119
        sent to the main endpoint selector.  Only the endpoint selectors
120
        explicitly requested by the user will be returned.
121
        """
122
        selectors = []
123
        if self.arguments['--with-contacts']:
124
            selectors.append('--contacts')
125
        if self.arguments['--with-flows']:
126
            selectors.append('--flows')
127
        return tuple(selectors)
128
129
    def get_cache_url(self):
130
        """Return a URL to a database to be used as cache (if provided)."""
131
        return self.arguments['--cache']
132
133
134
def main(argv=None):
135
    """
136
    This is an entry point used to automatically generate the rapidpro-pull
137
    command.
138
    """
139
    arguments = ArgumentProcessor(argv)
140
    downloader = rapidpropull.download.DownloadTask(arguments)
141
    try:
142
        downloader.download()
143
    except temba_client.exceptions.TembaConnectionError:
144
        print('Unable to connect to host', file=sys.stderr)
145
        sys.exit(1)
146
    except temba_client.exceptions.TembaTokenError:
147
        print('Authentication with provided token failed', file=sys.stderr)
148
        sys.exit(1)
149
    else:
150
        print(json.dumps(downloader.get_downloaded_json_structure()))
151