diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2015-09-29 22:07:24 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2015-09-29 22:07:24 +0300 |
commit | b071adbbfbfbd3b63e75818c0850d0fa1f8c8faa (patch) | |
tree | dbef1e8bbe658c0d7005e8133f3388a95c95adf5 | |
parent | 8388e2dced146e17e63b0166f2df684b4a2c70a3 (diff) | |
parent | 3fcf9ee5980319e25fa8d225ea3d46f67f503d5f (diff) | |
download | dico-b071adbbfbfbd3b63e75818c0850d0fa1f8c8faa.tar.gz dico-b071adbbfbfbd3b63e75818c0850d0fa1f8c8faa.tar.bz2 |
Merge branch 'master' into modinc
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | dico/connect.c | 6 | ||||
-rw-r--r-- | dicoweb/dicoclient/dicoclient.py | 36 | ||||
-rw-r--r-- | dicoweb/dicoclient/dicoshell.py | 179 | ||||
-rw-r--r-- | dicoweb/requirements.txt | 2 | ||||
-rw-r--r-- | dicoweb/templates/index.html | 1 | ||||
-rw-r--r-- | dicoweb/views.py | 31 |
7 files changed, 148 insertions, 111 deletions
@@ -1,7 +1,7 @@ -GNU Dico NEWS -- history of user-visible changes. 2014-09-26 +GNU Dico NEWS -- history of user-visible changes. 2014-09-28 Copyright (C) 2008-2010, 2012-2014 Sergey Poznyakoff See the end of file for copying conditions. Please send Dico bug reports to <bug-dico@gnu.org.ua> @@ -10,12 +10,14 @@ Version 2.2.90 (Git) * IPv6 support * Guile 2.x support * Implement info and description for gcide dictionary. +* Added manpages + Version 2.2, 2012-03-04 * Configuration changes ** load-module diff --git a/dico/connect.c b/dico/connect.c index 6362dd8..b77cdc6 100644 --- a/dico/connect.c +++ b/dico/connect.c @@ -273,15 +273,15 @@ int dict_connect(struct dict_connection **pconn, dico_url_t url) { int fd, rc, family; struct addrinfo hints, *res, *rp; dico_stream_t str; struct dict_connection *conn; + char const *port = url->port ? url->port : DICO_DICT_PORT_STR; - XDICO_DEBUG_F2(1, _("Connecting to %s:%s\n"), url->host, - url->port ? url->port : DICO_DICT_PORT_STR); + XDICO_DEBUG_F2(1, _("Connecting to %s:%s\n"), url->host, port); if (source_addr) { memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo(source_addr, NULL, &hints, &res); if (rc) { @@ -307,13 +307,13 @@ dict_connect(struct dict_connection **pconn, dico_url_t url) } else { fd = -1; } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; - rc = getaddrinfo(url->host, url->port, &hints, &res); + rc = getaddrinfo(url->host, port, &hints, &res); for (rp = res; rp; rp = rp->ai_next) { if (fd != -1 && family != rp->ai_family) { close(fd); fd = -1; } if (fd == -1) { diff --git a/dicoweb/dicoclient/dicoclient.py b/dicoweb/dicoclient/dicoclient.py index 2c93706..a929c30 100644 --- a/dicoweb/dicoclient/dicoclient.py +++ b/dicoweb/dicoclient/dicoclient.py @@ -1,8 +1,8 @@ # This file is part of GNU Dico. -# Copyright (C) 2008-2010, 2012, 2013 Wojciech Polak +# Copyright (C) 2008-2010, 2012, 2013, 2015 Wojciech Polak # # GNU Dico is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # @@ -16,16 +16,22 @@ import re import socket import base64 import quopri -__version__ = '1.0' +try: + from django.utils.six.moves import range, reduce +except ImportError: + from six.moves import range, reduce + +__version__ = '1.1' class DicoClient: + """GNU Dico client module written in Python (a part of GNU Dico software)""" host = None levenshtein_distance = 0 mime = False @@ -74,14 +80,14 @@ class DicoClient: self.__connected = False def option(self, name, *args): """Send the OPTION command.""" if self.__connected: self.__send('OPTION %s%s' % - (name, reduce(lambda x, y: str(x) + ' ' + str(y), - args, ''))) + (name, reduce(lambda x, y: str(x) + ' ' + str(y), + args, ''))) res = self.__read() code, msg = res[0].split(' ', 1) if int(code) == 250: if name.lower() == 'mime': self.mime = True return True @@ -110,13 +116,16 @@ class DicoClient: lines[:] = (buf.split('\r\n')) if lines[-1] == '': del lines[-1] del mimeinfo['content-transfer-encoding'] elif mimeinfo['content-transfer-encoding'].lower() == 'quoted-printable': buf = quopri.decodestring('\n'.join(lines)) - lines[:] = buf.split('\r\n') + try: + lines[:] = buf.split('\r\n') + except TypeError: + lines[:] = buf.decode('utf-8').split('\r\n') if lines[-1] == '': del lines[-1] del mimeinfo['content-transfer-encoding'] return mimeinfo def __get_rs(self, line): @@ -163,13 +172,17 @@ class DicoClient: buf.append(line) return buf def __send(self, command): if not self.__connected: raise DicoNotConnectedError('Not connected') - self.socket.send(command.encode('utf_8') + "\r\n") + cmd = command + "\r\n" + try: + self.socket.send(cmd) + except (UnicodeEncodeError, TypeError): + self.socket.send(cmd.encode('utf-8')) if self.transcript: self.__debug('C:%s' % command) def __send_client(self): if self.verbose: self.__debug('Sending client information') @@ -188,13 +201,13 @@ class DicoClient: self.__send('SHOW %s' % what) return self.__read() def __send_define(self, database, word): if self.verbose: self.__debug('Sending query for word "%s" in database "%s"' % - (word, database)) + (word, database)) self.__send('DEFINE "%s" "%s"' % (database, word)) return self.__read() def __send_match(self, database, strategy, word): if self.verbose: self.__debug('Sending query to match word "%s" in database "%s", using "%s"' @@ -270,14 +283,14 @@ class DicoClient: for j in src: lang_src[src.strip()] = True for j in dst: lang_dst[dst.strip()] = True return { 'desc': '\n'.join(dsc), - 'lang_src': lang_src.keys(), - 'lang_dst': lang_dst.keys(), + 'lang_src': list(lang_src.keys()), + 'lang_dst': list(lang_dst.keys()), } else: return {'error': code, 'msg': msg} def show_lang_pref(self): """Show server language preferences.""" @@ -384,18 +397,19 @@ class DicoClient: pass return s def __decode(self, encoded): for octc in (c for c in re.findall(r'\\(\d{3})', encoded)): encoded = encoded.replace(r'\%s' % octc, chr(int(octc, 8))) - return unicode(encoded, 'utf_8') + return encoded def __debug(self, msg): - print 'dico: Debug: %s' % msg + print('dico: Debug: %s' % msg) class DicoNotConnectedError (Exception): + def __init__(self, value): self.parameter = value def __str__(self): return repr(self.parameter) diff --git a/dicoweb/dicoclient/dicoshell.py b/dicoweb/dicoclient/dicoshell.py index b6493fa..8cbac3d 100644 --- a/dicoweb/dicoclient/dicoshell.py +++ b/dicoweb/dicoclient/dicoshell.py @@ -1,8 +1,8 @@ # This file is part of GNU Dico. -# Copyright (C) 2008-2010, 2012, 2013 Wojciech Polak +# Copyright (C) 2008-2010, 2012, 2013, 2015 Wojciech Polak # # GNU Dico is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # @@ -21,12 +21,17 @@ import atexit import getopt import readline import curses.ascii import socket import dicoclient +try: + from django.utils.six.moves import range, input +except ImportError: + from six.moves import range, input + class Shell: """Simple GNU Dico-Python Shell.""" prompt = 'dico> ' prefix = '.' @@ -51,107 +56,110 @@ class Shell: try: readline.read_history_file(histfile) except IOError: pass atexit.register(readline.write_history_file, histfile) - print '\nType ? for help summary\n' + print('\nType ? for help summary\n') while True: try: - input = raw_input(self.prompt).strip() - input = unicode(input, 'utf_8') + inputcmd = input(self.prompt).strip() except (EOFError, KeyboardInterrupt): - print + print() sys.exit() try: - self.parse(input) + self.parse(inputcmd) except socket.timeout: self.__error('socket timed out') except dicoclient.DicoNotConnectedError: try: self.dc.open() dict = self.dc.show_databases() self.last_databases = dict['databases'] dict = self.dc.show_strategies() self.last_strategies = dict['strategies'] - self.parse(input) - except socket.error, (errno, strerror): + self.parse(inputcmd) + except socket.error as serror: + (errno, strerror) = serror.args self.__error(strerror) - def parse(self, input): - if len(input) < 1: + def parse(self, inputcmd): + if len(inputcmd) < 1: return - if input[0] == self.prefix: - self.parse_command(input[1:]) - elif input == '?': + + if inputcmd[0] == self.prefix: + self.parse_command(inputcmd[1:]) + + elif inputcmd == '?': self.print_help() - elif re.match(r'^[0-9]+$', input): + + elif re.match(r'^[0-9]+$', inputcmd): try: - match = self.last_matches[int(input)] + match = self.last_matches[int(inputcmd)] dict = self.dc.define(match[0], match[1]) if 'count' in dict: for d in dict['definitions']: - print 'From %s, %s:' % (d['db'], d['db_fullname']. - encode('utf_8')) - print d['desc'] + print('From %s, %s:' % (d['db'], d['db_fullname'])) + print(d['desc']) elif 'error' in dict: - print dict['msg'] + print(dict['msg']) except IndexError: self.__error('No previous match') - elif input[0] == '/': - if len(input) > 1: - dict = self.dc.match(self.database, self.strategy, input[1:]) + + elif inputcmd[0] == '/': + if len(inputcmd) > 1: + dict = self.dc.match(self.database, self.strategy, inputcmd[1:]) if 'matches' in dict: self.last_matches = [] lmi = 0 for db in dict['matches']: - print 'From %s, %s:' % (db, self.__lookup_db(db). - encode('utf_8')) + print('From %s, %s:' % (db, self.__lookup_db(db))) for term in dict['matches'][db]: - print '%4d) "%s"' % (lmi, term.encode('utf_8')) + print('%4d) "%s"' % (lmi, term)) self.last_matches.append([db, term]) lmi = lmi + 1 elif 'error' in dict: - print dict['msg'] + print(dict['msg']) else: if len(self.last_matches) > 0: m = {} lmi = 0 for i, db in enumerate(self.last_matches): if not db[0] in m: m[db[0]] = [] m[db[0]].append(self.last_matches[i][1]) for db in m: - print 'From %s, %s:' % (db, self.__lookup_db(db)) + print('From %s, %s:' % (db, self.__lookup_db(db))) for term in m[db]: - print '%4d) "%s"' % (lmi, term) + print('%4d) "%s"' % (lmi, term)) lmi = lmi + 1 else: self.__error('No previous match') - elif input[0] == '!': - if re.match(r'^![0-9]+$', input): - number = int(input[1:]) + + elif inputcmd[0] == '!': + if re.match(r'^![0-9]+$', inputcmd): + number = int(inputcmd[1:]) readline.insert_text(readline.get_history_item(number)) readline.redisplay() + else: - dict = self.dc.define(self.database, input) + dict = self.dc.define(self.database, inputcmd) if 'count' in dict: for d in dict['definitions']: - print 'From %s, %s:' % (d['db'], d['db_fullname']. - encode('utf_8')) - print d['desc'] + print('From %s, %s:' % (d['db'], d['db_fullname'])) + print(d['desc']) elif 'error' in dict: - print dict['msg'] + print(dict['msg']) - def parse_command(self, input): - input = input.split(' ', 1) - cmd = input[0] + def parse_command(self, inputcmd): + inputcmd = inputcmd.split(' ', 1) + cmd = inputcmd[0] args = None - if len(input) == 2: - args = input[1] + if len(inputcmd) == 2: + args = inputcmd[1] if cmd == 'open': try: if args != None: args = args.split(' ', 1) if len(args) == 2: @@ -161,86 +169,87 @@ class Shell: else: self.dc.open() dict = self.dc.show_databases() self.last_databases = dict['databases'] dict = self.dc.show_strategies() self.last_strategies = dict['strategies'] - except socket.error, (errno, strerror): + except socket.error as serror: + (errno, strerror) = serror.args self.__error(strerror) elif cmd == 'close': self.dc.close() elif cmd == 'database': if args != None: self.database = args else: - print self.database + print(self.database) elif cmd == 'strategy': if args != None: self.strategy = args else: - print self.strategy + print(self.strategy) elif cmd == 'distance': if args != None: self.dc.levenshtein_distance = int(args) else: if self.dc.levenshtein_distance: - print 'Configured Levenshtein distance: %u' % \ - self.dc.levenshtein_distance + print('Configured Levenshtein distance: %u' % \ + self.dc.levenshtein_distance) else: - print 'No distance configured' + print('No distance configured') elif cmd == 'ls': dict = self.dc.show_strategies() self.last_strategies = dict['strategies'] if len(self.last_strategies): for i in self.last_strategies: - print '%s "%s"' % (i[0], i[1]) + print('%s "%s"' % (i[0], i[1])) elif cmd == 'ld': dict = self.dc.show_databases() self.last_databases = dict['databases'] if len(self.last_databases): for i in self.last_databases: - print '%s "%s"' % (i[0], i[1]) + print('%s "%s"' % (i[0], i[1])) elif cmd == 'mime': - print self.dc.option('MIME') + print(self.dc.option('MIME')) elif cmd == 'server': dict = self.dc.show_server() if 'desc' in dict: - print dict['desc'] + print(dict['desc']) elif 'error' in dict: self.__error(dict['error'] + ' ' + dict['msg']) elif cmd == 'info': if args != None: dict = self.dc.show_info(args) if 'desc' in dict: - print dict['desc'] + print(dict['desc']) elif 'error' in dict: self.__error(dict['error'] + ' ' + dict['msg']) elif cmd == 'history': hl = int(readline.get_current_history_length()) - for i in xrange(0, hl): - print '%4d) %s' % (i, readline.get_history_item(i)) + for i in range(0, hl): + print('%4d) %s' % (i, readline.get_history_item(i))) elif cmd == 'help': self.print_help() elif cmd == 'transcript': if args != None: if args in ('yes', 'on', 'true'): self.dc.transcript = True elif args in ('no', 'off', 'false'): self.dc.transcript = False else: self.__error('Expected boolean value') else: if self.dc.transcript: - print 'transcript is on' + print('transcript is on') else: - print 'transcript is off' + print('transcript is off') elif cmd == 'verbose': if args != None: self.dc.verbose = args else: - print self.dc.verbose + print(self.dc.verbose) elif cmd == 'prompt': if args != None: self.prompt = args else: self.__error('not enough arguments') elif cmd == 'prefix': @@ -261,63 +270,63 @@ class Shell: for d in self.last_databases: if d[0] == db: return d[1] return '' def __error(self, msg): - print 'dico: Error: %s' % msg + print('dico: Error: %s' % msg) def print_version(self): - print 'GNU Dico (Python Edition) ' + dicoclient.__version__ + print('GNU Dico (Python Edition) ' + dicoclient.__version__) def print_warranty(self): self.print_version() - print """Copyright (C) 2008-2010, 2012, 2013 Wojciech Polak + print("""Copyright (C) 2008-2010, 2012, 2013 Wojciech Polak GNU Dico is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Dico 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 General Public License for more details. You should have received a copy of the GNU General Public License - along with GNU Dico. If not, see <http://www.gnu.org/licenses/>.""" + along with GNU Dico. If not, see <http://www.gnu.org/licenses/>.""") def print_help(self): - print 'WORD Define WORD.' - print '/WORD Match WORD.' - print '/ Redisplay previous matches.' - print 'NUMBER Define NUMBERth match.' - print '!NUMBER Edit NUMBERth previous command.' - print - print self.prefix + 'open [HOST [PORT]] Connect to a DICT server.' - print self.prefix + 'close Close the connection.' - print self.prefix + 'database [NAME] Set or display current database name.' - print self.prefix + 'strategy [NAME] Set or display current strategy.' - print self.prefix + 'distance [NUM] Set or query Levenshtein distance (server-dependent).' - print self.prefix + 'ls List available matching strategies' - print self.prefix + 'ld List all accessible databases' - print self.prefix + 'info [DB] Display the information about the database.' - print self.prefix + 'prefix [CHAR] Set or display command prefix.' - print self.prefix + 'transcript [BOOL] Set or display session transcript mode.' - print self.prefix + 'verbose [NUMBER] Set or display verbosity level.' - print self.prefix + 'prompt STRING Change command line prompt.' - print self.prefix + 'history Display command history.' - print self.prefix + 'help Display this help text.' - print self.prefix + 'version Print program version.' - print self.prefix + 'warranty Print copyright statement.' - print self.prefix + 'quit Quit the shell.' + print('WORD Define WORD.') + print('/WORD Match WORD.') + print('/ Redisplay previous matches.') + print('NUMBER Define NUMBERth match.') + print('!NUMBER Edit NUMBERth previous command.') + print() + print(self.prefix + 'open [HOST [PORT]] Connect to a DICT server.') + print(self.prefix + 'close Close the connection.') + print(self.prefix + 'database [NAME] Set or display current database name.') + print(self.prefix + 'strategy [NAME] Set or display current strategy.') + print(self.prefix + 'distance [NUM] Set or query Levenshtein distance (server-dependent).') + print(self.prefix + 'ls List available matching strategies') + print(self.prefix + 'ld List all accessible databases') + print(self.prefix + 'info [DB] Display the information about the database.') + print(self.prefix + 'prefix [CHAR] Set or display command prefix.') + print(self.prefix + 'transcript [BOOL] Set or display session transcript mode.') + print(self.prefix + 'verbose [NUMBER] Set or display verbosity level.') + print(self.prefix + 'prompt STRING Change command line prompt.') + print(self.prefix + 'history Display command history.') + print(self.prefix + 'help Display this help text.') + print(self.prefix + 'version Print program version.') + print(self.prefix + 'warranty Print copyright statement.') + print(self.prefix + 'quit Quit the shell.') if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], 'h:', ['host=']) except getopt.GetoptError: - print '\nusage: %s [-h, --host=hostname]' % (sys.argv[0]) + print('\nusage: %s [-h, --host=hostname]' % (sys.argv[0])) sys.exit(0) shell = Shell(opts, args) shell.print_version() shell.run() diff --git a/dicoweb/requirements.txt b/dicoweb/requirements.txt index 47b7897..022e93f 100644 --- a/dicoweb/requirements.txt +++ b/dicoweb/requirements.txt @@ -1,2 +1,2 @@ -Django >=1.4.5 +Django >=1.7 git+git://git.gnu.org.ua/wit.git#egg=wit diff --git a/dicoweb/templates/index.html b/dicoweb/templates/index.html index 5ebb46a..7f35e3f 100644 --- a/dicoweb/templates/index.html +++ b/dicoweb/templates/index.html @@ -1,9 +1,10 @@ {% extends 'base.html' %} {% load i18n %} {% load dictlookup %} +{% load firstof from future %} {% block search %} <div id="searchform"> <form id="form" method="get" action=""> <table> diff --git a/dicoweb/views.py b/dicoweb/views.py index 6cf5349..14cf124 100644 --- a/dicoweb/views.py +++ b/dicoweb/views.py @@ -1,8 +1,8 @@ # This file is part of GNU Dico. -# Copyright (C) 2008-2010, 2012, 2013 Wojciech Polak +# Copyright (C) 2008-2010, 2012-2015 Wojciech Polak # # GNU Dico is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # @@ -18,16 +18,21 @@ import re import hashlib import socket from django.conf import settings from django.core import urlresolvers from django.core.cache import cache from django.shortcuts import render_to_response +from django.utils.encoding import force_bytes from django.utils.translation import ugettext as _ -import dicoclient -from wit import wiki2html +from dicoclient import dicoclient +try: + from wit import wiki2html +except ImportError: + wiki2html = None + print('WARNING: The wit module is not installed.') def index(request): page = { 'robots': 'index', } @@ -53,14 +58,14 @@ def index(request): server = settings.DICT_SERVERS[0] request.session['server'] = server if len(settings.DICT_SERVERS) > 1: selects['sv'] = HtmlOptions(settings.DICT_SERVERS, server) - key = hashlib.md5('%s/%s' % (sid, server.encode('ascii', - 'backslashreplace'))) + key = hashlib.md5(force_bytes( + '%s/%s' % (sid, server.encode('ascii', 'backslashreplace')))) sid = key.hexdigest() type = 'search' if 'define' in request.GET: type = 'define' else: @@ -107,15 +112,16 @@ def index(request): if 'q' in request.GET and q != '': langkey = '*' if database == '*': langkey = ','.join(accept_lang) - key = hashlib.md5('%s:%d/%s/%s/%s/%s/%s' % - (server, port, langkey, type, database, strategy, - q.encode('ascii', 'backslashreplace'))) + key = hashlib.md5(force_bytes( + '%s:%d/%s/%s/%s/%s/%s' % (server, port, langkey, type, + database, strategy, + q.encode('ascii', 'backslashreplace')))) key = key.hexdigest() result = cache.get('dicoweb/' + key) if not result: try: dc = dicoclient.DicoClient() @@ -168,13 +174,14 @@ def index(request): page['robots'] = 'noindex,nofollow' if 'definitions' in result: rx1 = re.compile('{+(.*?)}+', re.DOTALL) for df in result['definitions']: if 'content-type' in df \ - and df['content-type'].startswith('text/x-wiki'): + and df['content-type'].startswith('text/x-wiki') \ + and wiki2html: lang = df['x-wiki-language'] \ if 'x-wiki-language' in df else 'en' wikiparser = wiki2html.HtmlWiktionaryMarkup(text=df['desc'], html_base='?q=', lang=lang) wikiparser.parse() @@ -193,13 +200,13 @@ def index(request): def opensearch(request): url_query = request.build_absolute_uri(urlresolvers.reverse('index')) url_media = request.build_absolute_uri(settings.MEDIA_URL) return render_to_response('opensearch.xml', {'url_query': url_query, 'url_media': url_media}, - mimetype='application/xml') + content_type='application/xml') def __subs1(match): s = re.sub(r' +', ' ', match.group(1)) return '<a href="?q=%s" title="Search for %s">%s</a>' \ % (s.replace('\n', ''), s.replace('\n', ''), s) @@ -213,12 +220,16 @@ class HtmlOptions: def html(self): buf = [] for opt in self.lst: if len(opt) == 2: if not opt[1]: opt[1] = opt[0] + try: + opt[1] = opt[1].decode('utf-8') + except: + pass if opt[0] == self.value: buf.append('<option value="%s" selected="selected">%s</option>' % ( opt[0], opt[1])) else: buf.append('<option value="%s">%s</option>' % (opt[0], opt[1])) |