c1611ac590f1da39586bcb707fa927736458b2de
[doldaconnect.git] / lib / python / dolcon / __init__.py
1 from dolmod import *
2 import os
3
4 def login(useauthless = True, **kw):
5     """A convenience function for loginasync.
6
7     This function will initiate an asynchronous login per the
8     loginasync command, and then run a select loop while waiting for
9     it to complete. It will return a tuple (res, reason), where res is
10     the result code, and reason is an explanatory text for any error.
11
12     res can be any of the following:
13      * success:  Login completed successfully
14      * nologin:  No authentication mechanism could be negotiated
15      * server:   An error occurred on the server
16      * user:     An error occurred in the library
17      * conv:     The password conversation mechanism failed
18      * authfail: The server refused the login (due to e.g. bad credentials)
19     """
20     result = [None]
21     def mycb(*v):
22         result[0] = v
23     loginasync(mycb, useauthless, **kw)
24     while result[0] is None:
25         select()
26     return result[0]
27
28 def mustconnect(host, revision = latest):
29     """A convenience function for connect.
30
31     This function will connect to the given host, perform a select
32     loop, and ensure that the server approves of the connection. If
33     any of these steps fail, an exception is raised. If successful,
34     the file descriptor for the server connection is returned.
35     """
36     fd = connect(host)
37     while True:
38         resp = getresp()
39         if resp is not None and resp.getcmd() == u".connect":
40             break
41         select()
42     if resp.getcode() != 201:
43         raise RuntimeError, resp.intresp()[0][0]
44     if not checkproto(resp, revision):
45         raise RuntimeError, resp
46     return fd
47
48 def cnl(host = None, useauthless = True, revision = latest, **kw):
49     """A convenience function for connect and loginasync.
50
51     This function will connect to the given server, or the server in
52     the environment variable $DCSERVER if none is given, or, if that
53     fails, localhost, and authenticate to the server. If any of the
54     steps fail, an exception is raised.
55     """
56     if host is None:
57         host = os.getenv("DCSERVER")
58     if host is None:
59         host = "localhost"
60     fd = mustconnect(host, revision)
61     err, reason = login(useauthless, **kw)
62     if err != "success":
63         raise RuntimeError, (err, reason)
64     return fd
65     
66 def ecmd(*args):
67     """A convenience function for qcmd.
68
69     This function will queue the given command, and then wait in a
70     select loop until the command has been carried out. The return
71     value is a Response object, corresponding to the reponse from the
72     server.
73     """
74     tag = qcmd(*args)
75     while True:
76         resp = getresp(tag)
77         if resp is not None:
78             break;
79         select()
80     return resp
81
82 def ecmda(code, *args):
83     """A convenience function for ecmd.
84
85     This function does essentially the same as ecmd, but it will also
86     check so that the response has the given numerical code. If not,
87     an exception is raised.
88     """
89     resp = ecmd(*args)
90     if resp.getcode() != code:
91         raise ValueError, resp.getcode()
92     return resp
93
94 def ecmds(*args):
95     """Another convenience function for ecmd.
96
97     Like ecmda, but will fail on all 5xx codes, and succeed on all
98     others.
99     """
100     resp = ecmd(*args)
101     if resp.getcode() >= 500 and resp.getcode() < 600:
102         raise ValueError, tuple(resp.extract()[0])
103     return resp
104
105 def getresps():
106     """A generator function which will iterate over all responses from
107     getresp.
108     """
109     while True:
110         resp = getresp()
111         if resp is None:
112             break
113         else:
114             yield resp