File: dictlib.py

package info (click to toggle)
serpento 0.3.6
  • links: PTS
  • area: main
  • in suites: woody
  • size: 292 kB
  • ctags: 381
  • sloc: python: 1,644; ansic: 666; perl: 157; sh: 116; makefile: 72
file content (184 lines) | stat: -rw-r--r-- 5,635 bytes parent folder | download | duplicates (3)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/bin/env python
#
#  Source:    dictlib.py
#  Author:    Tor Andersson <mazirian@dsek.lth.se>
#  Date:    2000-03-24
#  Version:    0.0.1 alpha
#
# ---------------------------------------------------------------------------
#
#  Copyright (C) 2000 Tor Andersson
#
#  This library is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2.1 of the License, or (at your option) any later version.
#  
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  Lesser General Public License for more details.
#  
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# ---------------------------------------------------------------------------
#
#  object fields:
#    dict.error = string with last error message
#    dict.banner = banner from dict server
#
#  Throws DICTError when fatal error is encountered (50z and 4xy errors)
#

import string, socket

class DICT:
    """Implementation of DICT protocol as seen in RFC 2229"""

    # ------------------------------------------------------------------
    # private stuff

    errors = {
        '500': 'Syntax error, command not recognized',
        '501': 'Syntax error, illegal parameters',
        '502': 'Command not implemented',
        '503': 'Command parameter not implemented',
        '420': 'Server temporarily unavailable',
        '421': 'Server shutting down at operator request',
    }

    # open session
    def __init__(self, host, port=2628):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((host, port))
        self.file = self.sock.makefile("r")
        self.banner = self.rline('220')
        
    # send command
    def send(self, cmd):
        self.sock.send(cmd)
        self.sock.send("\r\n")
    
    # check for fatal errors (server down, client protocol errors)...
    def chk(self, resp):
        if DICT.errors.has_key(resp[0:3]):
            raise "DICTError", DICT.errors[resp[0:3]]
    
    # receive text block
    def rtext(self):
        lines = []
        while 1:
            line = string.rstrip(self.file.readline())
            if line == '.':
                break
            lines.append(line)
        return lines
    
    # receive one line, and check expected return code if specified
    def rline(self, expected=''):
        line = string.rstrip(self.file.readline())
        self.chk(line)
        if expected and line[0:3] != expected:
            raise "DICTError", "Protocol mismatch..."
        return line
    
    # receive line + text block from show command
    def rshow(self, code):
        resp = self.rline()
        if resp[0:3] != code:
            self.error = resp
            return None
        text = self.rtext()
        return text
        
    # close session
    def close(self):
        self.file.close()
        self.sock.close()

    # ------------------------------------------------------------------
    # public protocol stuff
    
    def client(self, cli):
        "Notifies server of which client is used. Return nothing"
        self.send("CLIENT %s" % cli)
        self.rline('250')
    
    def define(self, db, word):
        "Find definition. Return [ [match, [lines]], ... ]"
        quotedword = string.replace(word, "'", "\\'")
        self.send('DEFINE %s "%s"' % (db, quotedword))
        resp = self.rline()
        if resp[0:3] != '150':
            self.error = resp
            return None
        ndefs = int(string.split(resp)[1])
        defs = []
        for n in range(ndefs):
            match = self.rline('151')
            text = self.rtext()
            defs.append( (match, text) )
        self.rline('250')
        return defs
    
    def match(self, db, strat, word):
        "Find matches using strategy. Return [match, ...]"
        quotedword = string.replace(word, "'", "\\'")
        self.send('MATCH %s %s "%s"' % (db, strat, quotedword))
        resp = self.rline()
        if resp[0:3] != '152':
            self.error = resp
            return None
        text = self.rtext()
        self.rline('250')
        return text
    
    def show_db(self):
        "Get list of databases"
        self.send("SHOW DB")
        text = self.rshow('110')
        self.rline('250')
        return text
    
    def show_strat(self):
        "Get list of strategies"
        self.send("SHOW STAT")
        text = self.rshow('111')
        self.rline('250')
        return text
        
    def show_info(self, db):
        "Get info about a database"
        self.send("SHOW %s" % db)
        text = self.rshow('112')
        self.rline('250')
        return text
        
    def show_server(self):
        "Get info about server"
        self.send("SHOW SERVER" % db)
        text = self.rshow('114')
        self.rline('250')
        return text
    
    def status(self):
        "Get server/connection status"
        self.send("STATUS")
        return self.rline('210')
    
    def help(self):
        "Get server help message"
        self.send("HELP")
        text = self.rshow('113')
        self.rline('250')
        return text
    
    def quit(self):
        "Quit connection and close socket"
        self.send("QUIT")
        self.rline('221')
        self.close()