# HG changeset patch # User ymh # Date 1391566705 -3600 # Node ID 6ffca49f6a0cdb736ff1684c1b8fb7dad5b66620 # Parent 493fceed57ec7cf7c4ae84071e11c414e5dd9ac9 use elasticsearch for label and free search diff -r 493fceed57ec -r 6ffca49f6a0c .settings/org.eclipse.core.resources.prefs --- a/.settings/org.eclipse.core.resources.prefs Mon Feb 03 02:43:13 2014 +0100 +++ b/.settings/org.eclipse.core.resources.prefs Wed Feb 05 03:18:25 2014 +0100 @@ -26,6 +26,7 @@ encoding//src/core/wp_utils.py=utf-8 encoding//src/get_notice_years.py=utf-8 encoding//src/jocondelab/admin.py=utf-8 +encoding//src/jocondelab/cache_utils.py=utf-8 encoding//src/jocondelab/config.py=utf-8 encoding//src/jocondelab/forms.py=utf-8 encoding//src/jocondelab/management/__init__.py=utf-8 @@ -54,9 +55,11 @@ encoding//src/jocondelab/migrations/0010_auto__add_contributable_term.py=utf-8 encoding//src/jocondelab/migrations/0011_auto__add_tagcloud_term.py=utf-8 encoding//src/jocondelab/migrations/0012_auto__add_notice_years.py=utf-8 +encoding//src/jocondelab/models/__init__.py=utf-8 encoding//src/jocondelab/models/contribution.py=utf-8 encoding//src/jocondelab/models/data.py=utf-8 encoding//src/jocondelab/models/displaysettings.py=utf-8 +encoding//src/jocondelab/search_indexes.py=utf-8 encoding//src/jocondelab/settings.py=utf-8 encoding//src/jocondelab/utils.py=utf-8 encoding//src/jocondelab/views/ajax.py=utf-8 diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/cache_utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jocondelab/cache_utils.py Wed Feb 05 03:18:25 2014 +0100 @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# Copyright Institut de Recherche et d'Innovation © 2014 +# +# contact@iri.centrepompidou.fr +# +# Ce code a été développé pour un premier usage dans JocondeLab, projet du +# ministère de la culture et de la communication visant à expérimenter la +# recherche sémantique dans la base Joconde +# (http://jocondelab.iri-research.org/). +# +# Ce logiciel est régi par la licence CeCILL-C soumise au droit français et +# respectant les principes de diffusion des logiciels libres. Vous pouvez +# utiliser, modifier et/ou redistribuer ce programme sous les conditions +# de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA +# sur le site "http://www.cecill.info". +# +# En contrepartie de l'accessibilité au code source et des droits de copie, +# de modification et de redistribution accordés par cette licence, il n'est +# offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, +# seule une responsabilité restreinte pèse sur l'auteur du programme, le +# titulaire des droits patrimoniaux et les concédants successifs. +# +# A cet égard l'attention de l'utilisateur est attirée sur les risques +# associés au chargement, à l'utilisation, à la modification et/ou au +# développement et à la reproduction du logiciel par l'utilisateur étant +# donné sa spécificité de logiciel libre, qui peut le rendre complexe à +# manipuler et qui le réserve donc à des développeurs et des professionnels +# avertis possédant des connaissances informatiques approfondies. Les +# utilisateurs sont donc invités à charger et tester l'adéquation du +# logiciel à leurs besoins dans des conditions permettant d'assurer la +# sécurité de leurs systèmes et ou de leurs données et, plus généralement, +# à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. +# +# Le fait que vous puissiez accéder à cet en-tête signifie que vous avez +# pris connaissance de la licence CeCILL-C, et que vous en avez accepté les +# termes. +# +''' + +@author: ymh +''' + +import hashlib + + +CONTROL_CHARACTERS = set([chr(i) for i in range(0,33)]) +CONTROL_CHARACTERS.add(chr(127)) + +## +# From django-cache-utils, https://bitbucket.org/kmike/django-cache-utils/ +# +def sanitize_memcached_key(key, max_length=250): + """ Removes control characters and ensures that key will + not hit the memcached key length limit by replacing + the key tail with md5 hash if key is too long. + """ + key = ''.join([c for c in key if c not in CONTROL_CHARACTERS]) + if len(key) > max_length: + hash_str = hashlib.md5(key).hexdigest() + key = key[:max_length-33]+'-'+hash_str + return key + +def make_key(key, key_prefix, version): + return sanitize_memcached_key(':'.join([key_prefix, str(version), key])) diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/config.py.tmpl --- a/src/jocondelab/config.py.tmpl Mon Feb 03 02:43:13 2014 +0100 +++ b/src/jocondelab/config.py.tmpl Wed Feb 05 03:18:25 2014 +0100 @@ -189,13 +189,15 @@ CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - 'LOCATION': 'unique-snowflake' + 'LOCATION': 'unique-snowflake', + 'KEY_FUNCTION' : 'jocondelab.cache_utils.make_key' } } CACHE_MIDDLEWARE_SECONDS = 600 HOME_CACHE_SECONDS = 30 + #PIPELINE_ENABLED = not DEBUG PIPELINE_CSS_COMPRESSOR = "pipeline.compressors.yuglify.YuglifyCompressor" PIPELINE_JS_COMPRESSOR = "pipeline.compressors.yuglify.YuglifyCompressor" diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/management/commands/import_dbpedia_fields.py --- a/src/jocondelab/management/commands/import_dbpedia_fields.py Mon Feb 03 02:43:13 2014 +0100 +++ b/src/jocondelab/management/commands/import_dbpedia_fields.py Wed Feb 05 03:18:25 2014 +0100 @@ -41,21 +41,24 @@ @author: ymh ''' +from optparse import make_option +import sys +import traceback +import urllib2 + from SPARQLWrapper.Wrapper import RDF, SPARQLWrapper -from core.models import Term -from core.utils import show_progress -from core.wp_utils import get_dbpedia_lang from django.conf import settings from django.core.management.base import NoArgsCommand from django.db import reset_queries, transaction from django.db.models.aggregates import Count from django.utils.http import urlunquote +from rdflib.term import URIRef + +from core.models import Term +from core.utils import show_progress +from core.wp_utils import get_dbpedia_lang from jocondelab.models.data import TermLinks, DbpediaFields -from optparse import make_option -from rdflib.term import URIRef -import sys -import traceback -import urllib2 +from django.core.management import call_command class Command(NoArgsCommand): ''' @@ -228,4 +231,6 @@ transaction.rollback() transaction.leave_transaction_management() - + print("Ddpedia fields imported. launching index recreation, no questions asked.") + call_command("rebuild_index", interactive=False) + diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/search_indexes.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jocondelab/search_indexes.py Wed Feb 05 03:18:25 2014 +0100 @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# +# Copyright Institut de Recherche et d'Innovation © 2014 +# +# contact@iri.centrepompidou.fr +# +# Ce code a été développé pour un premier usage dans JocondeLab, projet du +# ministère de la culture et de la communication visant à expérimenter la +# recherche sémantique dans la base Joconde +# (http://jocondelab.iri-research.org/). +# +# Ce logiciel est régi par la licence CeCILL-C soumise au droit français et +# respectant les principes de diffusion des logiciels libres. Vous pouvez +# utiliser, modifier et/ou redistribuer ce programme sous les conditions +# de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA +# sur le site "http://www.cecill.info". +# +# En contrepartie de l'accessibilité au code source et des droits de copie, +# de modification et de redistribution accordés par cette licence, il n'est +# offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, +# seule une responsabilité restreinte pèse sur l'auteur du programme, le +# titulaire des droits patrimoniaux et les concédants successifs. +# +# A cet égard l'attention de l'utilisateur est attirée sur les risques +# associés au chargement, à l'utilisation, à la modification et/ou au +# développement et à la reproduction du logiciel par l'utilisateur étant +# donné sa spécificité de logiciel libre, qui peut le rendre complexe à +# manipuler et qui le réserve donc à des développeurs et des professionnels +# avertis possédant des connaissances informatiques approfondies. Les +# utilisateurs sont donc invités à charger et tester l'adéquation du +# logiciel à leurs besoins dans des conditions permettant d'assurer la +# sécurité de leurs systèmes et ou de leurs données et, plus généralement, +# à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. +# +# Le fait que vous puissiez accéder à cet en-tête signifie que vous avez +# pris connaissance de la licence CeCILL-C, et que vous en avez accepté les +# termes. +# +from unidecode import unidecode +''' +@author: ymh +''' + +from haystack import indexes +from jocondelab.models import DbpediaFields + +class DbpediaFieldsIndex(indexes.SearchIndex, indexes.Indexable): + text = indexes.CharField(document=True, use_template=True) + label = indexes.CharField(model_attr='label', null=True) + label_trans = indexes.CharField(model_attr='label', null=True, indexed=True, stored=False) + label_ngram = indexes.NgramField(model_attr='label', null=True) + label_edge = indexes.EdgeNgramField(model_attr='label', null=True) + language_code = indexes.CharField(model_attr='language_code', null=True) + dbpedia_uri = indexes.CharField(model_attr='dbpedia_uri', null=True, indexed=False, stored=True) + + def get_model(self): + return DbpediaFields + + def index_queryset(self, using=None): + """Used when the entire index for model is updated.""" + return self.get_model().objects.filter(term__nb_illustrated_notice__gt=0) + + def prepare_label_trans(self, obj): + if obj.label is not None: + return unidecode(obj.label.lower()) + else: + return None diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/settings.py --- a/src/jocondelab/settings.py Mon Feb 03 02:43:13 2014 +0100 +++ b/src/jocondelab/settings.py Wed Feb 05 03:18:25 2014 +0100 @@ -205,7 +205,8 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'django_extensions', - 'django.contrib.admin', + 'django.contrib.admin', + 'haystack', 'south', 'mptt', 'pipeline', @@ -313,6 +314,17 @@ CACHE_MIDDLEWARE_SECONDS = 600 HOME_CACHE_SECONDS = 30 +#MAX number of term in case search term does not recognize a wikipedia label +MAX_TERMS_QUERY = 200 + +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'haystack.backends.simple_backend.SimpleEngine', + 'KEY_FUNCTION' : 'jocondelab.utils.make_key' + }, +} + + BASE_CSS = ('jocondelab/css/smoothness/jquery-ui-1.10.3.custom.min.css', 'jocondelab/lib/jquery.tagit.css', 'jocondelab/css/front-common.css') PIPELINE_CSS = { diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/templates/search/indexes/jocondelab/dbpediafields_text.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jocondelab/templates/search/indexes/jocondelab/dbpediafields_text.txt Wed Feb 05 03:18:25 2014 +0100 @@ -0,0 +1,2 @@ +{{ object.label }} +{{ object.language_code }} \ No newline at end of file diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/utils.py --- a/src/jocondelab/utils.py Mon Feb 03 02:43:13 2014 +0100 +++ b/src/jocondelab/utils.py Wed Feb 05 03:18:25 2014 +0100 @@ -37,7 +37,6 @@ # termes. # ''' -Created on Jun 16, 2013 @author: ymh ''' @@ -127,4 +126,5 @@ cache.set(self._get_count_key(), self._count, settings.DB_QUERY_CACHE_TIME) return self._count - count = property(_get_count_cached) \ No newline at end of file + count = property(_get_count_cached) + diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/views/ajax.py --- a/src/jocondelab/views/ajax.py Mon Feb 03 02:43:13 2014 +0100 +++ b/src/jocondelab/views/ajax.py Wed Feb 05 03:18:25 2014 +0100 @@ -44,20 +44,20 @@ import json import logging -import re from django.conf import settings +from django.core.cache import cache from django.db.models import Sum from django.http import HttpResponse from django.http.response import HttpResponseBadRequest from django.views.generic import TemplateView +from haystack.query import SearchQuerySet import requests from core.models import Notice, Thesaurus from jocondelab.models import (DbpediaYears, DbpediaGeo, DbpediaFields, ContributedTerm, ContributedFields, Contribution) - logger = logging.getLogger(__name__) def terms(request): @@ -65,14 +65,30 @@ lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2] q = request.GET.get('term', None) count = request.GET.get('count', 20) - qs = DbpediaFields.objects.filter(term__nb_illustrated_notice__gt=0,language_code=lang) - if lang in [ "fr", "en", "de", "it", "es", "pt", "ca", "br", "eu", "oc" ]: - qs = qs.filter(label__iregex=r"\y%s"%re.sub("(\W)",lambda m: u'\\'+m.group(1),q, flags=re.UNICODE)) - else: - qs = qs.filter(label__icontains=q) - qs = qs.values('dbpedia_uri','label').distinct().order_by('label')[:count] - res = [{"dbpedia_uri": r['dbpedia_uri'], "label": r['label']} for r in qs] - return HttpResponse(content=json.dumps(res), mimetype='application/json') + + cachekey = "--".join((q,lang,str(count))) + res_list = cache.get(cachekey) + + if not res_list: + + if lang in [ "fr", "en", "de", "it", "es", "pt", "ca", "br", "eu", "oc" ]: + fields_index_qs = SearchQuerySet().models(DbpediaFields).filter(language_code__exact=lang).autocomplete(label_ngram=q) + else: + fields_index_qs = SearchQuerySet().models(DbpediaFields).filter(language_code__exact=lang).autocomplete(label_edge=q) + + res_dict = {} + for r in fields_index_qs[:count*5]: + dbpedia_uri = r.get_stored_fields()['dbpedia_uri'] + label = r.get_stored_fields()['label'] + if not dbpedia_uri: + continue + res_entry = res_dict.setdefault(dbpedia_uri, {'label': None, 'score':0, 'uri':dbpedia_uri}) + res_entry['label'] = label if label and not res_entry.get('label', None) else res_entry['label'] + res_entry['score'] += r.score + + res_list = sorted([ res_entry for res_entry in res_dict.values()],key=lambda r: r.get('score',0), reverse=True) + cache.set(cachekey, res_list) + return HttpResponse(content=json.dumps([{"dbpedia_uri":r.get('uri'), "label": r.get('label','')} for r in res_list]), mimetype='application/json') def years(request): diff -r 493fceed57ec -r 6ffca49f6a0c src/jocondelab/views/front_office.py --- a/src/jocondelab/views/front_office.py Mon Feb 03 02:43:13 2014 +0100 +++ b/src/jocondelab/views/front_office.py Wed Feb 05 03:18:25 2014 +0100 @@ -55,6 +55,8 @@ from django.utils.http import urlencode from django.utils.translation import ugettext from django.views.generic import DetailView, TemplateView +from haystack.query import SearchQuerySet +from unidecode import unidecode from core.models import Notice, Term, TERM_WK_LINK_SEMANTIC_LEVEL_DICT from core.models.term import Thesaurus @@ -168,10 +170,13 @@ queryobj = {'dbpedia_uri': dbpedia_uri} fs = list(DbpediaFields.objects.filter(dbpedia_uri__in=dbpedia_uris, language_code=lang).exclude(label__isnull=True)) searchterms = set([fields.label for fields in fs]) + operator = "and" elif queryterms: searchterms = queryterms queryobj = {'q': querystr} - fs = list(DbpediaFields.objects.filter(label__in=queryterms, language_code=lang).exclude(label__isnull=True)) + label_search = SearchQuerySet().models(DbpediaFields).filter(language_code__exact=lang).auto_query(" ".join([unidecode(q.lower()) for q in queryterms]), "label_trans")[:getattr(settings, 'MAX_TERMS_QUERY', 200)] + fs = list(DbpediaFields.objects.filter(id__in=[r.pk for r in label_search], language_code=lang).exclude(label__isnull=True)) + operator = 'or' # If fs is empty, qs has to be empty if len(fs)==0: qs = qs.none() @@ -182,8 +187,14 @@ uri_cache.update(dict([(fields.label.lower() if fields.label else "", fields.dbpedia_uri) for fields in fs])) if page == 1 and len(dbpedia_uris) == 1 and len(fs) > 0: context["wkinfo"] = fs[0] + term_filters = Q() for term_ids in fields_hash.values(): - qs = qs.filter(noticeterm__term_id__in=term_ids) + term_filter_term = Q(noticeterm__term_id__in=term_ids) + if operator == "and": + term_filters &= term_filter_term + else: + term_filters |= term_filter_term + qs = qs.filter(term_filters) count_qs = qs qs = qs.filter(noticeterm__term__validated=True) diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/lib/lib_create_env.py --- a/virtualenv/res/lib/lib_create_env.py Mon Feb 03 02:43:13 2014 +0100 +++ b/virtualenv/res/lib/lib_create_env.py Wed Feb 05 03:18:25 2014 +0100 @@ -23,14 +23,14 @@ 'SOUTH': { 'setup': 'South', 'url':'http://www.aeracode.org/releases/south/south-0.7.6.tar.gz', 'local':"south-0.7.6.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'LIBJPEG': {'setup': None, 'url':'jpegsrc.v9.tar.gz', 'local':'jpegsrc.v9.tar.gz', 'install': {'method': 'install_libjpeg', 'option_str': None, 'dict_extra_env': None}}, 'ZLIB': {'setup': None, 'url':'zlib-1.2.8.tar.gz', 'local':'zlib-1.2.8.tar.gz', 'install': {'method': 'install_zlib', 'option_str': None, 'dict_extra_env': None}}, - 'HAYSTACK': {'setup': 'django-haystack', 'url': 'https://github.com/toastdriven/django-haystack/archive/v2.0.0.tar.gz', 'local': 'django-haystack-2.0.0.tar.gz', 'install':{'method':'pip', 'option_str': None, 'dict_extra_env': None}}, - 'PYELASTICSEARCH': {'setup': 'pyelasticsearch', 'url':'https://github.com/rhec/pyelasticsearch/archive/0.5.tar.gz', 'local':'pyelasticsearch-0.5.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'HAYSTACK': {'setup': 'django-haystack', 'url': 'https://github.com/toastdriven/django-haystack/archive/v2.1.0.tar.gz', 'local': 'django-haystack-2.1.0.tar.gz', 'install':{'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'PYELASTICSEARCH': {'setup': 'pyelasticsearch', 'url':'https://github.com/rhec/pyelasticsearch/archive/0.6.1.tar.gz', 'local':'pyelasticsearch-0.6.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'PYTHON-DATEUTIL' : {'setup':'python-dateutil', 'url':'https://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.1.tar.gz', 'local': 'python-dateutil-2.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'RDFLIB' : {'setup':'rdflib', 'url':'https://github.com/RDFLib/rdflib/archive/4.0.1.tar.gz', 'local': 'rdflib-4.0.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'SQLALCHEMY' : {'setup':'sqlalchemy', 'url':'https://pypi.python.org/packages/source/S/SQLAlchemy/SQLAlchemy-0.8.1.tar.gz', 'local': 'SQLAlchemy-0.8.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'RDFLIB-SQLALCHEMY' : {'setup':'rdflib-sqlalchemy', 'url':'https://github.com/editorsnotes/rdflib-sqlalchemy/archive/9996e2fd7cdd87e35384c529196407808c9f60ee.tar.gz', 'local': 'rdflib-sqlalchemy-0.2.dev.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, - 'REQUESTS': {'setup': 'requests', 'url':'https://github.com/kennethreitz/requests/archive/v1.2.3.tar.gz', 'local':'requests-1.2.3.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, - 'SIMPLEJSON': {'setup': 'simplejson','url':'https://github.com/simplejson/simplejson/archive/v3.3.0.tar.gz', 'local': 'simplejson-3.3.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'REQUESTS': {'setup': 'requests', 'url':'https://github.com/kennethreitz/requests/archive/v2.2.1.tar.gz', 'local':'requests-2.2.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'SIMPLEJSON': {'setup': 'simplejson','url':'https://github.com/simplejson/simplejson/archive/v3.3.2.tar.gz', 'local': 'simplejson-3.3.2.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'ISODATE': {'setup': 'isodate','url':'https://pypi.python.org/packages/source/i/isodate/isodate-0.4.9.tar.gz', 'local': 'isodate-0.4.9.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'PYPARSING': {'setup': 'pyparsing','url':'http://downloads.sourceforge.net/project/pyparsing/pyparsing/pyparsing-1.5.7/pyparsing-1.5.7.tar.gz', 'local': 'pyparsing-1.5.7.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'SPARQLWRAPPER': {'setup': 'sparqlwrapper','url':'http://downloads.sourceforge.net/project/sparql-wrapper/sparql-wrapper-python/1.5.2/SPARQLWrapper-1.5.2.tar.gz', 'local': 'SPARQLWrapper-1.5.2.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, @@ -39,6 +39,7 @@ 'MPTT' : { 'setup': 'django-mptt', 'url': 'https://codeload.github.com/django-mptt/django-mptt/tar.gz/master', 'local': 'django-mptt-0.5.-dev.tar.bz2', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'FUTURES' : { 'setup': 'futures', 'url': 'https://pypi.python.org/packages/source/f/futures/futures-2.1.6.tar.gz', 'local': 'futures-2.1.6.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'PIPELINE' : { 'setup': 'django-pipeline', 'url': 'https://github.com/cyberdelia/django-pipeline/archive/1.3.20.tar.gz', 'local': 'django-pipeline-1.3.20.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, + 'UNIDECODE' : { 'setup': 'unidecode', 'url': 'https://pypi.python.org/packages/source/U/Unidecode/Unidecode-0.04.14.tar.gz', 'local': 'Unidecode-0.04.14.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, } if system_str == 'Windows': diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/Unidecode-0.04.14.tar.gz Binary file virtualenv/res/src/Unidecode-0.04.14.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/django-haystack-2.0.0.tar.gz Binary file virtualenv/res/src/django-haystack-2.0.0.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/django-haystack-2.1.0.tar.gz Binary file virtualenv/res/src/django-haystack-2.1.0.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/pyelasticsearch-0.5.tar.gz Binary file virtualenv/res/src/pyelasticsearch-0.5.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/pyelasticsearch-0.6.1.tar.gz Binary file virtualenv/res/src/pyelasticsearch-0.6.1.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/requests-1.2.3.tar.gz Binary file virtualenv/res/src/requests-1.2.3.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/requests-2.2.1.tar.gz Binary file virtualenv/res/src/requests-2.2.1.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/simplejson-3.3.0.tar.gz Binary file virtualenv/res/src/simplejson-3.3.0.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/res/src/simplejson-3.3.2.tar.gz Binary file virtualenv/res/src/simplejson-3.3.2.tar.gz has changed diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/web/res/requirement.txt --- a/virtualenv/web/res/requirement.txt Mon Feb 03 02:43:13 2014 +0100 +++ b/virtualenv/web/res/requirement.txt Wed Feb 05 03:18:25 2014 +0100 @@ -3,9 +3,10 @@ SPARQLWrapper==1.5.2 SQLAlchemy==0.8.1 South==0.7.6 +Unidecode==0.04.14 distribute==0.6.34 django-extensions==1.1.1 -django-haystack==2.0.0 +django-haystack==2.1.0 django-mptt==0.5.-dev django-pipeline==1.3.20 futures==2.1.6 @@ -13,13 +14,13 @@ isodate==0.4.9 lxml==3.2.1 psycopg2==2.5 -pyelasticsearch==0.5 +pyelasticsearch==0.6.1 pyparsing==1.5.7 python-dateutil==2.1 rdflib==4.0.1 rdflib-sqlalchemy==0.2.dev -requests==1.2.3 -simplejson==3.3.0 +requests==2.2.1 +simplejson==3.3.2 six==1.3.0 wikitools==1.1.1 wsgiref==0.1.2 \ No newline at end of file diff -r 493fceed57ec -r 6ffca49f6a0c virtualenv/web/res/res_create_env.py --- a/virtualenv/web/res/res_create_env.py Mon Feb 03 02:43:13 2014 +0100 +++ b/virtualenv/web/res/res_create_env.py Wed Feb 05 03:18:25 2014 +0100 @@ -31,6 +31,7 @@ # 'WIKITOOLS', # 'MPTT', # 'PIPELINE', +# 'UNIDECODE', ] if system_str == "Linux":