aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-04-27 10:11:30 +0200
committerSergey Poznyakoff <gray@gnu.org>2021-04-27 10:11:30 +0200
commit24891d83e0882ffd3b5ebf94bf52dde91a1469b0 (patch)
treee4959ce279f9e1c342e9d67152a311ff7877fba6
parentd9fb47332dc056952f73823ac113f5057fba2531 (diff)
downloadweb-24891d83e0882ffd3b5ebf94bf52dde91a1469b0.tar.gz
web-24891d83e0882ffd3b5ebf94bf52dde91a1469b0.tar.bz2
Upgrade using dicoweb from GNU dico 2.11
-rw-r--r--INSTALL130
-rw-r--r--dicoclient/__init__.py4
-rw-r--r--dicoclient/dicoclient.py417
-rw-r--r--dicoclient/dicoshell.py303
-rw-r--r--dicoclient/setup.py2
-rw-r--r--dummy_translations.py2
-rw-r--r--manage.py15
-rw-r--r--settings-sample.py182
-rw-r--r--static/dicoweb.css90
-rw-r--r--static/dicoweb.js20
-rw-r--r--templates/base.html2
-rw-r--r--templates/download.html6
-rw-r--r--templates/opensearch.xml6
-rw-r--r--templatetags/dictlookup.py11
-rw-r--r--templatetags/withsetting.py2
-rw-r--r--urls.py24
-rw-r--r--views.py305
17 files changed, 858 insertions, 663 deletions
diff --git a/INSTALL b/INSTALL
index ee9a98b..3a59d38 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,79 +1,117 @@
GNU Dico - Dicoweb INSTALL
-Copyright (C) 2008-2010, 2012 Wojciech Polak
+See end of file for copying conditions.
* Dicoweb requirements
======================
-- Django 1.0+ -- a Python Web framework (http://www.djangoproject.com/)
-- Wit -- a wiki translator distributed within GNU Dico.
- (http://puszcza.gnu.org.ua/projects/wit/)
+- Django -- a Python Web framework (http://www.djangoproject.com/)
+- wikitrans -- a wiki translator (https://pypi.org/project/wikitrans/)
+- python-memcached -- Pure python memcached client
+ (https://pypi.org/project/python-memcached)
* Installation instructions
===========================
-Rename 'settings-sample.py' to 'settings.py' and edit your
+The instructions below assume dicoweb sources are located in
+/var/www/dicoweb.
+
+1. Create the virtual environment directory in /var/www/dicoweb.
+Assuming the directory will be named 'venv':
+
+ $ cd /var/www/dicoweb
+ $ virtualenv venv
+
+2. Activate the environment:
+
+ $ . venv/bin/activate
+
+3. Install the prerequisites
+
+ $ pip install -r requirements.txt
+
+4. Deactivate the environment
+
+ $ deactivate
+
+5. Rename 'settings-sample.py' to 'settings.py' and edit your
local Dicoweb site configuration.
+6. Enable the following Apache modules: mod_alias, mod_env, mod_wsgi.
+
+The exact instructions depend on your Apache configuration layout. In
+general, they boil down to adding the following three statements to
+the Apache configuration:
+
+ LoadModule alias_module modules/mod_alias.so
+ LoadModule env_module modules/mod_env.so
+ LoadModule wsgi_module modules/mod_wsgi.so
+
+7. Configure Apache virtual host. The minimal configuration is as
+follows:
+
+ <VirtualHost *:80>
+ ServerName dict.example.org
+ DocumentRoot /var/www/dicoweb
+
+ # Ensure proper encoding (for Python 3)
+ SetEnv LC_ALL en_US.utf8
+
+ # Configure virtual environment.
+ # (If not using virtual environment, omit the WSGIDaemonProcess and
+ # WSGIProcessGroup statements).
+
+ # Make sure to edit the statement below to match to the actual
+ # path to the site-packages directory.
+ WSGIDaemonProcess dicoweb python-path=/var/www/dicoweb/venv/lib/python3.5/site-packages
+ WSGIProcessGroup dicoweb
+
+ # Start up the module.
+ WSGIScriptAlias / /var/www/dicoweb/wsgi.py
+ # Provide access to the static files.
+ Alias /static /var/www/dicoweb/static
+ <Directory "/var/www/dicoweb/">
+ AllowOverride All
+ Options None
+ Require all granted
+ </Directory>
+ </VirtualHost>
+
+For a general discussion of deployment of the Django applications,
+please see https://docs.djangoproject.com/en/dev/howto/deployment.
** The development/test server
------------------------------
-Change the current working directory into the `dicoweb' directory
+To start the stand-alone development server, change to /var/www/dicoweb
and run the command `python manage.py runserver'. You will see
the following output:
Validating models...
0 errors found.
- Django version 1.0, using settings 'dicoweb.settings'
+ Django version 1.11.5, using settings 'dicoweb.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
-** Production server with mod_wsgi
-----------------------------------
+Use your web browser to query the displayed URL.
-Apache configuration:
+* Copyright information:
- LoadModule wsgi_module modules/mod_wsgi.so
- WSGIScriptAlias / /usr/local/django/dicoweb/dicoweb.wsgi
- Alias /static "/usr/local/django/dicoweb/static"
-
-More detailed information is available at:
-http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
-
-** Production server with mod_python
-------------------------------------
-
-Apache configuration:
-
- LoadModule python_module modules/mod_python.so
- <Location "/">
- SetHandler python-program
- PythonHandler django.core.handlers.modpython
- PythonPath "sys.path + ['/usr/local/django', '/usr/local/django/dicoweb']"
- SetEnv DJANGO_SETTINGS_MODULE dicoweb.settings
- PythonInterpreter dicoweb
- PythonDebug Off
- </Location>
-
- <Location "/static">
- SetHandler None
- </Location>
- <Location "/favicon.ico">
- SetHandler None
- </Location>
-
- <Directory "/usr/local/django/dicoweb/">
- AllowOverride All
- Options None
- Order allow,deny
- Allow from all
- </Directory>
+Copyright (C) 2008-2018 Wojciech Polak
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and this permission notice are preserved,
+ thus giving the recipient permission to redistribute in turn.
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
Local Variables:
mode: outline
-paragraph-separate: "[ ]*$"
+paragraph-separate: "[ ]*$"
version-control: never
End:
diff --git a/dicoclient/__init__.py b/dicoclient/__init__.py
index a300cea..9fcbe2b 100644
--- a/dicoclient/__init__.py
+++ b/dicoclient/__init__.py
@@ -1,5 +1,5 @@
# This file is part of GNU Dico.
-# Copyright (C) 2008-2009, 2012 Wojciech Polak
+# Copyright (C) 2008-2009, 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
@@ -16,4 +16,4 @@
__all__ = ["dicoclient"]
-from dicoclient import *
+from .dicoclient import *
diff --git a/dicoclient/dicoclient.py b/dicoclient/dicoclient.py
index 76336c2..f49c582 100644
--- a/dicoclient/dicoclient.py
+++ b/dicoclient/dicoclient.py
@@ -1,5 +1,6 @@
+# -*- coding: utf-8 -*-
# This file is part of GNU Dico.
-# Copyright (C) 2008-2010, 2012 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
@@ -18,15 +19,21 @@ import re
import socket
import base64
import quopri
-import hashlib
-__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;
+ host = None
levenshtein_distance = 0
mime = False
@@ -35,345 +42,336 @@ class DicoClient:
transcript = False
__connected = False
- def __init__ (self, host=None):
+ def __init__(self, host=None):
if host != None:
- self.host = host;
+ self.host = host
- def __del__ (self):
+ def __del__(self):
if self.__connected:
- self.socket.close ()
+ self.socket.close()
- def open (self, host=None, port=2628, cred=None):
+ def open(self, host=None, port=2628):
"""Open the connection to the DICT server."""
if host != None:
self.host = host
if self.verbose:
- self.__debug ('Connecting to %s:%d' % (self.host, port))
- socket.setdefaulttimeout (int (self.timeout))
- self.socket = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
- self.socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.socket.connect ((self.host, port))
+ self.__debug('Connecting to %s:%d' % (self.host, port))
+ socket.setdefaulttimeout(int(self.timeout))
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.socket.connect((self.host, port))
self.__connected = True
- self.fd = self.socket.makefile ();
+ self.fd = self.socket.makefile()
- self.server_banner = self.__read ()[0]
- capas, msgid = re.search ('<(.*)> (<.*>)$',
- self.server_banner).groups ()
- self.server_capas = capas.split ('.')
+ self.server_banner = self.__read()[0]
+ capas, msgid = re.search('<(.*)> (<.*>)$',
+ self.server_banner).groups()
+ self.server_capas = capas.split('.')
self.server_msgid = msgid
- self.__send_client ()
- self.__read ()
- if cred and 'user' in cred and 'password' in cred:
- self.auth(cred['user'], cred['password'])
-
- def auth (self, user, passwd):
- if self.__connected and 'auth' in self.server_capas:
- if self.verbose:
- self.__debug ('Authenticating on %s' % (self.host))
- m = hashlib.md5()
- m.update(self.server_msgid)
- m.update(passwd)
- self.__send ('AUTH %s %s' % (user, m.hexdigest()))
- res = self.__read ()
- code, msg = res[0].split (' ', 1)
- if int (code) == 230:
- return True
- return False
-
- def close (self):
+ self.__send_client()
+ self.__read()
+
+ def close(self):
"""Close the connection."""
if self.__connected:
- self.__send_quit ()
- self.__read ()
- self.socket.close ()
+ self.__send_quit()
+ self.__read()
+ self.socket.close()
self.__connected = False
- def option (self, name, *args):
+ 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, '')))
- res = self.__read ()
- code, msg = res[0].split (' ', 1)
- if int (code) == 250:
- if name.lower () == 'mime':
+ self.__send('OPTION %s%s' %
+ (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
return False
- def __get_mime (self, lines):
+ def __get_mime(self, lines):
cnt = 0
mimeinfo = {}
- firstline = lines[0].lower ()
+ firstline = lines[0].lower()
if firstline.find ('content-type:') != -1 or \
- firstline.find ('content-transfer-encoding:') != -1:
+ firstline.find('content-transfer-encoding:') != -1:
cnt += 1
for line in lines:
if line == '':
break
- t = line.split (':', 1)
- mimeinfo[t[0].lower ()] = t[1].strip ()
+ t = line.split(':', 1)
+ mimeinfo[t[0].lower()] = t[1].strip()
cnt += 1
- for i in range (0, cnt):
- lines.pop (0)
+ for i in range(0, cnt):
+ lines.pop(0)
else:
- lines.pop (0)
+ lines.pop(0)
if 'content-transfer-encoding' in mimeinfo:
- if mimeinfo['content-transfer-encoding'].lower () == 'base64':
- buf = base64.decodestring ('\n'.join (lines))
- lines[:] = (buf.split ('\r\n'))
- if lines[-1] == '': del lines[-1]
+ if mimeinfo['content-transfer-encoding'].lower() == 'base64':
+ buf = base64.decodestring('\n'.join(lines))
+ 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')
- if lines[-1] == '': del lines[-1]
+ elif mimeinfo['content-transfer-encoding'].lower() == 'quoted-printable':
+ buf = quopri.decodestring('\n'.join(lines))
+ 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):
- code, text = line.split (' ', 1)
- code = int (code)
+ def __get_rs(self, line):
+ code, text = line.split(' ', 1)
+ code = int(code)
return code, text
- def __read (self):
+ def __read(self):
if not self.__connected:
- raise DicoNotConnectedError ('Not connected')
+ raise DicoNotConnectedError('Not connected')
buf = []
- line = self.__readline ()
- if len (line) == 0:
- raise DicoNotConnectedError ('Not connected')
- buf.append (line)
- code, text = self.__get_rs (line)
+ line = self.__readline()
+ if len(line) == 0:
+ raise DicoNotConnectedError('Not connected')
+ buf.append(line)
+ code, text = self.__get_rs(line)
if code >= 100 and code < 200:
if code == 150:
while True:
- rs = self.__readline ()
- code, text = self.__get_rs (rs)
+ rs = self.__readline()
+ code, text = self.__get_rs(rs)
if code != 151:
- buf.append (rs)
+ buf.append(rs)
break
- buf.append ([rs, self.__readblock ()])
+ buf.append([rs, self.__readblock()])
else:
- buf.append (self.__readblock ())
- buf.append (self.__readline ())
+ buf.append(self.__readblock())
+ buf.append(self.__readline())
return buf
- def __readline (self):
- line = self.fd.readline ().rstrip ()
+ def __readline(self):
+ line = self.fd.readline().rstrip()
if self.transcript:
- self.__debug ('S:%s' % line)
+ self.__debug('S:%s' % line)
return line
- def __readblock (self):
+ def __readblock(self):
buf = []
while True:
- line = self.__readline ()
+ line = self.__readline()
if line == '.':
break
- buf.append (line)
+ buf.append(line)
return buf
-
- def __send (self, command):
+ def __send(self, command):
if not self.__connected:
- raise DicoNotConnectedError ('Not connected')
- self.socket.send (command.encode ('utf_8') + "\r\n")
+ raise DicoNotConnectedError('Not connected')
+ 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)
+ self.__debug('C:%s' % command)
- def __send_client (self):
+ def __send_client(self):
if self.verbose:
- self.__debug ('Sending client information')
- self.__send ('CLIENT "%s %s"' % ("GNU Dico (Python Edition)",
- __version__))
+ self.__debug('Sending client information')
+ self.__send('CLIENT "%s %s"' % ("GNU Dico (Python Edition)",
+ __version__))
- def __send_quit (self):
+ def __send_quit(self):
if self.verbose:
- self.__debug ('Quitting')
- self.__send ('QUIT');
+ self.__debug('Quitting')
+ self.__send('QUIT')
- def __send_show (self, what, arg=None):
+ def __send_show(self, what, arg=None):
if arg != None:
- self.__send ('SHOW %s "%s"' % (what, arg))
+ self.__send('SHOW %s "%s"' % (what, arg))
else:
- self.__send ('SHOW %s' % what)
- return self.__read ()
+ self.__send('SHOW %s' % what)
+ return self.__read()
- def __send_define (self, database, word):
+ def __send_define(self, database, word):
if self.verbose:
- self.__debug ('Sending query for word "%s" in database "%s"' %
- (word, database))
- self.__send ('DEFINE "%s" "%s"' % (database, word))
- return self.__read ()
+ self.__debug('Sending query for word "%s" in database "%s"' %
+ (word, database))
+ self.__send('DEFINE "%s" "%s"' % (database, word))
+ return self.__read()
- def __send_match (self, database, strategy, word):
+ def __send_match(self, database, strategy, word):
if self.verbose:
- self.__debug ('Sending query to match word "%s" in database "%s", using "%s"'
- % (word, database, strategy))
- self.__send ('MATCH "%s" "%s" "%s"' % (database, strategy, word))
- return self.__read ()
+ self.__debug('Sending query to match word "%s" in database "%s", using "%s"'
+ % (word, database, strategy))
+ self.__send('MATCH "%s" "%s" "%s"' % (database, strategy, word))
+ return self.__read()
- def __send_xlev (self, distance):
- self.__send ('XLEV %u' % distance)
- return self.__read ()
+ def __send_xlev(self, distance):
+ self.__send('XLEV %u' % distance)
+ return self.__read()
- def show_databases (self):
+ def show_databases(self):
"""List all accessible databases."""
if self.verbose:
- self.__debug ('Getting list of databases')
- res = self.__send_show ('DATABASES')
+ self.__debug('Getting list of databases')
+ res = self.__send_show('DATABASES')
if self.mime:
- mimeinfo = self.__get_mime (res[1])
+ mimeinfo = self.__get_mime(res[1])
dbs_res = res[1:-1][0]
dbs = []
for d in dbs_res:
- short_name, full_name = d.split (' ', 1)
- dbs.append ([short_name, self.__unquote (full_name)])
+ short_name, full_name = d.split(' ', 1)
+ dbs.append([short_name, self.__unquote(full_name)])
dct = {
- 'count': len (dbs),
+ 'count': len(dbs),
'databases': dbs,
}
return dct
- def show_strategies (self):
+ def show_strategies(self):
"""List available matching strategies."""
if self.verbose:
- self.__debug ('Getting list of strategies')
- res = self.__send_show ('STRATEGIES')
+ self.__debug('Getting list of strategies')
+ res = self.__send_show('STRATEGIES')
if self.mime:
- mimeinfo = self.__get_mime (res[1])
+ mimeinfo = self.__get_mime(res[1])
sts_res = res[1:-1][0]
sts = []
for s in sts_res:
- short_name, full_name = s.split (' ', 1)
- sts.append ([short_name, self.__unquote (full_name)])
+ short_name, full_name = s.split(' ', 1)
+ sts.append([short_name, self.__unquote(full_name)])
dct = {
- 'count': len (sts),
+ 'count': len(sts),
'strategies': sts,
}
return dct
- def show_info (self, database):
+ def show_info(self, database):
"""Provide information about the database."""
- res = self.__send_show ("INFO", database)
- code, msg = res[0].split (' ', 1)
- if int (code) < 500:
+ res = self.__send_show("INFO", database)
+ code, msg = res[0].split(' ', 1)
+ if int(code) < 500:
if self.mime:
- mimeinfo = self.__get_mime (res[1])
+ mimeinfo = self.__get_mime(res[1])
dsc = res[1]
- return {'desc': '\n'.join (dsc), 'type': 'info' }
+ return {'desc': '\n'.join(dsc)}
else:
return {'error': code, 'msg': msg}
- def show_lang_db (self):
+ def show_lang_db(self):
"""Show databases with their language preferences."""
- res = self.__send_show ('LANG DB')
- code, msg = res[0].split (' ', 1)
- if int (code) < 500:
+ res = self.__send_show('LANG DB')
+ code, msg = res[0].split(' ', 1)
+ if int(code) < 500:
if self.mime:
- mimeinfo = self.__get_mime (res[1])
+ mimeinfo = self.__get_mime(res[1])
dsc = res[1]
lang_src = {}
lang_dst = {}
for i in dsc:
- pair = i.split (' ', 1)[1]
- src, dst = pair.split (':', 1)
+ pair = i.split(' ', 1)[1]
+ src, dst = pair.split(':', 1)
for j in src:
lang_src[src.strip()] = True
for j in dst:
lang_dst[dst.strip()] = True
return {
- 'desc': '\n'.join (dsc),
- 'type': 'lang',
- 'lang_src': lang_src.keys (),
- 'lang_dst': lang_dst.keys (),
+ 'desc': '\n'.join(dsc),
+ 'lang_src': list(lang_src.keys()),
+ 'lang_dst': list(lang_dst.keys()),
}
else:
return {'error': code, 'msg': msg}
- def show_lang_pref (self):
+ def show_lang_pref(self):
"""Show server language preferences."""
- res = self.__send_show ('LANG PREF')
- code, msg = res[0].split (' ', 1)
- if int (code) < 500:
+ res = self.__send_show('LANG PREF')
+ code, msg = res[0].split(' ', 1)
+ if int(code) < 500:
return {'msg': msg}
else:
return {'error': code, 'msg': msg}
- def show_server (self):
+ def show_server(self):
"""Provide site-specific information."""
- res = self.__send_show ('SERVER')
- code, msg = res[0].split (' ', 1)
- if int (code) < 500:
+ res = self.__send_show('SERVER')
+ code, msg = res[0].split(' ', 1)
+ if int(code) < 500:
dsc = res[1]
- return {'desc': '\n'.join (dsc), 'type': 'server'}
+ return {'desc': '\n'.join(dsc)}
else:
return {'error': code, 'msg': msg}
- def define (self, database, word):
+ def define(self, database, word):
"""Look up word in database."""
- database = database.replace ('"', "\\\"")
- word = word.replace ('"', "\\\"")
- res = self.__send_define (database, word)
- code, msg = res[-1].split (' ', 1)
- if int (code) < 500:
+ database = database.replace('"', "\\\"")
+ word = word.replace('"', "\\\"")
+ res = self.__send_define(database, word)
+ code, msg = res[-1].split(' ', 1)
+ if int(code) < 500:
defs_res = res[1:-1]
defs = []
- rx = re.compile ('^\d+ ("[^"]+"|\w+) ([a-zA-Z0-9_\-]+) ("[^"]*"|\w+)')
+ rx = re.compile(
+ '^\d+ ("[^"]+"|\w+) ([a-zA-Z0-9_\-]+) ("[^"]*"|\w+)')
for i in defs_res:
- term, db, db_fullname = rx.search (i[0]).groups ()
+ term, db, db_fullname = rx.search(i[0]).groups()
df = {
- 'term': self.__unquote (term),
+ 'term': self.__unquote(term),
'db': db,
- 'db_fullname': self.__unquote (db_fullname),
+ 'db_fullname': self.__unquote(db_fullname),
}
if self.mime:
- mimeinfo = self.__get_mime (i[1])
- df.update (mimeinfo)
- df['desc'] = '\n'.join (i[1])
- defs.append (df)
+ mimeinfo = self.__get_mime(i[1])
+ df.update(mimeinfo)
+ df['desc'] = '\n'.join(i[1])
+ defs.append(df)
dct = {
- 'count': len (defs),
+ 'count': len(defs),
'definitions': defs,
- 'type': 'define'
}
return dct
else:
return {'error': code, 'msg': msg}
- def match (self, database, strategy, word):
+ def match(self, database, strategy, word):
"""Match word in database using strategy."""
if not self.__connected:
- raise DicoNotConnectedError ('Not connected')
+ raise DicoNotConnectedError('Not connected')
if self.levenshtein_distance and 'xlev' in self.server_capas:
- res = self.__send_xlev (self.levenshtein_distance)
- code, msg = res[-1].split (' ', 1)
- if int (code) != 250 and self.verbose:
- self.__debug ('Server rejected XLEV command')
- self.__debug ('Server reply: %s' % msg)
-
- database = database.replace ('"', "\\\"")
- strategy = strategy.replace ('"', "\\\"")
- word = word.replace ('"', "\\\"")
-
- res = self.__send_match (database, strategy, word)
- code, msg = res[-1].split (' ', 1)
- if int (code) < 500:
+ res = self.__send_xlev(self.levenshtein_distance)
+ code, msg = res[-1].split(' ', 1)
+ if int(code) != 250 and self.verbose:
+ self.__debug('Server rejected XLEV command')
+ self.__debug('Server reply: %s' % msg)
+
+ database = database.replace('"', "\\\"")
+ strategy = strategy.replace('"', "\\\"")
+ word = word.replace('"', "\\\"")
+
+ res = self.__send_match(database, strategy, word)
+ code, msg = res[-1].split(' ', 1)
+ if int(code) < 500:
if self.mime:
- mimeinfo = self.__get_mime (res[1])
+ mimeinfo = self.__get_mime(res[1])
mts_refs = res[1:-1][0]
mts = {}
for i in mts_refs:
- db, term = i.split (' ', 1)
- if mts.has_key (db):
- mts[db].append (self.__unquote (term))
+ db, term = i.split(' ', 1)
+ if db in mts:
+ mts[db].append(self.__unquote(term))
else:
- mts[db] = [self.__unquote (term)]
+ mts[db] = [self.__unquote(term)]
dct = {
'matches': mts,
}
@@ -381,35 +379,38 @@ class DicoClient:
else:
return {'error': code, 'msg': msg}
- def xlev (self, distance):
+ def xlev(self, distance):
"""Set Levenshtein distance."""
self.levenshtein_distance = distance
- res = self.__send_xlev (distance)
- code, msg = res[0].split (' ', 1)
- if int (code) == 250:
+ res = self.__send_xlev(distance)
+ code, msg = res[0].split(' ', 1)
+ if int(code) == 250:
return True
return False
- def __unquote (self, s):
- s = s.replace ("\\\\'", "'")
+ def __unquote(self, s):
+ s = s.replace("\\\\'", "'")
if s[0] == '"' and s[-1] == '"':
s = s[1:-1]
try:
- s = self.__decode (s)
+ s = self.__decode(s)
except UnicodeEncodeError:
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')
+ 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 encoded
+
+ def __debug(self, msg):
+ print('dico: Debug: %s' % msg)
- def __debug (self, msg):
- print 'dico: Debug: %s' % msg
class DicoNotConnectedError (Exception):
- def __init__ (self, value):
+
+ def __init__(self, value):
self.parameter = value
+
def __str__(self):
- return repr (self.parameter)
+ return repr(self.parameter)
diff --git a/dicoclient/dicoshell.py b/dicoclient/dicoshell.py
index 1c0e64d..8cbac3d 100644
--- a/dicoclient/dicoshell.py
+++ b/dicoclient/dicoshell.py
@@ -1,5 +1,5 @@
# This file is part of GNU Dico.
-# Copyright (C) 2008-2010, 2012 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
@@ -24,6 +24,12 @@ 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."""
@@ -38,186 +44,191 @@ class Shell:
last_strategies = []
transcript = False
- def __init__ (self, opts, args):
+ def __init__(self, opts, args):
for o, a in opts:
if o in ('-h', '--host'):
self.default_host = a
- self.dc = dicoclient.DicoClient (self.default_host)
+ self.dc = dicoclient.DicoClient(self.default_host)
- def run (self):
- histfile = os.path.expanduser ('~/.dico_history')
+ def run(self):
+ histfile = os.path.expanduser('~/.dico_history')
try:
- readline.read_history_file (histfile)
+ readline.read_history_file(histfile)
except IOError:
pass
- atexit.register (readline.write_history_file, histfile)
+ 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
- sys.exit ()
+ print()
+ sys.exit()
try:
- self.parse (input)
+ self.parse(inputcmd)
except socket.timeout:
- self.__error ('socket timed out')
+ self.__error('socket timed out')
except dicoclient.DicoNotConnectedError:
try:
- self.dc.open ()
- dict = self.dc.show_databases ()
+ self.dc.open()
+ dict = self.dc.show_databases()
self.last_databases = dict['databases']
- dict = self.dc.show_strategies ()
+ dict = self.dc.show_strategies()
self.last_strategies = dict['strategies']
- self.parse (input)
- except socket.error, (errno, strerror):
- self.__error (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 == '?':
- self.print_help ()
- elif re.match (r'^[0-9]+$', input):
+
+ if inputcmd[0] == self.prefix:
+ self.parse_command(inputcmd[1:])
+
+ elif inputcmd == '?':
+ self.print_help()
+