add "is_available" function to all version control modules
[translate_toolkit.git] / services / lookupservice.py
blob7b38f00e8f5457d6d57ebe1c73d3b90d632393a8
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # Copyright 2006 Zuza Software Foundation
5 #
6 # This file is part of translate.
8 # translate is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 """Server program to serve messages over XML-RPC
25 As this is implemented using the base classes (see storage.base), the
26 work is minimal to use this with any storage format that is implemented
27 using the base classes. Strictly speaking, only an init... function needs
28 to be registered."""
30 from translate.convert import convert
31 from translate.storage import tbx
32 from translate.storage import tmx
33 from translate.storage import po
34 from translate.storage import csvl10n
35 from translate.search import match
36 from translate.misc.multistring import multistring
38 from SimpleXMLRPCServer import SimpleXMLRPCServer
39 from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
41 class lookupRequestHandler(SimpleXMLRPCRequestHandler):
42 """Sets up the requested file for parsing"""
43 #TODO: Parse request to see if tbx/tmx is requested,
44 # or perhaps the url can specify the file to be queried
46 class lookupServer(SimpleXMLRPCServer):
47 def __init__(self, addr, storage):
48 """Loads the initial tbx file from the given filename"""
49 SimpleXMLRPCServer.__init__(self, addr, requestHandler=lookupRequestHandler, logRequests=1)
50 self.storage = storage
51 self.storage.makeindex()
52 self.matcher = match.matcher(storage)
53 print "Performing lookup from %d units" % len(storage.units)
54 print "Translation memory using %d units" % len(self.matcher.candidates.units)
56 def _dispatch(self, method, params):
57 try:
58 # All public methods must be prefixed with 'public_' so no
59 # internal methods are callable.
60 func = getattr(self, 'public_' + method)
61 except AttributeError:
62 raise Exception('no method called "%s"' % method)
63 else:
64 try:
65 return func(*params)
66 except Exception, e:
67 print str(e)
68 return ""
70 def internal_lookup(self, message):
71 """Could perhaps include some intelligence in future, like case trying with different casing, etc."""
72 message = message.strip()
73 if message == "":
74 return None
75 if not isinstance(message, unicode):
76 message = unicode(message)
77 try:
78 unit = self.storage.findunit(message)
79 except Exception:
80 return None
81 return unit
83 def public_lookup(self, message):
84 """Returns the source string of whatever was found. Keep in mind that this might not be what you want."""
85 unit = self.internal_lookup(message)
86 if unit:
87 return str(unit)
88 else:
89 return ""
91 def public_translate(self, message):
92 """Translates the message from the storage and returns a plain string"""
93 unit = self.internal_lookup(message)
94 if unit and unit.target:
95 return unit.target
96 else:
97 return ""
99 def public_matches(self, message, max_candidates=15, min_similarity=50):
100 """Returns matches from the storage with the associated similarity"""
101 self.matcher.setparameters(max_candidates=max_candidates, min_similarity=min_similarity)
102 if not isinstance(message, unicode):
103 message = unicode(message)
104 candidates = self.matcher.matches(message)
105 clean_candidates = []
106 for unit in candidates:
107 score = unit.getnotes()
108 original = unit.source
109 translation = unit.target
111 # We might have gotten multistrings, so just convert them for now
112 if isinstance(original, multistring):
113 original = unicode(original)
114 if isinstance(translation, multistring):
115 translation = unicode(translation)
116 clean_candidates += [(score, original, translation)]
117 return clean_candidates
119 class lookupOptionParser(convert.ConvertOptionParser):
120 """Parser that calls instantiates the lookupServer"""
121 def run(self):
122 """parses arguments and instantiates the server"""
123 (options, args) = self.parse_args()
124 options.inputformats = self.inputformats
125 self.usepsyco(options)
126 inputbase, inputext = self.splitinputext(options.input)
127 asdf, storagebuilder = self.outputoptions[inputext, None]
128 storage = storagebuilder(open(options.input))
129 server = lookupServer((options.address, int(options.port)), storage)
130 try:
131 server.serve_forever()
132 except:
133 server.server_close()
135 def inittbx(inputfile, columnorder=None):
136 return tbx.tbxfile(inputfile)
138 def inittmx(inputfile, columnorder=None):
139 return tmx.tmxfile(inputfile)
141 def initpo(inputfile, columnorder=None):
142 return po.pofile(inputfile)
144 def initcsv(inputfile, columnorder=None):
145 return csvl10n.csvfile(inputfile, columnorder)
147 def main():
148 formats = {"tbx": (None, inittbx), "tmx": (None, inittmx), "po": (None, initpo), "csv": (None, initcsv)}
149 parser = lookupOptionParser(formats, usepots=False, description=__doc__)
150 parser.add_option("-a", "--address", dest="address", default="localhost",
151 help="the host to bind to")
152 parser.add_option("-p", "--port", dest="port", default=1234,
153 help="the port to listen on")
154 parser.add_option("-l", "--language", dest="targetlanguage", default=None,
155 help="set target language code", metavar="LANG")
156 parser.add_option("", "--source-language", dest="sourcelanguage", default='en',
157 help="set source language code", metavar="LANG")
158 parser.remove_option("--output")
159 parser.remove_option("--exclude")
160 parser.passthrough.append("sourcelanguage")
161 parser.passthrough.append("targetlanguage")
162 parser.add_option("", "--columnorder", dest="columnorder", default=None,
163 help="specify the order and position of columns for CSV (comment,source,target)")
164 parser.passthrough.append("columnorder")
165 parser.run()
167 if __name__ == '__main__':
168 main()