Merge with 0f8c8b16cb58987fb71a997407cf06a8873bbbbb
authorcavaliet
Tue, 17 Jun 2014 10:32:57 +0200
changeset 272 1c774f7a0341
parent 271 8f77cf71ab02 (diff)
parent 270 0f8c8b16cb58 (current diff)
child 273 0fa407857df2
Merge with 0f8c8b16cb58987fb71a997407cf06a8873bbbbb
.settings/org.eclipse.core.resources.prefs
src/hdabo/config.py.tmpl
src/hdabo/django_wsgi.py
src/hdabo/models.py
src/hdabo/settings.py
src/hdalab/README.txt
src/hdalab/__init__.py
src/hdalab/locale/de/LC_MESSAGES/django.mo
src/hdalab/locale/de/LC_MESSAGES/django.po
src/hdalab/locale/de/LC_MESSAGES/djangojs.mo
src/hdalab/locale/de/LC_MESSAGES/djangojs.po
src/hdalab/locale/en/LC_MESSAGES/django.mo
src/hdalab/locale/en/LC_MESSAGES/django.po
src/hdalab/locale/en/LC_MESSAGES/djangojs.mo
src/hdalab/locale/en/LC_MESSAGES/djangojs.po
src/hdalab/locale/es/LC_MESSAGES/django.mo
src/hdalab/locale/es/LC_MESSAGES/django.po
src/hdalab/locale/es/LC_MESSAGES/djangojs.mo
src/hdalab/locale/es/LC_MESSAGES/djangojs.po
src/hdalab/locale/fr/LC_MESSAGES/djangojs.mo
src/hdalab/locale/fr/LC_MESSAGES/djangojs.po
src/hdalab/locale/it/LC_MESSAGES/django.mo
src/hdalab/locale/it/LC_MESSAGES/django.po
src/hdalab/locale/it/LC_MESSAGES/djangojs.mo
src/hdalab/locale/it/LC_MESSAGES/djangojs.po
src/hdalab/locale/ja/LC_MESSAGES/django.po
src/hdalab/locale/ja/LC_MESSAGES/djangojs.mo
src/hdalab/locale/ja/LC_MESSAGES/djangojs.po
src/hdalab/locale/zh-tw/LC_MESSAGES/djangojs.mo
src/hdalab/locale/zh-tw/LC_MESSAGES/djangojs.po
src/hdalab/management/commands/import_hda_insee_csv.py
src/hdalab/management/commands/import_hdabo_db.py
src/hdalab/management/commands/import_insee_csv.py
src/hdalab/management/commands/query_dbpedia.py
src/hdalab/models/__init__.py
src/hdalab/models/categories.py
src/hdalab/models/dataviz.py
src/hdalab/static/hdalab/css/common.css
src/hdalab/static/hdalab/css/facettes.css
src/hdalab/static/hdalab/css/index.css
src/hdalab/static/hdalab/js/gomina.js
src/hdalab/templates/base.html
src/hdalab/templates/facettes.html
src/hdalab/templates/index.html
src/hdalab/urls.py
src/hdalab/views/ajax.py
virtualenv/res/lib/lib_create_env.py
virtualenv/res/src/lxml-2.3.tar.bz2
virtualenv/web/res/res_create_env.py
virtualenv/web/virtualenv.py
--- a/.hgtags	Mon Jun 16 17:37:36 2014 +0200
+++ b/.hgtags	Tue Jun 17 10:32:57 2014 +0200
@@ -41,3 +41,28 @@
 17c05790e83531f7c2c75dc39aeebcab8b18ecb7 V02.11
 cfe89189fd6908fce3a121238d3a17a018dc251f V02.12
 46037fd31cafde624383e12c128c1c4d4a6fb56f V02.13
+d4e3ea75196634f98f1ec471e1945d5d7ca8449a V02.14
+d4e3ea75196634f98f1ec471e1945d5d7ca8449a V02.14
+ca50d1a91b482d028145606b14879fe3cea82674 V02.14
+68f7d25f12e122d021a05b7c859d28818f98f509 V02.15
+68f7d25f12e122d021a05b7c859d28818f98f509 V02.15
+c4953332bc52e276386c625175fb4071a20e1ee1 V02.15
+c4953332bc52e276386c625175fb4071a20e1ee1 V02.15
+b865d890346a96b97e9d5f5153f4574c50cd9c71 V02.15
+1544fe5309bf7bcaa76bb58ac15b6faa8a10de22 V02.16
+1544fe5309bf7bcaa76bb58ac15b6faa8a10de22 V02.16
+b6e1b012683b28d57dd6273d032b7a1ec50c17e4 V02.16
+b6e1b012683b28d57dd6273d032b7a1ec50c17e4 V02.16
+d1eea4065b01d05a8e82330231224cb37078108f V02.16
+eb02eed5f7d1dd9ab2075b0cd7cfbf978f8992e5 V02.17
+d662f4b0446c22f1869db1925251994f491d144f V02.18
+1f25d3696f57b6e6e328f6933e1c95ab34528e98 V02.19
+feef595beed40b13050c94da3ed5bea6f9911582 V02.20
+feef595beed40b13050c94da3ed5bea6f9911582 V02.20
+aa50a14266e16e661b25c078bfe20d5f1d668379 V02.20
+6f628208f34b4cbd8adb6ed3e121f74374e05da7 V02.21
+6f628208f34b4cbd8adb6ed3e121f74374e05da7 V02.21
+2986e2d0fa3bcdb941694894fbd9ccef030c4988 V02.21
+2986e2d0fa3bcdb941694894fbd9ccef030c4988 V02.21
+0368e86e4cbdb20ae42c958da49c2018843c1290 V02.21
+da962b8b5bce839c286e2f55d29caf90d180eafa V02.22
--- a/.settings/org.eclipse.core.resources.prefs	Mon Jun 16 17:37:36 2014 +0200
+++ b/.settings/org.eclipse.core.resources.prefs	Tue Jun 17 10:32:57 2014 +0200
@@ -1,52 +1,48 @@
-eclipse.preferences.version=1
-encoding//data/villes.csv=ISO-8859-1
-encoding//src/hdabo/forms.py=utf-8
-encoding//src/hdabo/management/commands/clean_tags.py=utf-8
-encoding//src/hdabo/management/commands/diff_csv.py=utf-8
-encoding//src/hdabo/management/commands/import_csv.py=utf-8
-encoding//src/hdabo/management/commands/import_tag_popularity.py=utf-8
-encoding//src/hdabo/management/commands/query_wikipedia.py=utf-8
-encoding//src/hdabo/management/utils.py=utf-8
-encoding//src/hdabo/migrations/0001_initial.py=utf-8
-encoding//src/hdabo/migrations/0002_backport_hdabo_sf.py=utf-8
-encoding//src/hdabo/migrations/0003_update_redirection.py=utf-8
-encoding//src/hdabo/migrations/0005_auto__chg_field_datasheet_organisation.py=utf-8
-encoding//src/hdabo/models.py=utf-8
-encoding//src/hdabo/search/french_whoosh_backend.py=utf-8
-encoding//src/hdabo/tests/models.py=utf-8
-encoding//src/hdabo/utils.py=utf-8
-encoding//src/hdabo/views.py=utf-8
-encoding//src/hdabo/wp_utils.py=utf-8
-encoding//src/hdalab/__init__.py=utf-8
-encoding//src/hdalab/management/commands/export_tags_csv.py=utf-8
-encoding//src/hdalab/management/commands/export_wpcategory_csv.py=utf-8
-encoding//src/hdalab/management/commands/fill_tag_years.py=utf-8
-encoding//src/hdalab/management/commands/geojson_transform.py=utf-8
-encoding//src/hdalab/management/commands/import_hda_insee_csv.py=utf-8
-encoding//src/hdalab/management/commands/import_hdabo_db.py=utf-8
-encoding//src/hdalab/management/commands/import_insee_csv.py=utf-8
-encoding//src/hdalab/management/commands/query_dbpedia.py=utf-8
-encoding//src/hdalab/management/commands/query_geo_inclusion.py=utf-8
-encoding//src/hdalab/management/commands/query_wikipedia_category.py=utf-8
-encoding//src/hdalab/management/utils.py=utf-8
-encoding//src/hdalab/migrations/0001_initial.py=utf-8
-encoding//src/hdalab/migrations/0002_dataviz.py=utf-8
-encoding//src/hdalab/migrations/0003_hdasession.py=utf-8
-encoding//src/hdalab/migrations/0005_rename_end_year.py=utf-8
-encoding//src/hdalab/migrations/0006_dbpedia_fields_one_to_one.py=utf-8
-encoding//src/hdalab/migrations/0007_geographic_inclusion.py=utf-8
-encoding//src/hdalab/migrations/0008_datasheet_insee.py=utf-8
-encoding//src/hdalab/models/dataviz.py=utf-8
-encoding//src/hdalab/settings.py=utf-8
-encoding//src/hdalab/urls.py=utf-8
-encoding//src/hdalab/utils.py=utf-8
-encoding//src/hdalab/views/ajax.py=utf-8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/haystack/backends/__init__.py=utf-8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/sortedm2m/fields.py=utf-8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/sortedm2m/forms.py=utf-8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/sortedm2m/tests.py=utf-8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/whoosh/analysis.py=utf8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/wikitools/api.py=utf-8
-encoding//virtualenv/web/env/hdabo/lib/python2.6/site-packages/wikitools/wiki.py=utf-8
-encoding//web/hdalab/config.py=utf-8
-encoding//web/hdalab/management/commands/fill_country_codes.py=utf-8
+eclipse.preferences.version=1
+encoding//data/villes.csv=ISO-8859-1
+encoding//src/hdabo/forms.py=utf-8
+encoding//src/hdabo/management/commands/clean_tags.py=utf-8
+encoding//src/hdabo/management/commands/diff_csv.py=utf-8
+encoding//src/hdabo/management/commands/import_csv.py=utf-8
+encoding//src/hdabo/management/commands/import_tag_popularity.py=utf-8
+encoding//src/hdabo/management/commands/query_wikipedia.py=utf-8
+encoding//src/hdabo/management/utils.py=utf-8
+encoding//src/hdabo/migrations/0001_initial.py=utf-8
+encoding//src/hdabo/migrations/0002_backport_hdabo_sf.py=utf-8
+encoding//src/hdabo/migrations/0003_update_redirection.py=utf-8
+encoding//src/hdabo/migrations/0005_auto__chg_field_datasheet_organisation.py=utf-8
+encoding//src/hdabo/models.py=utf-8
+encoding//src/hdabo/search/french_whoosh_backend.py=utf-8
+encoding//src/hdabo/tests/models.py=utf-8
+encoding//src/hdabo/utils.py=utf-8
+encoding//src/hdabo/views.py=utf-8
+encoding//src/hdabo/wp_utils.py=utf-8
+encoding//src/hdalab/__init__.py=utf-8
+encoding//src/hdalab/manage.py=utf-8
+encoding//src/hdalab/management/commands/export_tags_csv.py=utf-8
+encoding//src/hdalab/management/commands/export_wpcategory_csv.py=utf-8
+encoding//src/hdalab/management/commands/fill_tag_years.py=utf-8
+encoding//src/hdalab/management/commands/geojson_transform.py=utf-8
+encoding//src/hdalab/management/commands/import_hda_insee_csv.py=utf-8
+encoding//src/hdalab/management/commands/import_hdabo_db.py=utf-8
+encoding//src/hdalab/management/commands/import_insee_csv.py=utf-8
+encoding//src/hdalab/management/commands/query_category_inclusion.py=utf-8
+encoding//src/hdalab/management/commands/query_dbpedia.py=utf-8
+encoding//src/hdalab/management/commands/query_geo_inclusion.py=utf-8
+encoding//src/hdalab/management/commands/query_wikipedia_category.py=utf-8
+encoding//src/hdalab/management/utils.py=utf-8
+encoding//src/hdalab/migrations/0001_initial.py=utf-8
+encoding//src/hdalab/migrations/0002_dataviz.py=utf-8
+encoding//src/hdalab/migrations/0003_hdasession.py=utf-8
+encoding//src/hdalab/migrations/0005_rename_end_year.py=utf-8
+encoding//src/hdalab/migrations/0006_dbpedia_fields_one_to_one.py=utf-8
+encoding//src/hdalab/migrations/0007_geographic_inclusion.py=utf-8
+encoding//src/hdalab/migrations/0008_datasheet_insee.py=utf-8
+encoding//src/hdalab/models/dataviz.py=utf-8
+encoding//src/hdalab/settings.py=utf-8
+encoding//src/hdalab/urls.py=utf-8
+encoding//src/hdalab/utils.py=utf-8
+encoding//src/hdalab/views/ajax.py=utf-8
+encoding//src/hdalab/views/pages.py=utf-8
+encoding//web/hdalab/config.py=utf-8
+encoding//web/hdalab/management/commands/fill_country_codes.py=utf-8
--- a/src/hdabo/settings.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdabo/settings.py	Tue Jun 17 10:32:57 2014 +0200
@@ -118,7 +118,6 @@
 
 INSTALLED_APPS = (
     'south',              
-    'django',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
@@ -131,30 +130,6 @@
     'hdabo',
 )
 
-# A sample logging configuration. The only tangible logging
-# performed by this configuration is to send an email to
-# the site admins on every HTTP 500 error.
-# See http://docs.djangoproject.com/en/dev/topics/logging for
-# more details on how to customize your logging configuration.
-LOGGING = {
-    'version': 1,
-    'disable_existing_loggers': False,
-    'handlers': {
-        'mail_admins': {
-            'level': 'ERROR',
-            'class': 'django.utils.log.AdminEmailHandler'
-        }
-    },
-    'loggers': {
-        'django.request': {
-            'handlers': ['mail_admins'],
-            'level': 'ERROR',
-            'propagate': True,
-        },
-    }
-}
-
-#HAYSTACK_SITECONF = 'hdabo.search.sites'
 
 WIKIPEDIA_API_URL = "http://fr.wikipedia.org/w/api.php"
 WIKIPEDIA_VERSION_PERMALINK_TEMPLATE = "http://fr.wikipedia.org/w/index.php?oldid=%s"
@@ -163,9 +138,6 @@
 SEARCH_STAR_CHARACTER = "*"
 PAGINATION_DEFAULT_NB_BY_PAGE = 50
 
-# User class after migration to django > 1.6.5
-AUTH_USER_MODEL = 'hdabo.User'
-
 from hdabo.config import * #@UnusedWildImport
 
 if 'LOGIN_REDIRECT_URL' not in locals():
--- a/src/hdalab/README.txt	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/README.txt	Tue Jun 17 10:32:57 2014 +0200
@@ -26,4 +26,22 @@
 Il faut ensuite importer les fichiers donnant la correspondance entre notices HDA (référencées par leur identifiant hda_id) et codes INSEE
 Celles-ci sont fournies dans un fichier Excel donné par Bertrand, que j'ai converti en CSV et corrigé. Il s'agit de data/hda_insee.csv
 Pour importer ce fichier:
-    python manage.py import_insee_hda_csv <chemin/nom_du_fichier.csv>
\ No newline at end of file
+    python manage.py import_insee_hda_csv <chemin/nom_du_fichier.csv>
+    
+    
+=== Migration hdabo -> hdalab ===
+
+0) appliquer les migrations south
+1) lancement de la commande query_wikipedia_category
+2) lancement de la commande fill_tag_years
+3) lancement de la commande query_wikipedia
+4) lancement de la commande query_geo_inclusion
+5) lancement de la commande geo_json_transform
+6) lancement de la commande import_insee_csv
+7) lancement de la commande import_hda_insee_csv
+8) lancement de la commande query_category_inclusion
+
+Toutes ces actions sont echaînées dans la commande import_hdabo_db
+
+
+
--- a/src/hdalab/__init__.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/__init__.py	Tue Jun 17 10:32:57 2014 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-VERSION = (2, 12, 0, "final", 0)
+VERSION = (2, 22, 0, "final", 0)
 
 
 def get_version():
Binary file src/hdalab/locale/de/LC_MESSAGES/django.mo has changed
--- a/src/hdalab/locale/de/LC_MESSAGES/django.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/de/LC_MESSAGES/django.po	Tue Jun 17 10:32:57 2014 +0200
@@ -124,3 +124,7 @@
 #: templates/facettes.html:152
 msgid "Resultats de recherche"
 msgstr "Suchergebnisse"
+
+#: templates/completion.html:37
+msgid "Recherche par liste de completion"
+msgstr "Autovervollständigen Suche"
Binary file src/hdalab/locale/de/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/de/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/de/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -111,3 +111,11 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "Neue Liste"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "Quelle: Wikipedia"
+
+#: static/hdalab/js/completion.js:20
+msgid "Localisation&nbsp;:"
+msgstr "Standort:"
Binary file src/hdalab/locale/en/LC_MESSAGES/django.mo has changed
--- a/src/hdalab/locale/en/LC_MESSAGES/django.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/en/LC_MESSAGES/django.po	Tue Jun 17 10:32:57 2014 +0200
@@ -71,7 +71,7 @@
 
 #: templates/facettes.html:73
 msgid "Creer une vue sur des resultats de recherche"
-msgstr "Create a view on research results"
+msgstr "Create a view on search results"
 
 #: templates/facettes.html:74
 msgid "Creer une liste de notices"
@@ -124,3 +124,7 @@
 #: templates/facettes.html:152
 msgid "Resultats de recherche"
 msgstr "Search results"
+
+#: templates/completion.html:37
+msgid "Recherche par liste de completion"
+msgstr "Autocomplete Search"
Binary file src/hdalab/locale/en/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/en/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/en/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -109,3 +109,11 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "New list"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "Source: Wikipedia"
+
+#: static/hdalab/js/completion.js:20
+msgid "Localisation&nbsp;:"
+msgstr "Location:"
Binary file src/hdalab/locale/es/LC_MESSAGES/django.mo has changed
--- a/src/hdalab/locale/es/LC_MESSAGES/django.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/es/LC_MESSAGES/django.po	Tue Jun 17 10:32:57 2014 +0200
@@ -124,3 +124,7 @@
 #: templates/facettes.html:152
 msgid "Resultats de recherche"
 msgstr "Resultados de búsqueda"
+
+#: templates/completion.html:37
+msgid "Recherche par liste de completion"
+msgstr "Busqueda con autocompletar"
Binary file src/hdalab/locale/es/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/es/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/es/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -110,3 +110,11 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "Nueva lista"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "Fuente: Wikipedia"
+
+#: static/hdalab/js/completion.js:20
+msgid "Localisation&nbsp;:"
+msgstr "Localización:"
Binary file src/hdalab/locale/fr/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/fr/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/fr/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -110,3 +110,11 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "Nouvelle liste"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "Source&nbsp;: Wikipédia"
+
+#: static/hdalab/js/completion.js:20
+msgid "Localisation&nbsp;:"
+msgstr "Localisation&nbsp;:"
Binary file src/hdalab/locale/it/LC_MESSAGES/django.mo has changed
--- a/src/hdalab/locale/it/LC_MESSAGES/django.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/it/LC_MESSAGES/django.po	Tue Jun 17 10:32:57 2014 +0200
@@ -124,3 +124,7 @@
 #: templates/facettes.html:152
 msgid "Resultats de recherche"
 msgstr "Risultati della ricerca"
+
+#: templates/completion.html:37
+msgid "Recherche par liste de completion"
+msgstr "Ricerca con autocompletamento"
Binary file src/hdalab/locale/it/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/it/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/it/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -111,3 +111,11 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "Nuovo elenco"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "Fonte: Wikipedia"
+
+#: static/hdalab/js/completion.js:20
+msgid "Localisation&nbsp;:"
+msgstr "Localizzazione:"
--- a/src/hdalab/locale/ja/LC_MESSAGES/django.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/ja/LC_MESSAGES/django.po	Tue Jun 17 10:32:57 2014 +0200
@@ -3,7 +3,6 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
-#, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
@@ -20,23 +19,23 @@
 
 #: settings.py:40
 msgid "French"
-msgstr ""
+msgstr "フランス語"
 
 #: settings.py:41
 msgid "English"
-msgstr ""
+msgstr "英語"
 
 #: settings.py:42
 msgid "Italian"
-msgstr ""
+msgstr "イタリア語"
 
 #: settings.py:43
 msgid "German"
-msgstr ""
+msgstr "ドイツ語"
 
 #: settings.py:44
 msgid "Spanish"
-msgstr ""
+msgstr "スペイン語"
 
 #: settings.py:45
 msgid "Japanese"
@@ -44,7 +43,7 @@
 
 #: settings.py:46
 msgid "Chinese"
-msgstr ""
+msgstr "中国語"
 
 
 #: templates/facettes.html:5 templates/facettes.html.py:42
Binary file src/hdalab/locale/ja/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/ja/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/ja/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -3,7 +3,6 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
-#, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
@@ -111,3 +110,11 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "名称未設定のリスト"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "ウィキペディア"
+
+#: static/hdalab/js/completion.js:20
+msgid "Localisation&nbsp;:"
+msgstr "Location:"
Binary file src/hdalab/locale/zh-tw/LC_MESSAGES/djangojs.mo has changed
--- a/src/hdalab/locale/zh-tw/LC_MESSAGES/djangojs.po	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/locale/zh-tw/LC_MESSAGES/djangojs.po	Tue Jun 17 10:32:57 2014 +0200
@@ -112,3 +112,7 @@
 #: static/hdalab/js/gomina.js:920
 msgid "Nouvelle liste"
 msgstr "Nouvelle liste"
+
+#: static/hdalab/js/completion.js:73
+msgid "Source&nbsp;: Wikipédia"
+msgstr "Source&nbsp;: Wikipédia"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/manage.py	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from django.core.management import execute_manager
+import imp
+try:
+    imp.find_module('settings') # Assumed to be in the same directory.
+except ImportError:
+    import sys
+    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
+    sys.exit(1)
+
+import settings
+
+if __name__ == "__main__":
+    execute_manager(settings)
--- a/src/hdalab/management/commands/import_hda_insee_csv.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/management/commands/import_hda_insee_csv.py	Tue Jun 17 10:32:57 2014 +0200
@@ -44,7 +44,7 @@
                             minlength = max(j,minlength)
             else:
                 if len(line) > minlength:
-                    rawdata = {k: line[v].strip() for k,v in fields.iteritems()}
+                    rawdata = dict([(k,line[v].strip()) for k,v in fields.iteritems()])
                     # Traitement special pour la Corse
                     insee = int(re.sub('^2(A|B)','20',rawdata['insee']))
                         
--- a/src/hdalab/management/commands/import_hdabo_db.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/management/commands/import_hdabo_db.py	Tue Jun 17 10:32:57 2014 +0200
@@ -29,15 +29,27 @@
         else:
             data_path = args[0]
         
-        call_command('migrate')
+        print("===========  MIGRATE ===========")
+        call_command('syncdb', migrate=True)
         if options.get('categories', False):
-            call_command('query_wikipedia_category')
-                
-        call_command('query_dbpedia')
+            print("===========  QUERY WIKIPEDIA CATEGORY ===========")
+            call_command('query_wikipedia_category', interactive=False, force=True)
+
+        print("===========  QUERY DBPEDIA ===========")                
+        call_command('query_dbpedia', interactive=False, force=True)
+        print("===========  FILL TAG YEAR ===========")
         call_command('fill_tag_years')
+        print("===========  GEOJSON TRANSFORM ===========")
+        call_command('geojson_transform', os.path.join(data_path,'countries.geo.json'))
+        print("===========  QUERY GEO INCLUSION ===========")
         call_command('query_geo_inclusion')
+        print("===========  IMPORT INSEE CSV PASS 1 ===========")
         call_command('import_insee_csv', os.path.join(data_path,'villes.csv'))
+        print("===========  IMPORT INSEE CSV PASS 2 ===========")
         call_command('import_insee_csv', os.path.join(data_path,'additional_cities.csv'))
+        print("===========  IMPORT HDA INSEE CSV ===========")
         call_command('import_hda_insee_csv', os.path.join(data_path,'HDA_Insee.csv'))
+        print("===========  QUERY CATEGORY INCLUSION ===========")
+        call_command('query_category_inclusion', all=True, force=True, interactive=False)
         
         
\ No newline at end of file
--- a/src/hdalab/management/commands/import_insee_csv.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/management/commands/import_insee_csv.py	Tue Jun 17 10:32:57 2014 +0200
@@ -42,7 +42,7 @@
                             minlength = max(j,minlength)
             else:
                 if len(line) > minlength:
-                    rawdata = {k: line[v].strip() for k,v in fields.iteritems()}
+                    rawdata = dict([(k,line[v].strip()) for k,v in fields.iteritems()])
                     #print "Processing line %d" % i
                     #print rawdata
                     try:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/management/commands/query_category_inclusion.py	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+'''
+Created on July 2, 2012
+
+@author: raphv
+'''
+
+from django.conf import settings
+from django.core.management.base import NoArgsCommand
+from django.core.management.color import no_style
+from hdalab.models import WpCategory, WpCategoryInclusion
+from optparse import make_option
+from wikitools import api,wiki
+import sys
+import re
+import itertools
+from hdabo import utils
+from django.db.models import Count
+from django.db import transaction
+
+CATEGORY_PREFIX = u'Catégorie:'
+
+class Command(NoArgsCommand):
+    '''
+    query and update wikipedia for tag title.
+    '''
+    options = ''
+    help = """query and update wikipedia for tag title."""
+    
+    option_list = NoArgsCommand.option_list + (
+        make_option('--all',
+            action='store_true',
+            dest='all',
+            default=False,
+            help='force all categories to be updated, not only those not yet processed'),
+        make_option('--force',
+            action='store_true',
+            dest='force',
+            default=False,
+            help='ask no questions'),
+        make_option('--site',
+            action='store',
+            type='string',
+            dest='site_url',
+            default="http://fr.wikipedia.org/w/api.php",
+            help='the url for the wikipedia site'),
+        make_option('--limit',
+            action='store',
+            type='int',
+            dest='limit',
+            default= -1,
+            help='number of categories to process'),
+        make_option('--start',
+            action='store',
+            type='int',
+            dest='start',
+            default=0,
+            help='number of categories to ignore'),
+        make_option('--category',
+            action='append',
+            dest='category',
+            type='string',
+            default=[],
+            help='the categories to query'),
+
+    )
+
+
+    def query_all_categories(self, category_title, site):
+        
+        params = {'action':'query', 'cmtitle':category_title, 'list':'categorymembers', 'cmlimit': 'max'}
+        
+        res = []
+        
+        wpquery = api.APIRequest(site, params) #@UndefinedVariable
+        response = wpquery.query()
+        
+        if self.verbosity > 1:
+            print "Query category : " + repr(wpquery.request.get_full_url()+"?"+wpquery.request.get_data())
+            print repr(response)
+        
+        members = response.get('query', {}).get('categorymembers', [])
+                    
+        for member in members:
+            title = member.get('title',"")
+            if re.match(CATEGORY_PREFIX, title):
+                res.append(re.sub(CATEGORY_PREFIX, "", title))
+            
+        if self.verbosity > 1:
+            print "Query categories result: "
+            print repr(res)
+            
+        return res
+    
+    def process_categories(self, cat_list, parent_cat):
+        for cat in cat_list:
+            child_cat,created = WpCategory.objects.get_or_create(label=cat) #@UnusedVariable
+            WpCategoryInclusion.objects.get_or_create(parent_category=parent_cat, child_category=child_cat)
+        
+    def handle_noargs(self, **options):
+        
+        self.style = no_style()
+        
+        interactive = options.get('interactive', True)
+        
+        self.verbosity = int(options.get('verbosity', '1'))
+        
+        force = options.get('force', False)
+        
+        limit = options.get("limit", -1)
+        start = options.get("start", 0)
+        
+        site_url = options.get('site_url', settings.WIKIPEDIA_API_URL)
+        
+        types_mask = 0
+        
+        if self.verbosity > 2:
+            print "option passed : " + repr(options)
+
+        queryset = WpCategory.objects.filter(tags__hidden = False).distinct()
+        
+        cat_list = options.get("category", []);
+        
+        if cat_list:
+            queryset = queryset.filter(label__in=cat_list)
+        elif options.get('all',False):            
+            queryset = queryset.annotate(wpc=Count('child_categories')).filter(wpc = 0)                    
+        
+        queryset = queryset.order_by("label")
+        
+        if limit >= 0:
+            queryset = queryset[start:limit]
+        elif start > 0:
+            queryset = queryset[start:]            
+        
+        if self.verbosity > 2 :
+            print "Category Query is %s" % (queryset.query)
+        
+        site = wiki.Wiki(site_url) #@UndefinedVariable
+        
+        
+        count = queryset.count()
+        if self.verbosity > 1:
+            print "Processing %d categories" % (count)
+        
+        if not force and interactive:
+            confirm = raw_input("You have requested to query and replace the wikipedia information for %d categories.\n Are you sure you want to do this? \nType 'yes' to continue, or 'no' to cancel: " % (count))
+        else:
+            confirm = 'yes'
+            
+        if confirm != "yes":
+            print "wikipedia query cancelled"
+            return
+        
+        for i, category in enumerate(queryset):
+            
+            if self.verbosity > 1:
+                print "processing category %s (%d/%d)" % (category.label, i + 1, count)
+            else:
+                utils.show_progress(i + 1, count, category.label, 60)                            
+                
+            title = CATEGORY_PREFIX + category.label
+            # query categories
+
+            with transaction.commit_on_success():
+                res = self.query_all_categories(title, site)
+                self.process_categories(res, category)
\ No newline at end of file
--- a/src/hdalab/management/commands/query_dbpedia.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/management/commands/query_dbpedia.py	Tue Jun 17 10:32:57 2014 +0200
@@ -17,11 +17,11 @@
 from hdabo.utils import show_progress
 from rdflib.graph import Graph
 from rdflib import URIRef
-import re
 import traceback
 import sys
 from hdalab.models.dataviz import DbpediaFieldsTranslation
 from django import db
+from SPARQLWrapper import SPARQLWrapper, RDF
 
 class Command(NoArgsCommand):
     '''
@@ -123,41 +123,54 @@
             print "dbpedia query cancelled"
             return
 
+        endpoint = SPARQLWrapper("http://dbpedia.org/sparql", returnFormat=RDF)
+
         writer = None
         for i,tag in enumerate(queryset):
             writer = show_progress(i+1, count, tag.label, 50, writer)
             db.reset_queries()
-            rdf_uri = re.sub('\/resource\/', "/data/", tag.dbpedia_uri) + ".n3"            
-            g = Graph()
+            
+            #abstract query
+            #"select ?y
+            # where {<%s>  <http://dbpedia.org/ontology/abstract> ?y}" % (tag.dbpedia_uri)
+            
+            #rdf_uri = re.sub('\/resource\/', "/data/", tag.dbpedia_uri) + ".n3"            
+            #g = Graph()
             try :
-                g.parse(rdf_uri, format="n3")
-            
+                abstracts = {}
+                labels = {}
+                thumbnail = None
                 with transaction.commit_on_success():
+                    endpoint.setQuery("select distinct ?y where {<%s>  <http://dbpedia.org/ontology/abstract> ?y}" % (tag.dbpedia_uri))
+                    res_abstracts = endpoint.queryAndConvert()
+                    for _,_,o in res_abstracts.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
+                        abstracts[o.language] = (unicode(o), True)
+
+                    endpoint.setQuery("select distinct ?y where {<%s>  <http://www.w3.org/2000/01/rdf-schema#label> ?y}" % (tag.dbpedia_uri))
+                    res_labels = endpoint.queryAndConvert()
+                    for _,_,o in res_labels.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
+                        labels[o.language] = (unicode(o), True)
+                            
+                    endpoint.setQuery("select distinct ?y where {<%s>  <http://dbpedia.org/ontology/thumbnail> ?y} limit 1" % (tag.dbpedia_uri))
+                    res_thumbnails = endpoint.queryAndConvert()
+                    for _,_,o in res_thumbnails.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
+                        thumbnail = unicode(o)
+
+                    endpoint.setQuery('select distinct ?y where { <%s> ?p ?y . FILTER regex(?y, "^http://dbpedia.org/resource")}' % (tag.dbpedia_uri))
+                    res_links = endpoint.queryAndConvert()
+                    for _,_,o in res_links.triples((None, URIRef('http://www.w3.org/2005/sparql-results#value'), None)):
+                        tagqs = Tag.objects.filter(dbpedia_uri=unicode(o))
+                        if tagqs:
+                            TagLinks.objects.get_or_create(subject=tag, object=tagqs[0])                        
                     
-                    abstracts = {}
-                    labels = {}
-                    thumbnail = None
-                    for t in g:
-                        if t[1] == URIRef(u'http://dbpedia.org/ontology/abstract') and t[2] is not None \
-                            and hasattr(t[2], 'language'):
-                            abstracts[t[2].language] = unicode(t[2])
-                        if t[1] ==  URIRef(u'http://www.w3.org/2000/01/rdf-schema#label') and t[2] is not None \
-                            and hasattr(t[2], 'language'):
-                            labels[t[2].language] = unicode(t[2]) 
-                        if t[1] == URIRef(u'http://dbpedia.org/ontology/thumbnail') and t[2] is not None:
-                            thumbnail = unicode(t[2])
-                        if u'http://dbpedia.org/resource' in t[2]:
-                            tagqs = Tag.objects.filter(dbpedia_uri=unicode(t[2]))
-                            if tagqs:
-                                TagLinks.objects.get_or_create(subject=tag, object=tagqs[0])                        
-                    
-                    ref_label = labels['fr'] if 'fr' in labels else labels['en'] if 'en' in labels else labels.values()[0] if len(labels) > 0 else tag.label
-                    ref_abstract = abstracts['fr'] if 'fr' in abstracts else abstracts['en'] if 'en' in abstracts else abstracts.values()[0] if len(abstracts) > 0 else None
+                    ref_label_lang, (ref_label, _) = ('fr',labels['fr']) if 'fr' in labels else ('en',labels['en']) if 'en' in labels else labels.items()[0] if len(labels) > 0 else ('fr',(tag.label, True))
+                    ref_abstract_lang, (ref_abstract, _) = ('fr',abstracts['fr']) if 'fr' in abstracts else ('en',abstracts['en']) if 'en' in abstracts else abstracts.items()[0] if len(abstracts) > 0 else ('fr',(None, 'True'))
+
                     for lang in settings.LANGUAGES:
                         if lang[0] not in labels:
-                            labels[lang[0]]= ref_label
+                            labels[lang[0]]= (ref_label, False)
                         if lang[0] not in abstracts:
-                            abstracts[lang[0]] = ref_abstract
+                            abstracts[lang[0]] = (ref_abstract, False)
 
                     dbfield , created = DbpediaFields.objects.get_or_create(dbpedia_uri=tag.dbpedia_uri,tag=tag, defaults={'abstract':ref_abstract, 'thumbnail':thumbnail, 'label':ref_label}) #@UndefinedVariable                    
                     if not created:
@@ -169,16 +182,16 @@
 
                     consolidated_trans = {}
                     for lang,label in labels.iteritems():
-                        consolidated_trans[lang] = [label,ref_abstract]
+                        consolidated_trans[lang] = [label,(ref_abstract, lang==ref_abstract_lang)]
                     for lang,abstract in abstracts.iteritems():
                         if lang in consolidated_trans:
                             consolidated_trans[lang][1] = abstract
                         else:
-                            consolidated_trans[lang] = [ref_label, abstract] 
+                            consolidated_trans[lang] = [(ref_label, lang==ref_label_lang), abstract] 
                          
                     for lang, trans in consolidated_trans.iteritems():
                         label, abstract = tuple(trans)
-                        DbpediaFieldsTranslation.objects.create(master=dbfield, language_code=lang, label=label, abstract=abstract)
+                        DbpediaFieldsTranslation.objects.create(master=dbfield, language_code=lang, label=label[0], is_label_translated=label[1], abstract=abstract[0], is_abstract_translated=abstract[1])
                     
                     
             except Exception as e:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/migrations/0010_categoryinclusion.py	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,312 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding model 'WpCategoryInclusion'
+        db.create_table('hdalab_wpcategoryinclusion', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('parent_category', self.gf('django.db.models.fields.related.ForeignKey')(related_name='child_categories', to=orm['hdalab.WpCategory'])),
+            ('child_category', self.gf('django.db.models.fields.related.ForeignKey')(related_name='parent_categories', to=orm['hdalab.WpCategory'])),
+        ))
+        db.send_create_signal('hdalab', ['WpCategoryInclusion'])
+
+        # Adding unique constraint on 'WpCategoryInclusion', fields ['parent_category', 'child_category']
+        db.create_unique('hdalab_wpcategoryinclusion', ['parent_category_id', 'child_category_id'])
+
+
+    def backwards(self, orm):
+        
+        # Removing unique constraint on 'WpCategoryInclusion', fields ['parent_category', 'child_category']
+        db.delete_unique('hdalab_wpcategoryinclusion', ['parent_category_id', 'child_category_id'])
+
+        # Deleting model 'WpCategoryInclusion'
+        db.delete_table('hdalab_wpcategoryinclusion')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 7, 2, 5, 14, 31, 895549)'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 7, 2, 5, 14, 31, 895384)'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'hdabo.author': {
+            'Meta': {'object_name': 'Author'},
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'hda_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.datasheet': {
+            'Meta': {'object_name': 'Datasheet'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Author']", 'null': 'True', 'blank': 'True'}),
+            'college_periods': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'college_periods_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_college_periods']", 'to': "orm['hdabo.TimePeriod']"}),
+            'college_themes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'college_themes_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_college_themes']", 'to': "orm['hdabo.Domain']"}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'domains': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_domains']", 'to': "orm['hdabo.Domain']"}),
+            'format': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.DocumentFormat']", 'null': 'True', 'blank': 'True'}),
+            'hda_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
+            'highschool_periods': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'highschool_periods_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_highschool_periods']", 'to': "orm['hdabo.TimePeriod']"}),
+            'highschool_themes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'highschool_themes_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_highschool_themes']", 'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'manual_order': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'modification_datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Organisation']", 'null': 'True'}),
+            'original_creation_date': ('django.db.models.fields.DateField', [], {}),
+            'original_modification_date': ('django.db.models.fields.DateField', [], {}),
+            'primary_periods': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'primary_periods_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_primary_periods']", 'to': "orm['hdabo.TimePeriod']"}),
+            'primary_themes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'primary_themes_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_primary_themes']", 'to': "orm['hdabo.Domain']"}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['hdabo.Tag']", 'through': "orm['hdabo.TaggedSheet']", 'symmetrical': 'False'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'town': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Location']", 'null': 'True', 'blank': 'True'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'validated': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'validation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'validator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.datasheet_college_periods': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_college_periods'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {}),
+            'timeperiod': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TimePeriod']"})
+        },
+        'hdabo.datasheet_college_themes': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_college_themes'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.datasheet_domains': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_domains'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.datasheet_highschool_periods': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_highschool_periods'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {}),
+            'timeperiod': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TimePeriod']"})
+        },
+        'hdabo.datasheet_highschool_themes': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_highschool_themes'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.datasheet_primary_periods': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_primary_periods'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {}),
+            'timeperiod': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TimePeriod']"})
+        },
+        'hdabo.datasheet_primary_themes': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_primary_themes'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.documentformat': {
+            'Meta': {'object_name': 'DocumentFormat'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'})
+        },
+        'hdabo.domain': {
+            'Meta': {'unique_together': "(('label', 'school_period'),)", 'object_name': 'Domain'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'school_period': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.location': {
+            'Meta': {'object_name': 'Location'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '5'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'})
+        },
+        'hdabo.organisation': {
+            'Meta': {'object_name': 'Organisation'},
+            'hda_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'website': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.tag': {
+            'Meta': {'unique_together': "(('label', 'original_label', 'url_status'),)", 'object_name': 'Tag'},
+            'alias': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'alternative_label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'alternative_wikipedia_pageid': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'alternative_wikipedia_url': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TagCategory']", 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+            'normalized_label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+            'original_label': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'popularity': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'url_status': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'wikipedia_pageid': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'wikipedia_url': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.tagcategory': {
+            'Meta': {'object_name': 'TagCategory'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'})
+        },
+        'hdabo.taggedsheet': {
+            'Meta': {'object_name': 'TaggedSheet'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'index_note': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}),
+            'order': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'original_order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Tag']"}),
+            'wikipedia_revision_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.timeperiod': {
+            'Meta': {'unique_together': "(('label', 'school_period'),)", 'object_name': 'TimePeriod'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'school_period': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdalab.country': {
+            'Meta': {'object_name': 'Country'},
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'hdalab.datasheetextras': {
+            'Meta': {'object_name': 'DatasheetExtras'},
+            'datasheet': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'extras'", 'unique': 'True', 'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'insee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdalab.InseeCoords']", 'null': 'True', 'blank': 'True'})
+        },
+        'hdalab.dbpediafields': {
+            'Meta': {'object_name': 'DbpediaFields'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'tag': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'dbpedia_fields'", 'unique': 'True', 'null': 'True', 'to': "orm['hdabo.Tag']"}),
+            'thumbnail': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'hdalab.dbpediafieldstranslation': {
+            'Meta': {'unique_together': "(('master', 'language_code'),)", 'object_name': 'DbpediaFieldsTranslation'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
+            'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'to': "orm['hdalab.DbpediaFields']"})
+        },
+        'hdalab.geoinclusion': {
+            'Meta': {'object_name': 'GeoInclusion'},
+            'country': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'includes'", 'to': "orm['hdalab.Country']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'tag': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'locatedin'", 'unique': 'True', 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.hdasession': {
+            'Meta': {'object_name': 'HdaSession'},
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sessionid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36', 'db_index': 'True'})
+        },
+        'hdalab.infoboxparameter': {
+            'Meta': {'unique_together': "(('tag_infobox', 'param_name'),)", 'object_name': 'InfoboxParameter'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'param_name': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'param_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'tag_infobox': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdalab.TagInfobox']"})
+        },
+        'hdalab.inseecoords': {
+            'Meta': {'object_name': 'InseeCoords'},
+            'city_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'insee': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
+            'latitude': ('django.db.models.fields.FloatField', [], {}),
+            'longitude': ('django.db.models.fields.FloatField', [], {})
+        },
+        'hdalab.taginfobox': {
+            'Meta': {'unique_together': "(('tag', 'name', 'revision_id'),)", 'object_name': 'TagInfobox'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'revision_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'source': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'infoboxes'", 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.taglinks': {
+            'Meta': {'object_name': 'TagLinks'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taglinks_objects'", 'to': "orm['hdabo.Tag']"}),
+            'subject': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taglinks_subjects'", 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.tagwpcategory': {
+            'Meta': {'unique_together': "(('tag', 'wp_category', 'hidden'),)", 'object_name': 'TagWpCategory'},
+            'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wp_categories'", 'to': "orm['hdabo.Tag']"}),
+            'wp_category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdalab.WpCategory']"})
+        },
+        'hdalab.tagyears': {
+            'Meta': {'object_name': 'TagYears'},
+            'end_year': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'start_year': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'years'", 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.wpcategory': {
+            'Meta': {'object_name': 'WpCategory'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048'})
+        },
+        'hdalab.wpcategoryinclusion': {
+            'Meta': {'unique_together': "(('parent_category', 'child_category'),)", 'object_name': 'WpCategoryInclusion'},
+            'child_category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parent_categories'", 'to': "orm['hdalab.WpCategory']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'parent_category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'child_categories'", 'to': "orm['hdalab.WpCategory']"})
+        }
+    }
+
+    complete_apps = ['hdalab']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/migrations/0011_auto__add_field_dbpediafieldstranslation_is_label_translated__add_fiel.py	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,309 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Adding field 'DbpediaFieldsTranslation.is_label_translated'
+        db.add_column('hdalab_dbpediafieldstranslation', 'is_label_translated', self.gf('django.db.models.fields.BooleanField')(default=True), keep_default=False)
+
+        # Adding field 'DbpediaFieldsTranslation.is_abstract_translated'
+        db.add_column('hdalab_dbpediafieldstranslation', 'is_abstract_translated', self.gf('django.db.models.fields.BooleanField')(default=True), keep_default=False)
+
+
+    def backwards(self, orm):
+        
+        # Deleting field 'DbpediaFieldsTranslation.is_label_translated'
+        db.delete_column('hdalab_dbpediafieldstranslation', 'is_label_translated')
+
+        # Deleting field 'DbpediaFieldsTranslation.is_abstract_translated'
+        db.delete_column('hdalab_dbpediafieldstranslation', 'is_abstract_translated')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 9, 6, 7, 27, 20, 166066)'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 9, 6, 7, 27, 20, 165955)'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'hdabo.author': {
+            'Meta': {'object_name': 'Author'},
+            'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'hda_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.datasheet': {
+            'Meta': {'object_name': 'Datasheet'},
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Author']", 'null': 'True', 'blank': 'True'}),
+            'college_periods': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'college_periods_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_college_periods']", 'to': "orm['hdabo.TimePeriod']"}),
+            'college_themes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'college_themes_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_college_themes']", 'to': "orm['hdabo.Domain']"}),
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'domains': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_domains']", 'to': "orm['hdabo.Domain']"}),
+            'format': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.DocumentFormat']", 'null': 'True', 'blank': 'True'}),
+            'hda_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
+            'highschool_periods': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'highschool_periods_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_highschool_periods']", 'to': "orm['hdabo.TimePeriod']"}),
+            'highschool_themes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'highschool_themes_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_highschool_themes']", 'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'manual_order': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'modification_datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Organisation']", 'null': 'True'}),
+            'original_creation_date': ('django.db.models.fields.DateField', [], {}),
+            'original_modification_date': ('django.db.models.fields.DateField', [], {}),
+            'primary_periods': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'primary_periods_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_primary_periods']", 'to': "orm['hdabo.TimePeriod']"}),
+            'primary_themes': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'primary_themes_datasheets'", 'symmetrical': 'False', 'through': "orm['hdabo.Datasheet_primary_themes']", 'to': "orm['hdabo.Domain']"}),
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['hdabo.Tag']", 'through': "orm['hdabo.TaggedSheet']", 'symmetrical': 'False'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'town': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Location']", 'null': 'True', 'blank': 'True'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'validated': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'validation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'validator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.datasheet_college_periods': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_college_periods'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {}),
+            'timeperiod': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TimePeriod']"})
+        },
+        'hdabo.datasheet_college_themes': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_college_themes'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.datasheet_domains': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_domains'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.datasheet_highschool_periods': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_highschool_periods'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {}),
+            'timeperiod': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TimePeriod']"})
+        },
+        'hdabo.datasheet_highschool_themes': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_highschool_themes'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.datasheet_primary_periods': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_primary_periods'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {}),
+            'timeperiod': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TimePeriod']"})
+        },
+        'hdabo.datasheet_primary_themes': {
+            'Meta': {'ordering': "['sort_value']", 'object_name': 'Datasheet_primary_themes'},
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Domain']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sort_value': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.documentformat': {
+            'Meta': {'object_name': 'DocumentFormat'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'})
+        },
+        'hdabo.domain': {
+            'Meta': {'unique_together': "(('label', 'school_period'),)", 'object_name': 'Domain'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'school_period': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdabo.location': {
+            'Meta': {'object_name': 'Location'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '5'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'})
+        },
+        'hdabo.organisation': {
+            'Meta': {'object_name': 'Organisation'},
+            'hda_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'website': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.tag': {
+            'Meta': {'unique_together': "(('label', 'original_label', 'url_status'),)", 'object_name': 'Tag'},
+            'alias': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'alternative_label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'alternative_wikipedia_pageid': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'alternative_wikipedia_url': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.TagCategory']", 'null': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+            'normalized_label': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+            'original_label': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
+            'popularity': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'url_status': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'wikipedia_pageid': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'wikipedia_url': ('django.db.models.fields.URLField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.tagcategory': {
+            'Meta': {'object_name': 'TagCategory'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'})
+        },
+        'hdabo.taggedsheet': {
+            'Meta': {'object_name': 'TaggedSheet'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'datasheet': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'index_note': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}),
+            'order': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'original_order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdabo.Tag']"}),
+            'wikipedia_revision_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'})
+        },
+        'hdabo.timeperiod': {
+            'Meta': {'unique_together': "(('label', 'school_period'),)", 'object_name': 'TimePeriod'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'school_period': ('django.db.models.fields.IntegerField', [], {})
+        },
+        'hdalab.country': {
+            'Meta': {'object_name': 'Country'},
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'hdalab.datasheetextras': {
+            'Meta': {'object_name': 'DatasheetExtras'},
+            'datasheet': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'extras'", 'unique': 'True', 'to': "orm['hdabo.Datasheet']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'insee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdalab.InseeCoords']", 'null': 'True', 'blank': 'True'})
+        },
+        'hdalab.dbpediafields': {
+            'Meta': {'object_name': 'DbpediaFields'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'dbpedia_uri': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            'tag': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'dbpedia_fields'", 'unique': 'True', 'null': 'True', 'to': "orm['hdabo.Tag']"}),
+            'thumbnail': ('django.db.models.fields.URLField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'})
+        },
+        'hdalab.dbpediafieldstranslation': {
+            'Meta': {'unique_together': "(('master', 'language_code'),)", 'object_name': 'DbpediaFieldsTranslation'},
+            'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_abstract_translated': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_label_translated': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
+            'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'to': "orm['hdalab.DbpediaFields']"})
+        },
+        'hdalab.geoinclusion': {
+            'Meta': {'object_name': 'GeoInclusion'},
+            'country': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'includes'", 'to': "orm['hdalab.Country']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'tag': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'locatedin'", 'unique': 'True', 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.hdasession': {
+            'Meta': {'object_name': 'HdaSession'},
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sessionid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36', 'db_index': 'True'})
+        },
+        'hdalab.infoboxparameter': {
+            'Meta': {'unique_together': "(('tag_infobox', 'param_name'),)", 'object_name': 'InfoboxParameter'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'param_name': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'param_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'tag_infobox': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['hdalab.TagInfobox']"})
+        },
+        'hdalab.inseecoords': {
+            'Meta': {'object_name': 'InseeCoords'},
+            'city_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'insee': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
+            'latitude': ('django.db.models.fields.FloatField', [], {}),
+            'longitude': ('django.db.models.fields.FloatField', [], {})
+        },
+        'hdalab.taginfobox': {
+            'Meta': {'unique_together': "(('tag', 'name', 'revision_id'),)", 'object_name': 'TagInfobox'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'revision_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'source': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'infoboxes'", 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.taglinks': {
+            'Meta': {'object_name': 'TagLinks'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taglinks_objects'", 'to': "orm['hdabo.Tag']"}),
+            'subject': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taglinks_subjects'", 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.tagwpcategory': {
+            'Meta': {'unique_together': "(('tag', 'wp_category', 'hidden'),)", 'object_name': 'TagWpCategory'},
+            'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wp_categories'", 'to': "orm['hdabo.Tag']"}),
+            'wp_category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tags'", 'to': "orm['hdalab.WpCategory']"})
+        },
+        'hdalab.tagyears': {
+            'Meta': {'object_name': 'TagYears'},
+            'end_year': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'start_year': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'years'", 'to': "orm['hdabo.Tag']"})
+        },
+        'hdalab.wpcategory': {
+            'Meta': {'object_name': 'WpCategory'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048'})
+        },
+        'hdalab.wpcategoryinclusion': {
+            'Meta': {'unique_together': "(('parent_category', 'child_category'),)", 'object_name': 'WpCategoryInclusion'},
+            'child_category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parent_categories'", 'to': "orm['hdalab.WpCategory']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'parent_category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'child_categories'", 'to': "orm['hdalab.WpCategory']"})
+        }
+    }
+
+    complete_apps = ['hdalab']
--- a/src/hdalab/models/__init__.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/models/__init__.py	Tue Jun 17 10:32:57 2014 +0200
@@ -1,5 +1,5 @@
 from hdalab.models.categories import (WpCategory, InfoboxParameter, TagInfobox, 
-    TagWpCategory)
-from hdalab.models.dataviz import TagYears, Country, GeoInclusion, TagLinks, DbpediaFields, HdaSession, InseeCoords, DatasheetExtras
+    TagWpCategory, WpCategoryInclusion)
+from hdalab.models.dataviz import TagYears, Country, GeoInclusion, TagLinks, DbpediaFields, HdaSession, InseeCoords, DatasheetExtras, DbpediaFieldsTranslation
 
-__all__ = ['WpCategory', 'InfoboxParameter', 'TagInfobox', 'TagWpCategory', 'TagYears', 'Country', 'GeoInclusion', 'TagLinks', 'DbpediaFields', 'HdaSession', 'InseeCoords', 'DatasheetExtras']
\ No newline at end of file
+__all__ = ['WpCategory', 'InfoboxParameter', 'TagInfobox', 'TagWpCategory', 'TagYears', 'Country', 'GeoInclusion', 'TagLinks', 'DbpediaFields', 'DbpediaFieldsTranslation', 'HdaSession', 'InseeCoords', 'DatasheetExtras', 'WpCategoryInclusion']
\ No newline at end of file
--- a/src/hdalab/models/categories.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/models/categories.py	Tue Jun 17 10:32:57 2014 +0200
@@ -19,7 +19,7 @@
 
 class TagWpCategory(models.Model):
     tag = models.ForeignKey(Tag, related_name="wp_categories")
-    wp_category = models.ForeignKey(WpCategory)
+    wp_category = models.ForeignKey(WpCategory, related_name="tags")
     hidden = models.BooleanField(blank=False, null=False)
     
     class Meta:
@@ -44,3 +44,13 @@
     class Meta:
         app_label = 'hdalab'
         unique_together = ('tag_infobox','param_name')
+
+# Added on 02/07/2012
+
+class WpCategoryInclusion(models.Model):
+    parent_category = models.ForeignKey(WpCategory, related_name="child_categories")
+    child_category = models.ForeignKey(WpCategory, related_name="parent_categories")
+    
+    class Meta:
+        app_label = 'hdalab'
+        unique_together = ('parent_category','child_category')
\ No newline at end of file
--- a/src/hdalab/models/dataviz.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/models/dataviz.py	Tue Jun 17 10:32:57 2014 +0200
@@ -59,6 +59,8 @@
     language_code = models.CharField(max_length=15, blank=False, null=False, db_index=True)
     label = models.CharField(max_length=2048, unique=False, blank=True, null=False)
     abstract = models.TextField(blank=True, null=True)
+    is_label_translated = models.BooleanField(default=True)
+    is_abstract_translated = models.BooleanField(default=True)
     class Meta:
         app_label = 'hdalab'
         unique_together = ('master', 'language_code')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/css/cattree.css	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,52 @@
+.leftzone {
+    width: 280px;
+    min-height: 400px;
+    float: left;
+    height: 100%;
+    padding-right: 20px;
+    border-right: 1px solid #999;
+}
+
+.leftzone h2 {
+    font-size: 16px; font-weight: bold; margin-bottom: 5px;
+}
+
+.leftzone h3 {
+    font-size: 13px; font-weight: bold; margin: 30px 0 5px;
+}
+
+.leftzone input {
+    background: #ffffff; width: 260px; font-size: 14px; font-weight: bold; margin: 5px 0;
+}
+
+.results {
+    margin-top: 30px;
+}
+
+.content-results {
+    color: #000060;
+}
+
+ul.disciplist, ul.theslist {
+    list-style: none; margin: 10px 5px;
+}
+
+.disciplist li, .theslist li {
+    font-size: 12px; font-weight: bold;
+}
+
+.disciplist a, .theslist a {
+    color: #000066;
+}
+
+.disciplist .selected a, .theslist .selected a {
+    color: #0000ff;
+}
+
+.ui-autocomplete strong {
+    font-weight: bold; color: #990000;
+}
+
+div.cattree {
+    margin: 10px 0 0 320px;
+}
--- a/src/hdalab/static/hdalab/css/common.css	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/static/hdalab/css/common.css	Tue Jun 17 10:32:57 2014 +0200
@@ -88,7 +88,15 @@
 }
 
 h1 {
-    margin: 5px 0 10px; font-size: 34px; color: #ffffff;
+    margin: 5px 0 10px; font-size: 34px;
+}
+
+h1 a {
+    color: #ffffff;
+}
+
+h1 a:hover {
+    color: #e07000;
 }
 
 #nav {
@@ -96,7 +104,8 @@
 }
 
 #nav li {
-    float: left; font-size: 14px; margin-left: 10px; font-weight: bold;
+    float: left; font-size: 14px; margin-left: 15px; font-weight: bold;
+    color: #CCCCCC;
 }
 
 #nav a {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/css/completion.css	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,195 @@
+#titlebar, #columns {
+    width: 100%;
+    clear: both;
+}
+
+.langbutton {
+    width: 19px; height: 13px; margin: 2px; padding: 0; border: none; text-indent: -999px; background-position: 0 -26px; cursor: pointer;
+}
+
+.langbutton:hover {
+    background-position: 0 -13px;
+}
+
+.langbutton.selected {
+    background-position: 0 0; cursor: default;
+}
+
+.barrebloc {
+    float: left; width: 473px; border: 1px solid #b0b0b0;
+    background-image: url(../img/bgdhdalab.png); background-position: 0 -22px; background-repeat: repeat-x; cursor: pointer; cursor: hand;
+    border-top-left-radius: 4px; border-top-right-radius: 4px
+}
+
+.barrebloc h2 {
+    margin: 4px 0; font-size: 16px; text-align: center; color: #ffffff; font-weight: bold;
+}
+
+.bloc {
+    float: left; width: 475px; margin-bottom: 10px;
+}
+
+#bloc_translationinfo {
+	color: #666;
+	font-style: italic;
+}
+
+.corpsbloc {
+    float: left; width: 465px; border: 1px solid #b0b0b0; padding: 8px 4px; border-top-style: none;
+    background-color: #ffffff; background-image: url(../img/bgdhdalab.png); background-position: 0 -62px; background-repeat: repeat-x;
+    border-bottom-left-radius: 4px; border-bottom-right-radius: 4px
+}
+
+#hdatitle {
+    float: left; width: 475px; margin: 5px 0; font-size: 20px;
+}
+
+#titleleft {
+	float: left;
+}
+
+#titleright {
+    float: right;
+}
+
+#langselect {
+	float: right;
+}
+
+#leftcol {
+    float: left; width: 475px; margin-right: 5px;
+}
+
+#rightcol {
+    float: left; width: 475px; margin-left: 5px;
+}
+
+#contentlist {
+    list-style: none;
+}
+
+li.content-item {
+    margin: 2px 0 12px;
+}
+
+.content-item h3 {
+    font-size: 18px; margin: 3px 0; clear: both;
+}
+
+.content-item h4 {
+    font-size: 11px; margin: 3px 0;
+}
+
+.content-item h4 a {
+    color: #000066;
+}
+
+.maplet {
+    float: right;
+}
+
+.content-item p {
+    font-size: 12px; margin: 3px 0;
+}
+
+.content-annotation ul {
+    list-style : disc; margin: 2px 0; padding-left: 1.5em; font-size: 12px;
+    cursor: pointer; cursor: hand;
+}
+
+.content-annotation li {
+    margin: 2px 0;
+}
+
+.content-annotation textarea {
+    width: 99%; margin: 0; padding: 0; font-size: 12px;
+}
+
+ul.content-tags {
+    list-style: none;
+}
+
+li.content-tag-item {
+    display: inline-block; margin: 2px; padding: 2px; font-size: 13px; background: #666666;
+}
+
+.content-tag-item a {
+    color: #ffffff;
+}
+
+.content-tag-item a:hover {
+    color: #ff8080;
+}
+
+.content-tag-item a.tagmatch {
+    color: #ffff00; font-weight: bold;
+}
+
+#taginfo p, h2, h3  {
+    margin: 5px 0;
+}
+
+#taginfo h3 {
+    font-size: 14px;
+}
+
+#taginfo p {
+    font-size: 11px;
+}
+
+#img_wikipedia {
+    float: left; max-width: 160px; max-height: 120px; margin: 2px 2px 2px 0;
+}
+
+#tagsearch {
+    width: 100%; font-size: 16px; font-weight: bold; border-style: none; border-bottom: 1px solid #000;
+}
+
+#tagsearch.waiting {
+    background: url(../img/small-loader.gif) no-repeat right;
+}
+
+ul.ui-autocomplete {
+    font-family: "Open Sans"; max-width: 230px;
+    max-height: 400px; overflow-y: auto; overflow-x: hidden;
+}
+
+.wpinfo {
+    margin-left: 240px;
+}
+
+.ui-menu-item:hover .acwp {
+    display: block;
+}
+
+.acnb {
+    float: right; font-size: 12px; margin: 2px 0 0 2px;
+}
+
+.actitle {
+    font-size: 13px;
+}
+
+.wptitle {
+    font-size: 13px; font-weight: bold;
+}
+
+.wpimg {
+    max-width: 80px; max-height: 60px; float: left; margin: 5px 2px 2px 0; border: none;
+}
+
+.wpabstract {
+    font-size: 11px;
+}
+
+.wpsource {
+    font-size: 10px; font-style: bold;
+}
+
+.clear {
+    clear: both;
+}
+
+.actitle strong, .wptitle strong {
+    color: #c000c0;
+}
\ No newline at end of file
--- a/src/hdalab/static/hdalab/css/facettes.css	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/static/hdalab/css/facettes.css	Tue Jun 17 10:32:57 2014 +0200
@@ -269,31 +269,6 @@
     color: #800000;
 }
 
-
-#tagsearchwrap {
-    width: 200px;
-}
-
-#tagsearch {
-    width: 100%; font-size: 16px; font-weight: bold; border-style: none; border-bottom: 1px solid #000;
-}
-
-#tagsearch.grise {
-    color: #666; font-style: italic; font-weight: normal;
-}
-
-ul.ui-autocomplete {
-    width: 200px; font-family: "Open Sans";
-}
-
-.ui-autocomplete strong {
-    font-weight: bold;
-}
-
-#tagdata {
-    float: right; width: 465px;
-}
-
 #rightcol {
     float: left; width: 475px; margin-left: 5px;
 }
@@ -334,6 +309,10 @@
     font-size: 18px; margin: 3px 0;
 }
 
+.content-item h3 a, .content-item p a {
+    color: #000000;
+}
+
 .content-item h4 {
     font-size: 11px; margin: 3px 0;
 }
@@ -455,4 +434,57 @@
     position: absolute; width: 10px; height: 10px; background: #000000; border-radius: 5px; display: none;
 }
 
+/* COMPLETION */
 
+#tagsearch {
+    width: 100%; font-size: 16px; font-weight: bold; border-style: none; border-bottom: 1px solid #000;
+}
+
+#tagsearch.waiting {
+    background: url(../img/small-loader.gif) no-repeat right;
+}
+
+ul.ui-autocomplete {
+    font-family: "Open Sans"; max-width: 230px;
+    max-height: 400px; overflow-y: auto; overflow-x: hidden;
+}
+
+.wpinfo {
+    margin-left: 240px;
+}
+
+.ui-menu-item:hover .acwp {
+    display: block;
+}
+
+.acnb {
+    float: right; font-size: 12px; margin: 2px 0 0 2px;
+}
+
+.actitle {
+    font-size: 13px;
+}
+
+.wptitle {
+    font-size: 13px; font-weight: bold;
+}
+
+.wpimg {
+    max-width: 80px; max-height: 60px; float: left; margin: 5px 2px 2px 0; border: none;
+}
+
+.wpabstract {
+    font-size: 11px;
+}
+
+.wpsource {
+    font-size: 10px; font-style: bold;
+}
+
+.clear {
+    clear: both;
+}
+
+.actitle strong, .wptitle strong {
+    color: #c000c0;
+}
--- a/src/hdalab/static/hdalab/css/index.css	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/static/hdalab/css/index.css	Tue Jun 17 10:32:57 2014 +0200
@@ -44,12 +44,24 @@
     font-weight: bold;
 }
 
-.entree-bloc {
-    width: 960px; height: 300px; margin: 5px 0 15px; cursor: pointer;
+.liste {
+    clear: both;
+}
+
+.bloc-appli {
+    width: 310px; float: left;
+}
+
+.separateur-applis {
+    width: 15px; height: 100px; float: left;
+}
+
+.fond-bloc {
+    cursor: pointer; height: 290px; margin: 5px 0 15px; padding: 5px;
 }
 
 .overlay-bloc {
-    width: 940px; padding: 5px 10px; background: rgba(255, 200, 120, .8); display: none;
+    padding: 5px 10px; background: rgba(255, 190, 100, 0.85); display: none;
 }
 
 p.goto {
@@ -57,7 +69,15 @@
 }
 
 #bloc-facettes {
-    background: url(../img/facettes-preview.jpg);
+    background: url(../img/facettes-thumb.jpg);
+}
+
+#bloc-categories {
+    background: url(../img/categories-thumb.jpg);
+}
+
+#bloc-thesaurus {
+    background: url(../img/thesaurus-thumb.jpg);
 }
 
 .mini-table {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/css/notice.css	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,115 @@
+h2 {
+    font-size: 20px; font-weight: bold; text-align: center;
+}
+
+.main-datasheet {
+    float: left; width: 300px; border-radius: 3px; padding: 9px; border: 1px solid #999;
+    background: #FFF8F0; margin-top: 10px;
+}
+
+.main-datasheet a {
+    color: #000000;
+}
+
+.main-datasheet h3 {
+    font-size: 16px; font-weight: bold; font-style: italic; margin: 10px 0;
+}
+
+.main-datasheet img {
+    max-width: 173px; float: right; margin: 5px 0 2px 2px; border: 1px solid #999;
+}
+
+.main-datasheet p {
+    font-size: 12px; margin: 5px 0;
+}
+
+.main-datasheet ul {
+    padding-left: 15px; margin: 10px 0 5px;
+}
+
+.main-datasheet li {
+    font-size: 13px; margin: 5px 0; font-weight: bold;
+}
+
+.main-datasheet li a {
+    text-decoration: underline;
+}
+
+.tag-container {
+    float: left; width: 320px; height: 1px; position: relative;
+}
+
+.tag-container h2, .related-datasheets h2 {
+    margin: 10px;
+}
+
+.tag-canvas, .tags-main {
+    position: absolute; top: 0; left: 0;
+}
+
+.tags-main {
+    width: 320px;
+}
+
+.tags {
+    list-style: none; text-align: center;
+}
+
+.tags li {
+    font-size: 12px; line-height: 14px; min-height: 14px; margin: 20px 0; cursor: pointer;
+}
+
+
+.tags span {
+    color: #ffffff; padding: 4px; background: #666680; 
+}
+
+.tags span.selected {
+    color: #FFFF00; font-weight: bold;
+}
+
+.related-datasheets {
+    float: left; width: 320px;
+}
+
+.datasheets {
+    list-style: none;
+}
+
+.datasheet {
+    border-radius: 3px; padding: 4px; border: 1px solid #999; margin: 5px 0;
+    background: #FFF8F0;
+}
+
+.datasheet img {
+    max-width: 86px; float: right; margin: 2px 0 2px 2px; border: 1px solid #999;
+}
+
+.datasheet h3 {
+    font-size: 13px; font-weight: bold; line-height: 13px; margin: 4px 0;
+}
+
+.datasheet h3 a {
+    color: #000000;
+}
+
+.datasheet h4 {
+    font-size: 12px; font-style: italic; line-height: 12px; margin: 4px 0;
+}
+
+.datasheet-tags {
+    list-style: none; /* display: none; */
+}
+
+.datasheet-tags li {
+    padding: 2px; color: #ffffff; background: #999999; margin: 2px 2px 0 0;
+    font-size: 11px; display: inline-block;
+}
+
+.datasheet-tags li.common-tag {
+    font-weight: bold; background: #666680;
+}
+
+.datasheet:hover .datasheet-tags {
+    display: block;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/css/thesaurus.css	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,25 @@
+.column {
+    float: left; width: 449px;
+    padding-left: 20px;
+}
+
+.separator {
+    float: left; width: 1px; height: 500px; margin: 30px 10px 0; background: #666;
+}
+
+.column h3 {
+    font-size: 14px; font-weight: bold;
+    margin: 10px 0;
+}
+
+.explain {
+    font-size: 12px;
+}
+
+.explain p, li {
+    margin: 5px 0;
+}
+
+.explain ul {
+    margin-left: 16px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/css/trees.css	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,125 @@
+.hidden {
+    display: none;
+}
+
+.cattree .content p.title {
+    font-weight: bold; cursor: pointer;
+}
+
+.cattree .content p.title:before {
+    font-weight: normal;
+}
+
+.cattree .score_0, .cattree .score_1, .cattree .score_0 a, .cattree .score_1 a {
+    color: #80d080;
+}
+
+.cattree .score_2, .cattree .score_3, .cattree .score_4, .cattree .score_2 a, .cattree .score_3 a, .cattree .score_4 a {
+    color: #409840;
+}
+
+.cattree .score_5, .cattree .score_6, .cattree .score_7, .cattree .score_5 a, .cattree .score_6 a, .cattree .score_7 a {
+    color: #006000;
+}
+
+.cattree .score_0:before, .cattree .score_1:before {
+    content: "★☆☆ ";
+}
+
+.cattree .score_2:before, .cattree .score_3:before, .cattree .score_4:before {
+    content: "★★☆ ";
+}
+
+.cattree .score_5:before, .cattree .score_6:before, .cattree .score_7:before {
+    content: "★★★ ";
+}
+
+.cattree .img-container {
+    float: left; margin: 10px 0 0; width: 60px; height: 50px; background: #dddddd;
+}
+
+.cattree .img-container img {
+    min-width: 30px; max-width: 60px; max-height: 50px; margin: 0px auto;
+}
+
+.cattree .content p.description {
+    margin: 4px 0 4px 64px; font-size: 12px; min-height: 50px;
+}
+
+.cattree a.content {
+    color: #000000;
+}
+
+.cattree li, .cattree p.theme {
+    margin: 4px 0; font-size: 12px; position: relative;
+}
+
+.cattree p.theme {
+    color: #000080; height: 20px; cursor: pointer;
+}
+
+.cattree p.theme:after {
+    font-weight: bold;
+    content: " [-]"
+}
+
+.cattree .folded p.theme:after {
+    font-weight: bold;
+    content: " [+]"
+}
+
+.cattree .theme span {
+    font-weight: bold; line-height: 12px;
+}
+
+.cattree ul {
+    list-style: none; position: relative; padding: 0; margin: 0;
+}
+
+.cattree .folded ul {
+    display: none;
+}
+
+.cattree .foldedcontent {
+    height: 0px; overflow: hidden;
+}
+
+.cattree .show_more {
+    color: #800000; font-style: italic; cursor: pointer;
+}
+
+.cattree li {
+    list-style: none;
+}
+
+.cattree ul li {
+    margin-left: 38px;
+}
+
+.cattree ul li:after {
+   content: ""; position: absolute; left: -50px; top: 9px; width: 40px; bottom: 0; border-style: solid none none solid; border-width: 1px; border-color: #333;
+}
+
+.cattree ul li:before {
+    content: ""; position: absolute; left: -50px; top: -10px; height: 19px; width: 1px; background: #333;
+}
+
+.cattree ul li:last-child:after {
+    border-style: solid none none;
+}
+
+.cattree .eltype {
+    font-style: italic; display: none;
+}
+
+.cattree li.themeli {
+    list-style: square;
+}
+
+.cattree li.content {
+    list-style: disc;
+}
+
+.loading {
+    height: 128px; background: url(../img/loader.gif) no-repeat center;
+}
\ No newline at end of file
Binary file src/hdalab/static/hdalab/img/categories-thumb.jpg has changed
Binary file src/hdalab/static/hdalab/img/facettes-thumb.jpg has changed
Binary file src/hdalab/static/hdalab/img/loader.gif has changed
Binary file src/hdalab/static/hdalab/img/small-loader.gif has changed
Binary file src/hdalab/static/hdalab/img/thesaurus-thumb.jpg has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/js/cattree.js	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,60 @@
+function showData(_label, _data) {
+    $(".disciplist li").each(function() {
+        if ($(this).text().trim().toLowerCase() === _label.toLowerCase()) {
+            $(this).addClass("selected");
+        }
+    })
+    $(".label-name").html(_label);
+    if (_data) {
+        renderData($("#tree"), _data, 1);
+        $(".results").show();
+        $(".content-count").html($(".cattree a.content").length);
+        $(".category-count").html(Math.max(0, $("p.category").length - 1));
+        $(".tag-count").html($("p.tag").length);
+    } else {
+        $("#tree").html("");
+        $(".results").hide();
+    }
+}
+
+function gettree(_label) {
+    $(".disciplist li").removeClass("selected");
+    $("#tree").html('<div class="loading"></div>');
+    $.getJSON(
+        endpoints.cat_tree,
+        { label: _label },
+        function(_data) {
+            showData(_label, _data);
+        }
+    );
+}
+
+$(function() {
+    $("#catsearch").autocomplete({
+        source: endpoints.cat_search,
+        minLength: 2,
+        select: function( event, ui ) {
+            gettree(ui.item.value);
+        }
+    })
+    .data("autocomplete")._renderItem = function(ul, item) {
+        return $( "<li></li>" )
+            .data( "item.autocomplete", item )
+            .append(
+                "<a>"
+                + item.label.replace(
+                    new RegExp('('
+                        + $("#catsearch").val().replace(/(\W)/g, '\\$1')
+                        + ')','gi') ,
+                    '<strong>$1</strong>')
+                + "</a>" )
+            .appendTo( ul )
+    };
+    $("#catform").submit(function() {
+        gettree($("#catsearch").val());
+    });
+    gettree("cinéma");
+    $(".disciplist li").click(function() {
+        gettree($(this).text().trim());
+    });
+});
\ No newline at end of file
--- a/src/hdalab/static/hdalab/js/gomina.js	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/static/hdalab/js/gomina.js	Tue Jun 17 10:32:57 2014 +0200
@@ -112,54 +112,6 @@
     gomNs.map.addLayer(gJ);
 }
 
-
-function tagInfo(_taglabel, _filter) {
-    var _urlParam = { "label": _taglabel };
-    $.getJSON(gomNs.urls['tag_info'],
-        _urlParam,
-        function(data) {
-            $("#tagsearch").val(data.translated_label).removeClass("grise");
-            $("#tagcount").html(data.content_count
-                + ' ' + ngettext("contenu", "contenus", data.content_count) + ' '+gettext("pour ce tag"));
-            var _html = '';
-            if (data.wikipedia_url) {
-                _html += '<h3><a href="'
-                    + data.wikipedia_url
-                    + '" target="_blank">Wikipedia: '
-                    + decodeURI(data.wikipedia_url.match(/[^\/]+$/)[0]).replace("_"," ")
-                    + '</a></h3>'
-            }
-            if (data.thumbnail) {
-                _html += '<img id="img_wikipedia" src="'
-                    + data.thumbnail
-                    + '" />';
-            }
-            if (data.translated_abstract) {
-                _html += '<p>' + _(data.translated_abstract).escape().replace(/(^.{0,240})([\s]|$)(.*)/,'$1&hellip;') + '</p>';
-            }
-/*            if (data.links) {
-                var _lC = data.requested_label.toLowerCase();
-                var _t = data.links.map(function(d) {
-                    return (d.subject.toLowerCase() == _lC) ? d.object : d.subject;
-                });
-                _t.sort();
-                _t = _(_t).uniq(true);
-                _html += '<h3>Tags liés (dbpedia)</h3><ul class="content-tags">'
-                    + _t.map(function(d) {
-                        return '<li class="content-tag-item"><a href="#" onclick="tagInfo($(this).text()); return false;">'
-                            + d
-                            + '</a></li>';
-                    }).join('')
-                    + '</ul>';
-            } */
-            $("#tagdata").html(_html);
-        });
-    if (typeof _filter !== "undefined" && _filter) {
-        addFilter('tag', _taglabel);
-    }
-    $("#showlist").removeClass("actif");
-}
-
 function addFilter(_type, _label) {
     var _curView = gomNs.sessiondata.views[gomNs.sessiondata.view];
     if (_curView.type == 'filter') {
@@ -254,9 +206,6 @@
     var _htmFilters = '',
         _fl = _curView.tag.length,
         _cl = _curView.country.length;
-/*    if (!_curView.period && !_fl && !_cl) {
-        _htmFilters = '<li class="nofilter">Aucun filtre</li>';
-} */
     if (_curView.period[0] == gomNs.minYear && _curView.period[1] == gomNs.maxYear) {
         _htmFilters += '<li class="filperiod">'+gettext("Toutes periodes")+'</li>';
     } else {
@@ -306,15 +255,20 @@
     if (contentdata && contentdata.length) {
         var _htmlCl = '<ul id="contentlist">'
             + contentdata.map(function(_d) {
-                var _html = '<li class="content-item"><h3>'
+                var _dsurl = gomNs.urls.datasheet.replace(/ID$/,_d.hda_id);
+                var _html = '<li class="content-item"><h3><a href="'
+                    + _dsurl
+                    + '">'
                     + _d.title
-                    + '</h3>'
+                    + '</a></h3>'
                     + ( typeof _d.coords == "object" ?
                         '<div class="maplet"><img src="http://maps.googleapis.com/maps/api/staticmap?center=47,1.5&zoom=4&size=160x160&maptype=roadmap&markers=color:red%7C'
                         + _d.coords.latitude
                         + ','
                         + _d.coords.longitude
-                        + '&sensor=false" /><h4>Localisation&nbsp;: '
+                        + '&sensor=false" /><h4>'
+                        + gettext('Localisation&nbsp;:')
+                        + ' '
                         + _d.coords.city_name
                         + '</h4></div>'
                         : '')
@@ -322,11 +276,13 @@
                     + _d.url
                     + '" target="_blank">'
                     + _d.url.replace(/(^.{40}).+(.{30}$)/m,'$1 &hellip; $2')
-                    + '</a></h4><p>'
+                    + '</a></h4><p><a href="'
+                    + _dsurl
+                    + '">'
                     + _d.description.replace(/(^.{0,160})([\s]|$)(.*)/,'$1&hellip;')
-                    + '</p><ul class="content-tags">'
+                    + '</a></p><ul class="content-tags">'
                     + _d.tags.map(function(_t) {
-                        return '<li class="content-tag-item"><a href="#" onclick="tagInfo(this.getAttribute(\'original-label\'), true); return false;" original-label="'
+                        return '<li class="content-tag-item"><a href="#" onclick="addFilter(\'tag\', this.getAttribute(\'original-label\')); return false;" original-label="'
                             + _t.label
                             + '"'
                             + (_t.match ? ' class="tagmatch"' : '')
@@ -456,7 +412,7 @@
             + _(data.tags).map(function(_d) {
                 return '<li style="font-size:'
                     + parseInt(10 + _scale * Math.sqrt(_d.score - _minTag))
-                    + 'px;"><a href="#" onclick="tagInfo(this.getAttribute(\'original-label\'), true); return false;" original-label="'
+                    + 'px;"><a href="#" onclick="addFilter(\'tag\', this.getAttribute(\'original-label\')); return false;" original-label="'
                     + _d.label
                     +'"'
                     + (_d.match ? ' class="tagmatch"' : '')
@@ -505,7 +461,7 @@
             '<ul class="disc-ul">'
             + _disc.map(function(_d) {
                 var _col = getGradient(_d.score / _max);
-                return '<li class="disc-li" onclick="tagInfo(this.getAttribute(\'original-label\'), true); return false;" original-label="'
+                return '<li class="disc-li" onclick="addFilter(\'tag\', this.getAttribute(\'original-label\')); return false;" original-label="'
                     + _d.label
                     + '"><div class="disc-label"><a href="#">'
                     + _d.translated_label
@@ -694,6 +650,28 @@
 function animStop() {
     $("#waiting").empty().fadeOut();
 }
+function ellipse(_text, _length) {
+    var _rgxp = new RegExp('(^.{0,' + _length + '})([\s]|$)(.*)')
+    return _text.replace(/(\n|\r|\r\n)/mg,' ').trim().replace(_rgxp,'$1…')
+}
+
+function highlightText(_text, _search) {
+    var _rgxp = new RegExp('(' + _search.replace(/(\W)/g, '\\$1') + ')','gi');
+    return _text.replace(_rgxp, '<strong>$1</strong>');
+}
+
+function wikipediaUrl(_text) {
+    return "http://" + gomNs.languageCode + ".wikipedia.org/wiki/" + encodeURI(_text.replace(/ /g,'_'))
+}
+
+wpTemplate = _.template(
+    '<h4 class="wptitle"><% print(highlightText(item.label, inputvalue)); %></h4><% if (item.thumbnail) { %><img class="wpimg" src="<%-item.thumbnail%>" /><% };'
+    + ' if (item.abstract) { %><p class="wpabstract"><% print(ellipse(item.abstract,250))%></p><p class="wpsource"><a href="<% print(wikipediaUrl(item.label)) %>" target="_blank"><% print(gettext("Source&nbsp;: Wikipédia")) %></a></p><% }; %><div class="clear"></div>'
+);
+
+acTemplate = _.template(
+    '<a><span class="acnb"><%- item.nb %></span><h4 class="actitle"><% print(highlightText(item.label, inputvalue)); %></h4></a>'
+);
 
 $(document).ready(function() {
     switch(gomNs.mappingLibrary) {
@@ -788,50 +766,7 @@
                 debouncedSaveChanges();
             }
         }
-    })
-    var _defLab = $( "#tagsearch" ).val();
-    $( "#tagsearch" ).autocomplete({
-        source: gomNs.urls['tag_search'],
-        minLength: 2,
-        focus: function( event, ui ) {
-            tagInfo(ui.item.value, false);
-            return false;
-        },
-        select: function( event, ui ) {
-            tagInfo(ui.item.value, true);
-            return false;
-        },
-        open: function() {
-            $('#tagdata').css({
-                width: "250px"
-            })
-        },
-        close: function() {
-            $('#tagdata').css({
-                width: "465px"
-            })
-        }
-    })
-    .addClass("grise")
-    .focusin(function() {
-        if ($(this).val() == _defLab) {
-            $(this).val("").removeClass("grise");
-        }
-    })
-    .data("autocomplete")._renderItem = function(ul, item) {
-        return $( "<li></li>" )
-            .data( "item.autocomplete", item )
-            .append( '<a><span style="float: right;">'
-                + item.nb
-                + '</span>'
-                + item.label.replace(
-                    new RegExp('('
-                        + $("#tagsearch").val().replace(/(\W)/g, '\\$1')
-                        + ')','gi') ,
-                    '<strong>$1</strong>')
-                + "</a>" )
-            .appendTo( ul );
-    };
+    });
     $("#sessionname").click(function() {
         if (gomNs.write_allowed && !$(this).children().length) {
             var _el = document.createElement('input');
@@ -924,4 +859,47 @@
        }
        return false;
     });
+        $(" #tagform ").submit(function() {
+        return false;
+    });
+    var cache = {}, /*CACHE => http://jqueryui.com/demos/autocomplete/#remote-with-cache */
+        lastXhr;
+    $( "#tagsearch" ).autocomplete({
+        source: function( request, response ) {
+            var term = request.term;
+            if ( term in cache ) {
+                $("#tagsearch").removeClass("waiting");
+                response( cache[ term ] );
+                return;
+            }
+            $("#tagsearch").addClass("waiting");
+            lastXhr = $.getJSON( gomNs.urls['tag_search'], request, function( data, status, xhr ) {
+                cache[ term ] = data;
+                if ( xhr === lastXhr ) {
+                    response( data );
+                    $("#tagsearch").removeClass("waiting");
+                }
+            });
+        },
+        minLength: ( gomNs.languageCode == 'ja' ? 1 : 2 ),
+        focus: function( event, ui ) {
+            $(".wpinfo").html(wpTemplate({
+                item: ui.item,
+                inputvalue: $("#tagsearch").val()
+            }));
+        },
+        select: function( event, ui ) {
+            addFilter('tag', ui.item.original_label);
+        }
+    })
+    .data("autocomplete")._renderItem = function(ul, item) {
+        var _contents = acTemplate({
+            item: item,
+            inputvalue: $("#tagsearch").val()
+        });
+        return $( "<li>" )
+            .data( "item.autocomplete", item )
+            .html( _contents )
+            .appendTo( ul );
+    };
 });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/js/notice.js	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,99 @@
+var selectedelement = null;
+
+function drawlinks() {
+    var w$ = $(window)
+        scroll = w$.scrollTop(),
+        windowheight = w$.height();
+    $(".tags-main, .main-datasheet").css({
+        "margin-top": Math.max(0, scroll - 60) + "px"
+    });
+    var cvheight = Math.max($(".tags-main").outerHeight(), $(".related-datasheets").outerHeight()),
+        cvwidth = $(".tag-container").width(),
+        cv$ = $(".tag-canvas"),
+        cvo = cv$.offset(),
+        colors = ["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"];
+    cv$.attr({
+        width: cvwidth,
+        height: cvheight
+    }).css({
+        width: cvwidth,
+        height: cvheight
+    });
+    
+    $(".main-datasheet-tag, .datasheet").css("opacity", selectedelement ? .7 : 1);
+    $(selectedelement).css("opacity",1);
+    
+    var ctx = cv$[0].getContext('2d'),
+        mds$ = $(".main-datasheet"),
+        ymain = Math.floor(mds$.height() / 2 + mds$.offset().top - cvo.top);
+    
+    $(".main-datasheet-tag").each(function() {
+        var tag$ = $(this),
+            ytag = Math.floor(tag$.offset().top + tag$.outerHeight() / 2 - cvo.top);
+        ctx.strokeStyle = "#999999";
+        ctx.lineWidth = (this === selectedelement ? 4 : 1);
+        ctx.beginPath();
+        ctx.moveTo(0, ymain);
+        ctx.bezierCurveTo(80,ymain, 40,ytag, 120, ytag);
+        ctx.lineTo(160, ytag);
+        ctx.stroke();
+        
+        var tagid = tag$.attr("data-tag-id"),
+            relds = $(".related-datasheet-tag[data-tag-id=" + tagid + "]").parent().parent();
+        
+        if (this === selectedelement) {
+            relds.css("opacity", 1);
+        }
+        
+        relds.each(function(i) {
+            var ds$ = $(this),
+                dst = ds$.offset().top,
+                dsh = ds$.outerHeight(),
+                visible = ds$.is(":visible") && (dst - scroll < windowheight) && (dst + dsh - scroll > 0);
+            if (visible) {
+                var yds = Math.floor(dst + dsh / 2 - cvo.top);
+                ctx.lineWidth = (this === selectedelement || tag$[0] === selectedelement ? 4 : 1);
+                ctx.strokeStyle = colors[ds$.index() % colors.length];
+                ctx.beginPath();
+                ctx.moveTo(160, ytag);
+                ctx.lineTo(200, ytag);
+                ctx.bezierCurveTo(280,ytag, 280,yds, 320, yds);
+                ctx.stroke();
+                if (this === selectedelement) {
+                    tag$.css("opacity",1);
+                }
+            }
+        })
+    });
+}
+
+$(function() {
+    $(window).scroll(drawlinks);
+    $(window).resize(drawlinks);
+    $(".main-datasheet-tag").click(function() {
+        var tag$ = $(this);
+        if (tag$.hasClass("selected")) {
+            $(".datasheet").show();
+            tag$.removeClass("selected");
+        } else {
+            $(".datasheet").hide();
+            var tagid = tag$.attr("data-tag-id");
+            $(".related-datasheet-tag[data-tag-id=" + tagid + "]").parent().parent().show();
+            $(".main-datasheet-tag").removeClass("selected");
+            tag$.addClass("selected");
+        }
+        drawlinks();
+    });
+    $(".main-datasheet-tag, .datasheet").mouseover(function() {
+        if (selectedelement !== this) {
+            selectedelement = this;
+            drawlinks();
+        }
+    }).mouseout(function() {
+        if (selectedelement) {
+            selectedelement = null;
+            drawlinks();
+        }
+    });
+    drawlinks();
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/js/thesaurus.js	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,178 @@
+var trees = [
+    {
+        title: "Thésaurus de l'Architecture et de l'Urbanisme : Secteur urbain",
+        tree: {
+            label: "secteur urbain",
+            contents: [
+                {
+                    label: "banlieue",
+                    contents: [
+                        {
+                            label: "faubourg"
+                        }
+                    ]
+                },
+                {
+                    label: "îlot"
+                },
+                {
+                    label: "quartier",
+                    contents: [
+                        {
+                            label: "centre-ville"
+                        }
+                    ]
+                },
+                {
+                    label: "secteur urbain concerté",
+                    contents: [
+                        {
+                            label: "grand ensemble"
+                        },
+                        {
+                            label: "lotissement",
+                            contents: [
+                                {
+                                    label: "lotissement concerté",
+                                    contents: [
+                                        {
+                                            label: "cité-jardin"
+                                        },
+                                        {
+                                            label: "cité ouvrière"
+                                        },
+                                        {
+                                            label: "courée"
+                                        },
+                                    ]
+                                }
+                            ]
+                        }
+                    ]
+                },
+            ]
+        }
+    },
+    {
+        title: "Thésaurus Garnier : Architecture d'habitation",
+        tree: {
+            label: "architecture d'habitation",
+            contents: [
+                {
+                    label: "cité-jardin"
+                },
+                {
+                    label: "édifice d'habitation",
+                    contents: [
+                        {
+                            label: "demeure",
+                            contents: [
+                                {
+                                    label: "chalet"
+                                },
+                                {
+                                    label: "château"
+                                },
+                                {
+                                    label: "château-fort",
+                                    contents: [
+                                        {
+                                            label: "chemin de ronde"
+                                        },
+                                        {
+                                            label: "donjon"
+                                        }
+                                    ]
+                                },
+                                {
+                                    label: "hôtel particulier"
+                                },
+                                {
+                                    label: "maison"
+                                },
+                                {
+                                    label: "manoir"
+                                },
+                                {
+                                    label: "palais"
+                                }
+                            ]
+                        },
+                        {
+                            label: "abri",
+                            contents: [
+                                {
+                                    label: "buron"
+                                },
+                                {
+                                    label: "cabane"
+                                },
+                                {
+                                    label: "campement",
+                                    contents: [
+                                        {
+                                            label: "tente"
+                                        },
+                                        {
+                                            label: "tipi"
+                                        },
+                                        {
+                                            label: "igloo"
+                                        }
+                                    ]
+                                }
+                            ]
+                        }
+                    ]
+                }
+            ]
+        }
+    },
+    {
+        title: "Thésaurus Garnier : Sciences occultes",
+        tree: {
+            label: "sciences occultes",
+            contents: [
+                {
+                    label: "alchimie"
+                },
+                {
+                    label: "astrologie"
+                },
+                {
+                    label: "divination"
+                },
+                {
+                    label: "magie",
+                    contents: [
+                        {
+                            label: "sorcellerie"
+                        },
+                        {
+                            label: "sorcière"
+                        }
+                    ]
+                }
+            ]
+        }
+    }
+];
+$(function() {
+    $(".column").each(function(_key) {
+        var _tree = trees[_key],
+            _el = $(this);
+        _el.find("h3").text(_tree.title);
+        $.getJSON(
+            endpoints.fill_tree,
+            { tree: JSON.stringify(_tree.tree) },
+            function(_data) {
+                renderData(_el.find(".cattree"), _data, 2);
+                _el.find("p.theme:contains('cité-jardin')")
+                    .css("background-color","#ffff80")
+                    .parent()
+                    .parentsUntil(".cattree")
+                        .removeClass("folded");
+            }
+        );
+    });
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/js/trees.js	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,81 @@
+
+function countContentsAndThemes(_data) {
+    _data.counts = {
+        contents: (typeof _data.contents == "object" && typeof _data.contents.slice == "function" ? _data.contents.length : 0),
+        themes: (typeof _data.themes == "object" && typeof _data.themes.slice == "function" ? _data.themes.length : 0)
+    }
+    if (typeof _data.themes == "object" && typeof _data.themes.slice == "function") {
+        for (var _i = 0; _i < _data.themes.length; _i++) {
+            countContentsAndThemes(_data.themes[_i]);
+            var _subres = _data.themes[_i].counts;
+            _data.counts.contents += _subres.contents;
+            _data.counts.themes += _subres.themes;
+        }
+    }
+}
+
+function renderTemplate(_data, _level, _scale, _maxlevel) {
+    _data.isfolded = _level >= _maxlevel;
+    _(_data.tags).each(function(_tag) {
+        _(_tag.contents).each(function(_content, _key) {
+            _content.trimmed_description = _content.description.trim().replace(/(\n|\r|\r\n)/mg,' ').replace(/(^.{150,200})[\s].+$/m,'$1&hellip;');
+            _content.hidden = (_key >= 5);
+        });
+        _tag.show_more = _tag.contents && _tag.contents.length > 5 ? _tag.contents.length - 5 : 0;
+    });
+    _(_data.contents).each(function(_content, _key) {
+        _content.trimmed_description = _content.description.trim().replace(/(\n|\r|\r\n)/mg,' ').replace(/(^.{150,200})[\s].+$/m,'$1&hellip;');
+        _content.hidden = (_key >= 5);
+    });
+    _data.show_more = _data.contents && _data.contents.length > 5 ? _data.contents.length - 5 : 0;
+    _data.font_size = (10+Math.log(_data.counts.contents)*_scale);
+    var _dsurl = endpoints.datasheet.replace(/ID$/,'');
+    var _prefix = '<li class="themeli{{#isfolded}} folded{{/isfolded}}"><p class="theme"><span style="font-size: {{font_size}}px">{{label}}</span> &mdash; {{#counts.themes}}{{counts.themes}} thème(s){{#counts.contents}}, {{/counts.contents}}{{/counts.themes}}{{#counts.contents}}{{counts.contents}} notice(s){{/counts.contents}}</p><ul>',
+        _suffix = '{{#contents}}<li class="content{{#hidden}} hidden{{/hidden}}" id="content_{{id}}"><p class="title score_{{score}}"><a href="'
+            + _dsurl
+            + '{{hda_id}}">{{title}}</a></p><div class="foldedcontent"><div class="img-container"><img src="http://www.histoiredesarts.culture.fr/images/cached/images/{{hda_id}}.jpg" />'
+            + '</div><p class="description">Source: <a href="{{organization_url}}" target="_blank">{{organization}}</a><br /><a href="'
+            + _dsurl
+            + '{{hda_id}}" class="content">{{trimmed_description}}</a></p></div></li>{{/contents}}{{#show_more}}<li class="show_more">Plus de contenus (<span class="show_more_count">{{show_more}}</span>)&hellip;</li>{{/show_more}}</ul></li>',
+        _html = Mustache.to_html(_prefix, _data);
+    if (typeof _data.themes == "object" && typeof _data.themes.slice == "function") {
+        for (var _i = 0; _i < _data.themes.length; _i++) {
+            _html += renderTemplate(_data.themes[_i], _level + 1, _scale, _maxlevel);
+        }
+    }
+    _html += Mustache.to_html(_suffix, _data);
+    return _html;
+}
+
+function renderData(_selector, _data, _maxlevel) {
+    countContentsAndThemes(_data);
+    var _scale = 8 / Math.max(1,Math.log(_data.counts.contents));
+    _selector.html(renderTemplate(_data, 0, _scale, _maxlevel));
+    _selector.find("p.theme").click(function() {
+        $(this).parent().toggleClass("folded")
+        return false;
+    });
+    _selector.find("li.content").mouseenter(function() {
+        $(this).find(".foldedcontent")
+        .dequeue()
+        .animate({
+            height: 5 + $(this).find("p.description").outerHeight()
+        },
+        500);
+    }).mouseleave(function() {
+        $(this).find(".foldedcontent")
+        .dequeue()
+        .animate({
+            height: "0"
+        },
+        500);
+    });
+    _selector.find(".show_more").click(function() {
+        $(this).siblings(".hidden:lt(5)").removeClass("hidden");
+        var _l = $(this).siblings(".hidden").length;
+        $(this).find(".show_more_count").html(_l);
+        if (!_l) {
+            $(this).detach();
+        } 
+    });
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/static/hdalab/lib/mustache.js	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,436 @@
+/*
+  mustache.js — Logic-less templates in JavaScript
+
+  See http://mustache.github.com/ for more info.
+*/
+
+var Mustache = function () {
+  var _toString = Object.prototype.toString;
+
+  Array.isArray = Array.isArray || function (obj) {
+    return _toString.call(obj) == "[object Array]";
+  }
+
+  var _trim = String.prototype.trim, trim;
+
+  if (_trim) {
+    trim = function (text) {
+      return text == null ? "" : _trim.call(text);
+    }
+  } else {
+    var trimLeft, trimRight;
+
+    // IE doesn't match non-breaking spaces with \s.
+    if ((/\S/).test("\xA0")) {
+      trimLeft = /^[\s\xA0]+/;
+      trimRight = /[\s\xA0]+$/;
+    } else {
+      trimLeft = /^\s+/;
+      trimRight = /\s+$/;
+    }
+
+    trim = function (text) {
+      return text == null ? "" :
+        text.toString().replace(trimLeft, "").replace(trimRight, "");
+    }
+  }
+
+  var escapeMap = {
+    "&": "&amp;",
+    "<": "&lt;",
+    ">": "&gt;",
+    '"': '&quot;',
+    "'": '&#39;'
+  };
+
+  function escapeHTML(string) {
+    return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
+      return escapeMap[s] || s;
+    });
+  }
+
+  var regexCache = {};
+  var Renderer = function () {};
+
+  Renderer.prototype = {
+    otag: "{{",
+    ctag: "}}",
+    pragmas: {},
+    buffer: [],
+    pragmas_implemented: {
+      "IMPLICIT-ITERATOR": true
+    },
+    context: {},
+
+    render: function (template, context, partials, in_recursion) {
+      // reset buffer & set context
+      if (!in_recursion) {
+        this.context = context;
+        this.buffer = []; // TODO: make this non-lazy
+      }
+
+      // fail fast
+      if (!this.includes("", template)) {
+        if (in_recursion) {
+          return template;
+        } else {
+          this.send(template);
+          return;
+        }
+      }
+
+      // get the pragmas together
+      template = this.render_pragmas(template);
+
+      // render the template
+      var html = this.render_section(template, context, partials);
+
+      // render_section did not find any sections, we still need to render the tags
+      if (html === false) {
+        html = this.render_tags(template, context, partials, in_recursion);
+      }
+
+      if (in_recursion) {
+        return html;
+      } else {
+        this.sendLines(html);
+      }
+    },
+
+    /*
+      Sends parsed lines
+    */
+    send: function (line) {
+      if (line !== "") {
+        this.buffer.push(line);
+      }
+    },
+
+    sendLines: function (text) {
+      if (text) {
+        var lines = text.split("\n");
+        for (var i = 0; i < lines.length; i++) {
+          this.send(lines[i]);
+        }
+      }
+    },
+
+    /*
+      Looks for %PRAGMAS
+    */
+    render_pragmas: function (template) {
+      // no pragmas
+      if (!this.includes("%", template)) {
+        return template;
+      }
+
+      var that = this;
+      var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) {
+        return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
+      });
+
+      return template.replace(regex, function (match, pragma, options) {
+        if (!that.pragmas_implemented[pragma]) {
+          throw({message:
+            "This implementation of mustache doesn't understand the '" +
+            pragma + "' pragma"});
+        }
+        that.pragmas[pragma] = {};
+        if (options) {
+          var opts = options.split("=");
+          that.pragmas[pragma][opts[0]] = opts[1];
+        }
+        return "";
+        // ignore unknown pragmas silently
+      });
+    },
+
+    /*
+      Tries to find a partial in the curent scope and render it
+    */
+    render_partial: function (name, context, partials) {
+      name = trim(name);
+      if (!partials || partials[name] === undefined) {
+        throw({message: "unknown_partial '" + name + "'"});
+      }
+      if (!context || typeof context[name] != "object") {
+        return this.render(partials[name], context, partials, true);
+      }
+      return this.render(partials[name], context[name], partials, true);
+    },
+
+    /*
+      Renders inverted (^) and normal (#) sections
+    */
+    render_section: function (template, context, partials) {
+      if (!this.includes("#", template) && !this.includes("^", template)) {
+        // did not render anything, there were no sections
+        return false;
+      }
+
+      var that = this;
+
+      var regex = this.getCachedRegex("render_section", function (otag, ctag) {
+        // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
+        return new RegExp(
+          "^([\\s\\S]*?)" +         // all the crap at the beginning that is not {{*}} ($1)
+
+          otag +                    // {{
+          "(\\^|\\#)\\s*(.+)\\s*" + //  #foo (# == $2, foo == $3)
+          ctag +                    // }}
+
+          "\n*([\\s\\S]*?)" +       // between the tag ($2). leading newlines are dropped
+
+          otag +                    // {{
+          "\\/\\s*\\3\\s*" +        //  /foo (backreference to the opening tag).
+          ctag +                    // }}
+
+          "\\s*([\\s\\S]*)$",       // everything else in the string ($4). leading whitespace is dropped.
+
+        "g");
+      });
+
+
+      // for each {{#foo}}{{/foo}} section do...
+      return template.replace(regex, function (match, before, type, name, content, after) {
+        // before contains only tags, no sections
+        var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
+
+        // after may contain both sections and tags, so use full rendering function
+            renderedAfter = after ? that.render(after, context, partials, true) : "",
+
+        // will be computed below
+            renderedContent,
+
+            value = that.find(name, context);
+
+        if (type === "^") { // inverted section
+          if (!value || Array.isArray(value) && value.length === 0) {
+            // false or empty list, render it
+            renderedContent = that.render(content, context, partials, true);
+          } else {
+            renderedContent = "";
+          }
+        } else if (type === "#") { // normal section
+          if (Array.isArray(value)) { // Enumerable, Let's loop!
+            renderedContent = that.map(value, function (row) {
+              return that.render(content, that.create_context(row), partials, true);
+            }).join("");
+          } else if (that.is_object(value)) { // Object, Use it as subcontext!
+            renderedContent = that.render(content, that.create_context(value),
+              partials, true);
+          } else if (typeof value == "function") {
+            // higher order section
+            renderedContent = value.call(context, content, function (text) {
+              return that.render(text, context, partials, true);
+            });
+          } else if (value) { // boolean section
+            renderedContent = that.render(content, context, partials, true);
+          } else {
+            renderedContent = "";
+          }
+        }
+
+        return renderedBefore + renderedContent + renderedAfter;
+      });
+    },
+
+    /*
+      Replace {{foo}} and friends with values from our view
+    */
+    render_tags: function (template, context, partials, in_recursion) {
+      // tit for tat
+      var that = this;
+
+      var new_regex = function () {
+        return that.getCachedRegex("render_tags", function (otag, ctag) {
+          return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g");
+        });
+      };
+
+      var regex = new_regex();
+      var tag_replace_callback = function (match, operator, name) {
+        switch(operator) {
+        case "!": // ignore comments
+          return "";
+        case "=": // set new delimiters, rebuild the replace regexp
+          that.set_delimiters(name);
+          regex = new_regex();
+          return "";
+        case ">": // render partial
+          return that.render_partial(name, context, partials);
+        case "{": // the triple mustache is unescaped
+        case "&": // & operator is an alternative unescape method
+          return that.find(name, context);
+        default: // escape the value
+          return escapeHTML(that.find(name, context));
+        }
+      };
+      var lines = template.split("\n");
+      for(var i = 0; i < lines.length; i++) {
+        lines[i] = lines[i].replace(regex, tag_replace_callback, this);
+        if (!in_recursion) {
+          this.send(lines[i]);
+        }
+      }
+
+      if (in_recursion) {
+        return lines.join("\n");
+      }
+    },
+
+    set_delimiters: function (delimiters) {
+      var dels = delimiters.split(" ");
+      this.otag = this.escape_regex(dels[0]);
+      this.ctag = this.escape_regex(dels[1]);
+    },
+
+    escape_regex: function (text) {
+      // thank you Simon Willison
+      if (!arguments.callee.sRE) {
+        var specials = [
+          '/', '.', '*', '+', '?', '|',
+          '(', ')', '[', ']', '{', '}', '\\'
+        ];
+        arguments.callee.sRE = new RegExp(
+          '(\\' + specials.join('|\\') + ')', 'g'
+        );
+      }
+      return text.replace(arguments.callee.sRE, '\\$1');
+    },
+
+    /*
+      find `name` in current `context`. That is find me a value
+      from the view object
+    */
+    find: function (name, context) {
+      name = trim(name);
+
+      // Checks whether a value is thruthy or false or 0
+      function is_kinda_truthy(bool) {
+        return bool === false || bool === 0 || bool;
+      }
+
+      var value;
+
+      // check for dot notation eg. foo.bar
+      if (name.match(/([a-z_]+)\./ig)) {
+        var childValue = this.walk_context(name, context);
+        if (is_kinda_truthy(childValue)) {
+          value = childValue;
+        }
+      } else {
+        if (is_kinda_truthy(context[name])) {
+          value = context[name];
+        } else if (is_kinda_truthy(this.context[name])) {
+          value = this.context[name];
+        }
+      }
+
+      if (typeof value == "function") {
+        return value.apply(context);
+      }
+      if (value !== undefined) {
+        return value;
+      }
+      // silently ignore unkown variables
+      return "";
+    },
+
+    walk_context: function (name, context) {
+      var path = name.split('.');
+      // if the var doesn't exist in current context, check the top level context
+      var value_context = (context[path[0]] != undefined) ? context : this.context;
+      var value = value_context[path.shift()];
+      while (value != undefined && path.length > 0) {
+        value_context = value;
+        value = value[path.shift()];
+      }
+      // if the value is a function, call it, binding the correct context
+      if (typeof value == "function") {
+        return value.apply(value_context);
+      }
+      return value;
+    },
+
+    // Utility methods
+
+    /* includes tag */
+    includes: function (needle, haystack) {
+      return haystack.indexOf(this.otag + needle) != -1;
+    },
+
+    // by @langalex, support for arrays of strings
+    create_context: function (_context) {
+      if (this.is_object(_context)) {
+        return _context;
+      } else {
+        var iterator = ".";
+        if (this.pragmas["IMPLICIT-ITERATOR"]) {
+          iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
+        }
+        var ctx = {};
+        ctx[iterator] = _context;
+        return ctx;
+      }
+    },
+
+    is_object: function (a) {
+      return a && typeof a == "object";
+    },
+
+    /*
+      Why, why, why? Because IE. Cry, cry cry.
+    */
+    map: function (array, fn) {
+      if (typeof array.map == "function") {
+        return array.map(fn);
+      } else {
+        var r = [];
+        var l = array.length;
+        for(var i = 0; i < l; i++) {
+          r.push(fn(array[i]));
+        }
+        return r;
+      }
+    },
+
+    getCachedRegex: function (name, generator) {
+      var byOtag = regexCache[this.otag];
+      if (!byOtag) {
+        byOtag = regexCache[this.otag] = {};
+      }
+
+      var byCtag = byOtag[this.ctag];
+      if (!byCtag) {
+        byCtag = byOtag[this.ctag] = {};
+      }
+
+      var regex = byCtag[name];
+      if (!regex) {
+        regex = byCtag[name] = generator(this.otag, this.ctag);
+      }
+
+      return regex;
+    }
+  };
+
+  return({
+    name: "mustache.js",
+    version: "0.5.0-dev",
+
+    /*
+      Turns a template and view into HTML
+    */
+    to_html: function (template, view, partials, send_fun) {
+      var renderer = new Renderer();
+      if (send_fun) {
+        renderer.send = send_fun;
+      }
+      renderer.render(template, view || {}, partials);
+      if (!send_fun) {
+        return renderer.buffer.join("\n");
+      }
+    }
+  });
+}();
--- a/src/hdalab/templates/base.html	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/templates/base.html	Tue Jun 17 10:32:57 2014 +0200
@@ -25,9 +25,15 @@
         <div id="header">
             <ul id="nav">
                 <li><a class="{% block home_actif %}{% endblock %}" href="{% url home %}">Accueil</a></li>
-                <li><a class="{% block facettes_actif %}{% endblock %}" href="{% url facettes %}">Recherche par facettes</a></li>
+                <li>&mdash;</li>
+                <li>Navigation par&nbsp;:</li>
+                <li><a class="{% block facettes_actif %}{% endblock %}" href="{% url facettes %}">Facettes</a></li>
+                <li><a class="{% block categories_actif %}{% endblock %}" href="{% url categories %}">Catégories de Wikipedia</a></li>
+                <li><a class="{% block thesaurus_actif %}{% endblock %}" href="{% url thesaurus %}">Thésaurus</a></li>
             </ul>
-            <h1>HdA Lab</h1>
+            <h1>
+                <a href="{% url home %}">HdA Lab</a>
+            </h1>
         </div>
         <div id="container">
 {% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/categories.html	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,62 @@
+{% extends "base.html" %}
+
+{% block title %}{{block.super}} &gt; Recherche par arbre{% endblock %}
+
+{% block css_import %}
+{{block.super}}
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/ui-lightness/jquery-ui-1.8.16.custom.css" />
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/trees.css?refresh" />
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/cattree.css?refresh" />
+{% endblock %}
+
+{% block js_import %}
+{{block.super}}
+        <script src="{{STATIC_URL}}hdalab/lib/underscore-min.js"></script>
+        <script src="{{STATIC_URL}}hdalab/lib/mustache.js"></script>
+        <script src="{{STATIC_URL}}hdalab/lib/jquery-ui-1.8.16.custom.min.js"></script>
+        <script type="text/javascript">
+        endpoints = {
+            cat_search: "{% url cat_search %}",
+            cat_tree: "{% url cat_tree %}",
+            fill_tree: "{% url fill_tree %}",
+            datasheet: "{% url notice 'ID' %}"
+        };
+        </script>
+        <script src="{{STATIC_URL}}hdalab/js/trees.js?refresh"></script>
+        <script src="{{STATIC_URL}}hdalab/js/cattree.js?refresh"></script>
+{% endblock %}
+
+{% block categories_actif %}actif{% endblock %}
+
+{% block main_content %}
+    <div class="leftzone">
+        <h2>Explorer les domaines artistiques</h2>
+        <p>
+            Cette interface expérimentale présente les ressources d'<a href="http://histoiredesarts.culture.fr/" target="_blank">Histoire des Arts</a>,
+            ordonnées selon l'arborescence des <a href="http://fr.wikipedia.org/wiki/Sp%C3%A9cial:ArbreCat%C3%A9gorie/Espace_Cat%C3%A9gorie" target="_blank">catégories de Wikipédia</a>.
+            Seules les ressources les plus pertinentes sont affichées.
+        </p>
+        <ul class="disciplist">
+            <li><a href="#">Architecture</a></li>
+            <li><a href="#">Cinéma</a></li>
+            <li><a href="#">Littérature</a></li>
+            <li><a href="#">Musique</a></li>
+            <li><a href="#">Peinture</a></li>
+            <li><a href="#">Photographie</a></li>
+            <li><a href="#">Poésie</a></li>
+            <li><a href="#">Sculpture</a></li>
+            <li><a href="#">Théâtre</a></li>
+        </ul>
+        <h3>Recherche de catégories de Wikipédia&nbsp;: </h3>
+        <p>
+            <form id="catform"><input id="catsearch" /></form>
+        </p>
+        <div class="results hidden">
+            <h2>Résultats pour &laquo;&nbsp;<span class="label-name"></span>&nbsp;&raquo;&nbsp;:</h2>
+            <p class="category-results"><span class="category-count"></span> sous-catégorie(s)</p>
+            <p class="tag-results"><span class="tag-count"></span> tag(s)</p>
+            <p class="content-results"><span class="content-count"></span> contenu(s)</p>
+        </div>
+    </div>
+    <div id="tree" class="cattree"></div>
+{% endblock %}
\ No newline at end of file
--- a/src/hdalab/templates/facettes.html	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/templates/facettes.html	Tue Jun 17 10:32:57 2014 +0200
@@ -8,7 +8,7 @@
 {{block.super}}
         <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/lib/leaflet/leaflet.css" />
         <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/ui-lightness/jquery-ui-1.8.16.custom.css" />
-        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/facettes.css" />
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/facettes.css?refresh" />
 {% endblock %}
 
 {% block js_import %}
@@ -20,16 +20,16 @@
         <script src="{{STATIC_URL}}hdalab/lib/ZeroClipboard.js"></script>
 
         <script src="{% url jsi18n 'hdalab' %}"></script>
-        <script src="{{STATIC_URL}}hdalab/js/gomina.js?v=1"></script>
+        <script src="{{STATIC_URL}}hdalab/js/gomina.js?refresh"></script>
         
         <script type="text/javascript">
         gomNs.languageCode = '{{LANGUAGE_CODE}}';
         gomNs.urls = {
             'filter': "{% url filter %}",
             'session_info': "{% url session_info %}",
+            'countries': "{{STATIC_URL}}hdalab/lib/countries.geo.json",
             'tag_search': "{% url tag_search %}",
-            'tag_info': "{% url tag_info %}",
-            'countries': "{{STATIC_URL}}hdalab/lib/countries.geo.json",
+            'datasheet': "{% url notice 'ID' %}"
         };
         ZeroClipboard.setMoviePath('{{STATIC_URL}}hdalab/lib/ZeroClipboard.swf');
         </script>
@@ -122,12 +122,15 @@
             </div>
             <div class="bloc" id="bloc_taginfo">
                 <div class="barrebloc">
-                    <h2>{% trans "Information sur un mot-cle" %}</h2>
+                    <h2>{% trans "Rechercher un tag" %}</h2>
                 </div>
                 <div class="corpsbloc" id="taginfo">
-                    <div id="tagcount"></div>
-                    <div id="tagsearchwrap"><input id="tagsearch" value="{% trans "Rechercher un tag" %}" /></div>
-                    <div id="tagdata"></div>
+                    <form id="tagform">
+                        <input id="tagsearch" placeholder="{% trans "Rechercher un tag" %}" />
+                    </form>
+                    <div class="wpinfo">
+                        
+                    </div>
                 </div>
             </div>
             <div class="bloc" id="bloc_translationinfo">
--- a/src/hdalab/templates/index.html	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/templates/index.html	Tue Jun 17 10:32:57 2014 +0200
@@ -11,10 +11,10 @@
 {{block.super}}
         <script type="text/javascript">
             $(function() {
-                $(".entree-bloc").mouseover(function() {
-                    var _id = this.id;
+                $(".fond-bloc").mouseover(function() {
+                    var _this = this;
                     $(".overlay-bloc").each(function() {
-                        if ($(this).parent().attr("id") == _id) {
+                        if (this.parentNode == _this) {
                             $(this).slideDown();
                         } else {
                             $(this).slideUp();
@@ -32,13 +32,46 @@
 
 {% block main_content %}
     <h2>Explorez autrement le portail Histoire des Arts</h2>
-    <h3>Recherche par facettes</h3>
-    <div class="entree-bloc" id="bloc-facettes">
-        <div class="overlay-bloc">
-            <p>Recherchez les contenus d'Histoire des Arts par plusieurs points d'entrée&nbsp;: pays, périodes historiques, disciplines artistiques et mots-clés liés aux &oelig;vres.</p>
-            <p>Les éléments de l'interface sont à la fois des critères de recherche et des mode de visualisation des résultats&nbsp;: Au fur et à mesure de vos recherches, ils se mettent à jour pour refléter le nombre de contenus correspondant.</p>
-            <p class="goto"><a href="{% url facettes %}">&raquo;</a></p>
+    <div class="liste-applis">
+        <div class="bloc-appli">
+            <h3>Recherche par facettes</h3>
+            <div class="fond-bloc" id="bloc-facettes">
+                <div class="overlay-bloc">
+                    <p>Recherchez les contenus d'Histoire des Arts par plusieurs points d'entrée&nbsp;: pays, périodes historiques, disciplines artistiques et mots-clés liés aux &oelig;vres.</p>
+                    <p>Les éléments de l'interface sont à la fois des critères de recherche et des mode de visualisation des résultats&nbsp;: Au fur et à mesure de vos recherches, ils se mettent à jour pour refléter le nombre de contenus correspondant.</p>
+                    <p class="goto"><a href="{% url facettes %}">&raquo;</a></p>
+                </div>
+            </div>
         </div>
+
+        <div class="separateur-applis"></div>
+        <div class="bloc-appli">
+            <h3>Catégories de Wikipedia</h3>
+            <div class="fond-bloc" id="bloc-categories">
+                <div class="overlay-bloc">
+                    <p>Naviguez dans l'arbre des catégories de Wikipedia pour atteindre les contenus du portail Histoire des Arts.</p>
+                    <p>Recherchez une catégorie par son titre, puis explorez les sous-catégories et les tags qui y sont rattachés.</p>
+                    <p class="goto"><a href="{% url categories %}">&raquo;</a></p>
+                </div>
+            </div>
+        </div>
+        
+        <div class="separateur-applis"></div>
+        <div class="bloc-appli">
+            <h3>Navigation par thésaurus</h3>
+            <div class="fond-bloc" id="bloc-thesaurus">
+                <div class="overlay-bloc">
+                    <p>Cette interface présente deux extraits de thésaurus utilisés par le ministère de la Culture et de la Communication :</p>
+                    <ul>
+                        <li>La branche « Secteur urbain » du Thésaurus de l’architecture et de l’urbanisme (état 2010)</li>
+                        <li>La branche « Architecture d’habitation » du Thésaurus iconographique Garnier (état 2012)</li>
+                    </ul>
+                    <p class="goto"><a href="{% url thesaurus %}">&raquo;</a></p>
+                </div>
+            </div>
+        </div>
+
+        <div style="clear: both;"> </div>
     </div>
     <h3>À propos de HdA Lab</h3>
     <p>Le portail Histoire des arts a pour vocation de mettre à la disposition de publics prescripteurs &mdash;&nbsp;via un site Internet&nbsp;&mdash; une sélection de ressources culturelles et éducatives riches en lien avec le programme officiel de l’enseignement de l’Histoire des arts. Le volet HDA-Lab de ce projet s’inscrit dans le cadre d’une collaboration entre l’Institut de Recherche et d'Innovation (IRI) et le Ministère de la Culture et de la Communication. Ce projet de recherche et développement prévoit la réalisation d’une preuve de concept destinée à montrer le potentiel heuristique du tagging sémantique.</p>
@@ -71,7 +104,6 @@
     <div class="mini-table">
         <div class="half-bloc">
             <p>Département des Programmes Numériques</p>
-            <p>Chef de département&nbsp;: <strong>Thomas Aillagon</strong></p>
         </div>
         <div class="half-bloc">
             <p>Directeur&nbsp;: <strong>Bernard Stiegler</strong></p>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/notice.html	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,54 @@
+{% extends "base.html" %}
+
+{% block title %}{{block.super}} &gt; {{datasheet.title}}{% endblock %}
+
+{% block css_import %}
+{{block.super}}
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/notice.css?refresh" />
+{% endblock %}
+
+{% block js_import %}
+{{block.super}}
+        <script src="{{STATIC_URL}}hdalab/lib/underscore-min.js"></script>
+        <script src="{{STATIC_URL}}hdalab/js/notice.js?refresh"></script>
+{% endblock %}
+
+{% block main_content %}
+<div class="main-datasheet">
+    <h2><a href="{{datasheet.url}}" target="_blank">{{datasheet.title}}</a></h2>
+    <h3><a href="{{datasheet.organisation.website}}" target="_blank">{{datasheet.organisation.name}}</a></h3>
+    <img src="http://histoiredesarts.culture.fr/images/cached/images/{{datasheet.hda_id}}.jpg" />
+    <p>{{datasheet.description}}</p>
+    <ul>
+        <li>Accéder à cette ressource sur <a href="{{datasheet.url}}" target="_blank">{{domain}}</a></li>
+        <li>Plus d'informations sur <a href="http://histoiredesarts.culture.fr/notices/{{datasheet.hda_id}}/" target="_blank">histoiredesarts.culture.fr</a></li>
+    </ul>
+</div>
+
+<div class="tag-container">
+    <canvas class="tag-canvas"></canvas>
+    <div class="tags-main">
+        <h2>Mots-clés</h2>
+        <ul class="tags">
+        {% for t in ordered_tags %}
+            <li><span class="main-datasheet-tag" data-tag-id="{{t.tag.id}}">{{t.tag.label}}</span></li>
+        {% endfor %}
+        </ul>
+    </div>
+</div>
+
+<div class="related-datasheets">
+    <h2>Notices liées :</h2>
+    <ul class="datasheets">
+    {% for ds in related %}
+        <li class="datasheet">
+            <img src="http://histoiredesarts.culture.fr/images/cached/images/{{ds.hda_id}}.jpg" />
+            <h3><a href="{% url notice ds.hda_id %}">{{ds.title}}</a></h3>
+            <h4>{{ds.organisation_name}}</h4>
+            <ul class="datasheet-tags">{% for t in ds.ordered_tags %}<li data-tag-id="{{t.id}}" class="related-datasheet-tag {% if t.common %} common-tag{% endif %}">{{t.label}}</li>{% endfor %}</ul>
+        </li>
+    {% endfor %}
+    </ul>
+</div>
+    
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/templates/thesaurus.html	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,52 @@
+{% extends "base.html" %}
+
+{% block title %}{{block.super}} &gt; Recherche par arbre{% endblock %}
+
+{% block css_import %}
+{{block.super}}
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/ui-lightness/jquery-ui-1.8.16.custom.css" />
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/trees.css?refresh" />
+        <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}hdalab/css/thesaurus.css?refresh" />
+{% endblock %}
+
+{% block js_import %}
+{{block.super}}
+        <script src="{{STATIC_URL}}hdalab/lib/underscore-min.js"></script>
+        <script src="{{STATIC_URL}}hdalab/lib/mustache.js"></script>
+        <script src="{{STATIC_URL}}hdalab/lib/jquery-ui-1.8.16.custom.min.js"></script>
+        <script type="text/javascript">
+        endpoints = {
+            fill_tree: "{% url fill_tree %}",
+            datasheet: "{% url notice 'ID' %}"
+        };
+        </script>
+        <script src="{{STATIC_URL}}hdalab/js/trees.js?refresh"></script>
+        <script src="{{STATIC_URL}}hdalab/js/thesaurus.js?refresh"></script>
+{% endblock %}
+
+{% block thesaurus_actif %}actif{% endblock %}
+
+{% block main_content %}
+    <div class="explain">
+        <p>Cette interface présente deux extraits de thésaurus utilisés par le ministère de la Culture et de la Communication :</p>
+        <ul>
+            <li>La branche « Secteur urbain » du Thésaurus de l’architecture et de l’urbanisme (état 2010)</li>
+            <li>La branche « Architecture d’habitation » du Thésaurus iconographique Garnier (état 2012)</li>
+        </ul>
+        <p>Les mots-clés de ces branches ont été liés avec Wikipédia. Ils deviennent ainsi sémantiquement interopérables avec les tags d’HDA-Lab. Comme le montre l’interface, ce procédé permet d’organiser et de visualiser les tags et les ressources d'HDA-Lab en utilisant des thésaurus « métiers » externes. Dans cet extrait, le mot-clé « Cité jardin » est présenté, en vis-à-vis, dans deux univers sémantiques différents</p>
+    </div>
+    
+    <div class="column leftcol">
+        <h3>Arborescence 1</h3>
+        <div class="cattree">
+        
+        </div>
+    </div>
+    <div class="separator"></div>
+    <div class="column rightcol">
+        <h3>Arborescence 2</h3>
+        <div class="cattree">
+            
+        </div>
+    </div>
+{% endblock %}
\ No newline at end of file
--- a/src/hdalab/urls.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/urls.py	Tue Jun 17 10:32:57 2014 +0200
@@ -24,13 +24,19 @@
     url('^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog', {'domain':'djangojs'}, name='jsi18n'),
     
     url(r'^facettes/', TemplateView.as_view(template_name="facettes.html"), name='facettes'),
+    url(r'^categories/', TemplateView.as_view(template_name="categories.html"), name='categories'),
+    url(r'^thesaurus/', TemplateView.as_view(template_name="thesaurus.html"), name='thesaurus'),
     url(r'^$', TemplateView.as_view(template_name="index.html"), name='home'),
+    
+    url(r'^notice/(?P<hda_id>[\w-]+)$', 'hdalab.views.pages.datasheet', name='notice')
 
 )
 
 urlpatterns += patterns('hdalab.views.ajax',
     (r'^a/filter$', 'filter', {}, 'filter'),
-    (r'^a/taginfo$', 'taginfo', {}, 'tag_info'),
     (r'^a/sessioninfo$', 'sessioninfo', {}, 'session_info'),
     (r'^a/tagsearch$', 'tagsearch', {}, 'tag_search'),
+    (r'^a/catsearch$', 'catsearch', {}, 'cat_search'),
+    (r'^a/cattree$', 'cattree', {}, 'cat_tree'),
+    (r'^a/filltree$', 'filltree', {}, 'fill_tree'),
 )
--- a/src/hdalab/views/ajax.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/src/hdalab/views/ajax.py	Tue Jun 17 10:32:57 2014 +0200
@@ -6,11 +6,12 @@
 '''
 from django.conf import settings
 from django.core.cache import cache
-from django.db.models import Q, Count
+from django.db.models import Q, Count, Min
 from django.http import HttpResponse
 from hdabo.models import Tag, Datasheet, TaggedSheet
 from hdalab.models import HdaSession, Country, TagYears, DatasheetExtras
 from hdalab.models.dataviz import DbpediaFieldsTranslation, DbpediaFields
+from hdalab.models.categories import WpCategory, WpCategoryInclusion, TagWpCategory
 from hdalab.utils import fix_cache_key
 import copy
 import django.utils.simplejson as json
@@ -18,48 +19,9 @@
 import itertools
 import uuid
 
-def taginfo(request):
-    label = request.GET.get('label', None)
-    
-    resobj = {'requested_label' : label}
-        
-    resobj["content_count"] = Datasheet.objects.filter(taggedsheet__tag__label__iexact = label).distinct().count()
-
-    res = Tag.objects.select_related('dbpedia_fields').filter(~Q(dbpedia_uri = None), label__iexact = label).order_by('-dbpedia_uri')[0:1]
-    if len(res) == 1:
-        restag = res.get()
-        resobj["dbpedia_uri"] = restag.dbpedia_uri
-        if resobj["dbpedia_uri"] is not None and restag.dbpedia_fields is not None:
-            dbfield = restag.dbpedia_fields
-            resobj["abstract"] = dbfield.abstract
-            resobj["dbpedia_label"] = dbfield.label
-            resobj["thumbnail"] = dbfield.thumbnail
-            transqs = DbpediaFieldsTranslation.objects.filter(master=dbfield, language_code=request.LANGUAGE_CODE)[0:1]
-            if transqs:
-                trans = transqs.get()
-                resobj['translated_abstract'] = trans.abstract
-                resobj['translated_label'] = trans.label
-            else:
-                resobj['translated_abstract'] = dbfield.abstract
-                resobj['translated_label'] = dbfield.label
-
-    #res = Tag.objects.filter(label__iexact = label).order_by('-wikipedia_url')[0:1]
-    #if len(res) == 1:
-    #    resobj["wikipedia_url"] = res.get().wikipedia_url
-    if 'translated_label' in resobj:
-        wikipedia_label = resobj['translated_label']
-    else:
-        wikipedia_label = label
-    wikipedia_label = wikipedia_label[0].capitalize() + wikipedia_label[1:]
-    resobj["wikipedia_url"] = "http://%s.wikipedia.org/wiki/%s" % (request.LANGUAGE_CODE,wikipedia_label.replace(' ', '_'))
-# We don't use links at the moment, so I'll comment this line to speed up requests
-#    resobj["links"] = [{'subject':tl.subject.label, 'object':tl.object.label} for tl in TagLinks.objects.select_related().filter(Q(subject__label__iexact = label) | Q(object__label__iexact = label))]
-
-    return HttpResponse(content=json.dumps(resobj), mimetype='application/json')
-
-
 def tagtranslation(request):
     
+    lang = request.GET.get('lang',request.LANGUAGE_CODE)
     labels = request.GET.get('labels',None)
 
     if not labels:
@@ -75,13 +37,103 @@
             if tag.dbpedia_fields:
                 masters.append(tag.dbpedia_fields)
     
-    translationqs = DbpediaFieldsTranslation.objects.select_related("master", "master__tag").filter(master__in = masters, language_code=request.LANGUAGE_CODE)
+    translationqs = DbpediaFieldsTranslation.objects.select_related("master", "master__tag").filter(master__in = masters, language_code=lang)
     
     translations = dict([(t.master.label, t.label) for t in translationqs])
     
     return HttpResponse(content=json.dumps(translations), mimetype='application/json')
+
+def subcat(category, globtags, level, max_level ):
+    # recursive function used by cattree
+    catlabel = category.label
+    tags = Tag.objects.filter(wp_categories__wp_category = category).distinct()
+    taglabels = [k for k in dict([(t.label,t.label) for t in tags])]
+    resobj = {
+          'label': category.label,
+          'themes': [],
+          'contents': []
+      }
+    for label in taglabels:
+        if label == catlabel:
+            globtags[label] = {'level': level, 'access': resobj }
+        else:
+            tag_in_list = {'label' : label, 'contents': []}
+            resobj['themes'].append(tag_in_list)
+            globtags[label] = {'level': (level + 1), 'access': tag_in_list }
+            
+    if level < max_level:
+        subcats = WpCategory.objects.filter(parent_categories__parent_category = category)
+        resobj['themes'] += [subcat(subcats[i], globtags, level + 1, max_level ) for i in range(len(subcats))]
+    return resobj
+
+def cleantags(category):
+    if category.has_key('contents') and len(category['contents']) == 0:
+        del category['contents']
+    if category.has_key('contents'):
+        category['contents'] = sorted(category['contents'], key=lambda content: -content['score'])
+    if category.has_key('themes'):
+        themes = []
+        for theme in category['themes']:
+            clean_theme = cleantags(theme)
+            if clean_theme.has_key('themes') or clean_theme.has_key('contents'):
+                themes.append(clean_theme)
+        category['themes'] = sorted(themes, key=lambda cat: cat['label'])
+        if len(category['themes']) == 0:
+            del category['themes']
+    return category
+
+def cattree(request):
+    # Gets the category tree from a label
+    ROOT_MAX_TAG_ORDER = 8
+    MAX_TAG_ORDER = 8
+    MAX_LEVEL = 3
+    LEVEL_COEFF = 5
+    label = request.GET.get('label', None)
+    lowerlabel = label.lower()
+    globtags = {}
+    resobj = None
+    master_category = WpCategory.objects.filter(label__iexact=label)[0:1]
+    if len(master_category):
+        resobj = subcat(master_category[0], globtags, 1, MAX_LEVEL )
     
-
+#    tag_list = [k for k in globtags]
+    
+#    if len(tag_list):
+    contents = []
+#    datasheets = Datasheet.objects.filter(validated = True, taggedsheet__tag__label__in = tag_list, taggedsheet__order__lte = MAX_TAG_ORDER).distinct()
+    datasheets = Datasheet.objects.filter(validated = True, taggedsheet__tag__label__iexact = label, taggedsheet__order__lte = ROOT_MAX_TAG_ORDER).select_related('organisation').distinct()
+    for datasheet in datasheets:
+        # Calculating where we add the datasheet in the tree
+        maintag = None
+        maintagscore = -5
+        dsscore = 0
+        rootscore = 0
+        for ts in TaggedSheet.objects.select_related('tag','datasheet').filter(datasheet__id=datasheet.id,order__lte=MAX_TAG_ORDER):
+            label = ts.tag.label
+            if globtags.has_key(label):
+                score = LEVEL_COEFF * globtags[label]['level'] - ts.order
+                if score > maintagscore:
+                    maintagscore = score
+                    maintag = label
+                    dsscore = (MAX_TAG_ORDER - ts.order)
+                if label.lower() == lowerlabel:
+                    rootscore = (ROOT_MAX_TAG_ORDER - ts.order)
+        if maintag is not None:
+            globtags[maintag]['access']['contents'].append({
+                'id': datasheet.id,
+                'title': datasheet.title,
+                'url': datasheet.url,
+                'description': datasheet.description,
+                'hda_id': datasheet.hda_id,
+                'organization': datasheet.organisation.name,
+                'organization_url': datasheet.organisation.website,
+                'score': max(dsscore, rootscore)
+            })
+    cleantags(resobj)
+                    
+#        resobj['contents'] = [{'id': d.id, 'title': d.title, 'tags': [t.label for t in d.tags.filter(taggedsheet__order__lte=5)]} for d in datasheets]
+    
+    return HttpResponse(content=json.dumps(resobj), mimetype='application/json')
 
 def sessioninfo(request):
     
@@ -127,42 +179,89 @@
 def tagsearch(request):
     
     q = request.GET.get('term',None)
+    maxcount = int(request.GET.get('count','40'))
+    lang = request.GET.get('lang',request.LANGUAGE_CODE)
+    
+    stemming_langs = [ 'fr', 'en', 'de', 'it' ]
+    # For Japanese, there are no word boundaries, we should not use the regexp in that case
+    no_translate_langs = [ 'fr' ]
+    
     if q:
         lq = q.lower()
-    qs = Tag.objects.filter(datasheet__validated=True).filter( Q(label__icontains = q ) | Q(dbpedia_fields__translations__label__icontains = q, dbpedia_fields__translations__language_code=request.LANGUAGE_CODE), ~Q(dbpedia_uri = None)) if q else Tag.objects.filter(~Q(dbpedia_uri = None))       
-    qs = qs.annotate(nb=Count('datasheet')).order_by('-nb')[:20]
+        qs = Tag.objects.select_related('dbpedia_fields').filter(datasheet__validated=True)
+        qrx = '(\\m|\\b)%s'%q
+        if lang in no_translate_langs:
+            if lang in stemming_langs:
+                qs = qs.filter( label__iregex = qrx )
+            else:
+                qs = qs.filter( label__icontains = q )
+        else:
+            if lang in stemming_langs:
+                qs = qs.filter(dbpedia_fields__translations__label__iregex=qrx, dbpedia_fields__translations__language_code=lang, dbpedia_fields__translations__is_label_translated = True)
+            else:
+                qs = qs.filter(dbpedia_fields__translations__label__icontains=q, dbpedia_fields__translations__language_code=lang, dbpedia_fields__translations__is_label_translated = True)
+    else:
+        qs = Tag.objects.filter(~Q(dbpedia_uri = None))
+           
+    qs = qs.annotate(nb=Count('datasheet',distinct=True)).order_by('-nb')[:maxcount]
     
     qslist = list(qs)
     
-    transqs = DbpediaFieldsTranslation.objects.filter(master__tag__in = qslist, language_code=request.LANGUAGE_CODE).select_related("master")
-    
-    translations = dict([(tr.master.tag_id, tr.label) for tr in transqs])
+    if lang in no_translate_langs:
+        translations = {}
+    else:
+        transqs = DbpediaFieldsTranslation.objects.filter(master__tag__in = qslist, language_code=lang, is_label_translated=True).select_related("master")
+        translations = dict([(tr.master.tag_id, {'label':tr.label,'abstract':tr.abstract, 'is_label_translated': tr.is_label_translated}) for tr in transqs])
     
     res = []
     
     for t in qslist:
-        resobj = {'value':t.label,'nb':t.nb}
+        dbfields = t.dbpedia_fields
+        resobj = {'original_label':t.label,'nb':t.nb}
+        resobj['thumbnail'] = dbfields.thumbnail if dbfields is not None else None
+        
+#        if t.id in translations and not translations[t.id].get('is_label_translated', True):
+#            continue
         if t.id in translations:
-            resobj['label'] = translations[t.id]
+            resobj['value'] = translations[t.id]['label']
+            resobj['abstract'] = translations[t.id]['abstract']
         else:
-            resobj['label'] = t.label
-        if q is None or resobj['label'].lower().find(lq) != -1:
+            resobj['value'] = t.label
+            resobj['abstract'] = dbfields.abstract if dbfields is not None else None
+        if q is None or resobj['value'].lower().find(lq) != -1:
             res.append(resobj)
     
     return HttpResponse(content=json.dumps(res), mimetype='application/json')
 
+def catsearch(request):
+    
+    q = request.GET.get('term',None)
+    
+    # On ne récupère que les catégories qui sont également des tags
+    qrx = '(\\m|\\b)%s'%q
+    qs = Tag.objects.filter(label__iregex=q)
+    
+    labels = [tag.label for tag in qs]
+    
+    qs = WpCategory.objects.annotate(nb=Count('child_categories__child_category__tags')).filter(label__in = labels, nb__gt=0)
+    
+    res = [{'value':t.label} for t in qs]
+    
+    return HttpResponse(content=json.dumps(res), mimetype='application/json')
 
 def filter(request):
     
+    lang = request.GET.get('lang',request.LANGUAGE_CODE)
     periode = request.GET.get('period',None)
     label = request.GET.get('label', None)
     country = request.GET.get('country', None)
     contentlist = request.GET.get('contentlist', None)
-    max_tag_order = request.GET.get('mto', 12)
+    max_tag_order = int(request.GET.get('mto', '12'))
     content_count = request.GET.get('contentcount', 12)
     tag_count = request.GET.get('tagcount', 30)
+    no_translate_langs = [ 'fr' ]
     
-    key_parts = ("filter",request.LANGUAGE_CODE,periode,label,country,contentlist,max_tag_order,content_count,tag_count)
+    key_parts = ("filter",lang,periode,label,country,contentlist,max_tag_order,content_count,tag_count)
     key_parts = [unicode(p).encode("utf-8") for p in key_parts]
     
     cache_key = fix_cache_key("-".join(key_parts))
@@ -222,12 +321,13 @@
             
             contentqs = contentqs.filter(tagcond).distinct()
             matchtagidsqs = list(Tag.objects.select_related("dbpedia_fields").only("id").filter(tagcondid))
-            matchtagids = [t.id for t in matchtagidsqs]            
-            masters = [t.dbpedia_fields for t in matchtagidsqs if t.dbpedia_fields is not None]
+            matchtagids = [t.id for t in matchtagidsqs]
             
-            translationqs = DbpediaFieldsTranslation.objects.select_related("master", "master__tag").filter(master__in = masters, language_code=request.LANGUAGE_CODE)    
-            labeltranslations = [{'label':t.master.label, 'translated_label':t.label} for t in translationqs]
-
+            if lang not in no_translate_langs:
+                masters = [t.dbpedia_fields for t in matchtagidsqs if t.dbpedia_fields is not None]
+                
+                translationqs = DbpediaFieldsTranslation.objects.select_related("master", "master__tag").filter(master__in = masters, language_code=lang)    
+                labeltranslations = [{'label':t.master.label, 'translated_label':t.label} for t in translationqs]
             
             tagqs = tagqs.filter(datasheet__in = contentqs)
             countryqs = countryqs.filter(includes__tag__taggedsheet__datasheet__in = contentqs)
@@ -239,7 +339,7 @@
                         
         cont_count = contentqs.count()
         
-        contenus = dict([(content.id, {'score' : 0, 'tags' : [], 'id':content.id, 'title': content.title, 'description': content.description, 'url': content.url}) for content in contentqs[0:content_count]])
+        contenus = dict([(content.id, {'score' : 0, 'tags' : [], 'hda_id': content.hda_id, 'id':content.id, 'title': content.title, 'description': content.description, 'url': content.url}) for content in contentqs[0:content_count]])
         contentids = contenus.keys()
         
         qs = DatasheetExtras.objects.select_related('insee').filter(datasheet__in = contentids)
@@ -248,8 +348,11 @@
         
         qs = list(TaggedSheet.objects.select_related('tag', 'tag__dbpedia_fields').filter(datasheet__in = contentids, order__lte = max_tag_order).order_by('order'))
         
-        transqs = DbpediaFieldsTranslation.objects.filter(master__in = [ts.tag.dbpedia_fields for ts in qs], language_code = request.LANGUAGE_CODE)
-        translations = dict([(trans.master_id,trans.label) for trans in transqs])
+        translations = {}
+        
+        if lang not in no_translate_langs:
+            transqs = DbpediaFieldsTranslation.objects.filter(master__in = [ts.tag.dbpedia_fields for ts in qs], language_code = lang)
+            translations = dict([(trans.master_id,trans.label) for trans in transqs])
         
         for ts in qs:
             match_tag = ts.tag.id in matchtagids
@@ -275,9 +378,10 @@
         tagqslist = list(tagqs)
         
         dbpediafields = dict([(df.tag_id, df) for df in DbpediaFields.objects.filter(tag__in = tagqslist)])
-    
-        transqs = DbpediaFieldsTranslation.objects.filter(master__in = dbpediafields.values(), language_code = request.LANGUAGE_CODE)
-        translations = dict([(trans.master_id,trans.label) for trans in transqs])
+
+        if lang not in no_translate_langs:
+            transqs = DbpediaFieldsTranslation.objects.filter(master__in = dbpediafields.values(), language_code = lang)
+            translations = dict([(trans.master_id,trans.label) for trans in transqs])
     
         tags = [{'id': tag.id, 'label': tag.label, 'score': tag.nb, 'translated_label': translations.get(dbpediafields[tag.id].id, tag.label) if tag.id in dbpediafields else tag.label} for tag in tagqslist]
     
@@ -285,10 +389,10 @@
         countries = dict([(country.dbpedia_uri, country.nb) for country in countryqs])
     
         discqslist = list(discqs.annotate(nb=Count('taggedsheet')).order_by('-nb')[:10])
-            
-        transqs = DbpediaFieldsTranslation.objects.filter(master__in = [tag.dbpedia_fields for tag in discqslist], language_code = request.LANGUAGE_CODE)
-        translations = dict([(trans.master_id,trans.label) for trans in transqs])
-    
+
+        if lang not in no_translate_langs:
+            transqs = DbpediaFieldsTranslation.objects.filter(master__in = [tag.dbpedia_fields for tag in discqslist], language_code = lang)
+            translations = dict([(trans.master_id,trans.label) for trans in transqs])
         
         disciplines = [{'label':tag.label,'score':tag.nb, 'translated_label': translations.get(tag.dbpedia_fields.id, tag.label) if tag.dbpedia_fields is not None else tag.label} for tag in discqslist]
         
@@ -319,3 +423,36 @@
         cache.set(cache_key, outputstr)
         
     return HttpResponse(content=outputstr, mimetype='application/json')
+
+def subtree(tree):
+    MAX_TAG_ORDER = 16
+    label = tree['label']
+    sub = tree.get('contents',[])
+    
+    datasheets = Datasheet.objects.filter(validated = True, taggedsheet__tag__label__iexact = label, taggedsheet__order__lte = MAX_TAG_ORDER).annotate(tagorder=Min('taggedsheet__order')).select_related('organisation').distinct()
+    
+    contents = [{ 'description': ds.description, 'title': ds.title, 'url': ds.url, 'score': int((MAX_TAG_ORDER - ds.tagorder)/2), 'id': ds.id, 'hda_id': ds.hda_id, 'organization': ds.organisation.name, 'organization_url': ds.organisation.website } for ds in datasheets]
+    
+    contents = sorted(contents, key=lambda e: -e['score'])
+    
+    res = { 'label': label }
+    
+    if len(contents):
+        res['contents'] = contents
+    
+    if len(sub):
+        subcats = [subtree(st) for st in sub]
+        subcats = [sc for sc in subcats if len(sc.get('contents',[])) or len(sc.get('themes',[]))]
+        res['themes'] = subcats
+    
+    return res
+
+def filltree(request):
+    
+    tree = request.GET.get('tree','{}')
+    
+    treeobj = json.loads(tree)
+    
+    res = subtree(treeobj)
+        
+    return HttpResponse(content=json.dumps(res), mimetype='application/json')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hdalab/views/pages.py	Tue Jun 17 10:32:57 2014 +0200
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+from django.shortcuts import render_to_response, redirect
+from django.template import RequestContext
+from hdabo.models import Datasheet, TaggedSheet
+import re
+import django.utils.simplejson as json
+
+def datasheet(request, hda_id=None):
+    MAX_TAG = 15
+    MAX_RELATED = 50
+    
+    datasheet = Datasheet.objects.select_related("organisation").get(hda_id=hda_id)
+    
+    domain = re.findall(r"^https?://(www\.)?([^/]+)",datasheet.url)
+    ordered_tags = TaggedSheet.objects.filter(datasheet=datasheet,order__lte=MAX_TAG).select_related("tag").order_by('order')
+    tags = [t.tag.id for t in ordered_tags]
+    tagorders = dict([(t.tag.id,t.order) for t in ordered_tags])
+    tsqs = TaggedSheet.objects.exclude(datasheet=datasheet).filter(order__lte=MAX_TAG,tag_id__in=tags)
+    dsscores = {}
+    addtoscore = 2*MAX_TAG
+    
+    for ts in tsqs:
+        a_order = tagorders[ts.tag_id]
+        b_order = ts.order
+        score = addtoscore - a_order - b_order
+        dsscore = dsscores.get(ts.datasheet_id,0)
+        dsscores[ts.datasheet_id] = dsscore + score
+    relatedqs = Datasheet.objects.filter(id__in=dsscores.keys()).select_related("organisation")
+    relatedds = [{
+        'id': ds.id,
+        'hda_id': ds.hda_id,
+        'title': ds.title,
+        'description': ds.description,
+        'organisation_name': ds.organisation.name,
+        'organisation_url': ds.organisation.website,
+        'score': dsscores.get(ds.id,0),
+    } for ds in relatedqs]
+    relatedds = sorted(relatedds, key=lambda ds: -ds['score'])[:MAX_RELATED]
+    
+    for ds in relatedds:
+        otqs = TaggedSheet.objects.filter(datasheet_id=ds['id'],order__lte=MAX_TAG).select_related("tag").order_by('order')
+        ds['ordered_tags'] = [{
+            'id': t.tag.id,
+            'label': t.tag.label,
+            'order': t.order,
+            'common' : (t.tag.id in tags)
+        } for t in otqs]
+    
+    return render_to_response(
+        "notice.html",
+        {
+            'datasheet':datasheet,
+            'domain': domain[0][1] if domain else "",
+            'ordered_tags': ordered_tags,
+            'related': relatedds,
+        },
+        context_instance=RequestContext(request)
+    )
--- a/virtualenv/res/lib/lib_create_env.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/virtualenv/res/lib/lib_create_env.py	Tue Jun 17 10:32:57 2014 +0200
@@ -7,47 +7,66 @@
 import urllib
 import platform
 import patch
+import struct
+import glob
+import re
 
 join = os.path.join
 system_str = platform.system()
 
-
 URLS = {
     #'': {'setup': '', 'url':'', 'local':''},
-    'DISTRIBUTE': {'setup': 'distribute', 'url':'http://pypi.python.org/packages/source/d/distribute/distribute-0.6.14.tar.gz', 'local':"distribute-0.6.14.tar.gz"},
-    'DJANGO': {'setup': 'django', 'url': 'http://www.djangoproject.com/download/1.6.5/tarball/', 'local':"Django-1.6.5.tar.gz"},
-    'DJANGO-EXTENSIONS': { 'setup': 'django-extensions', 'url':'https://github.com/django-extensions/django-extensions/archive/1.3.7.tar.gz', 'local':"django-extensions-1.3.7.tar.gz"},
-    'SOUTH': { 'setup': 'South', 'url':'http://www.aeracode.org/releases/south/south-0.8.4.tar.gz', 'local':"south-0.8.4.tar.gz"},
-    'HTTPLIB2': { 'setup': 'python-httplib2', 'url':'http://httplib2.googlecode.com/files/httplib2-0.6.0.tar.gz', 'local':"httplib2-0.6.0.tar.gz"},
-    'HAYSTACK': { 'setup': 'haystack', 'url':'https://github.com/toastdriven/django-haystack/archive/v2.1.0.tar.gz', 'local': "django-haystack-2.1.0.tar.gz"},
-    'WHOOSH' : { 'setup': 'Whoosh', 'url': 'https://pypi.python.org/packages/source/W/Whoosh/Whoosh-2.5.7.tar.gz', 'local': 'whoosh-2.5.7.tar.gz'},
-    'WIKITOOLS' : { 'setup': 'wikitools', 'url': 'wikitools.tar.bz2', 'local': 'wikitools.tar.bz2'},
-    'RDFLIB' : { 'setup': 'rdflib', 'url': 'http://rdflib.googlecode.com/files/rdflib-3.2.0.tar.gz', 'local': 'rdflib-3.2.0.tar.gz'},
-    'SPARQLWRAPPER' : { 'setup': 'SPARQLWrapper', 'url': 'http://downloads.sourceforge.net/project/sparql-wrapper/sparql-wrapper-python/1.5.0/SPARQLWrapper-1.5.0.tar.gz', 'local' : 'SPARQLWrapper-1.5.0.tar.gz'},
-    'REQUESTS' : { 'setup': 'requests', 'url': 'https://github.com/kennethreitz/requests/archive/v2.3.0.tar.gz', 'local' : 'requests-2.3.0.tar.gz'},
-    'PYELASTICSEARCH' : { 'setup': 'requests', 'url': 'https://github.com/rhec/pyelasticsearch/archive/0.6.1.tar.gz', 'local' : 'pyelasticsearch-0.6.1.tar.gz'},
+    'DISTRIBUTE': {'setup': 'distribute', 'url':'http://pypi.python.org/packages/source/d/distribute/distribute-0.6.24.tar.gz', 'local':"distribute-0.6.24.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'DJANGO': {'setup': 'django', 'url': 'http://www.djangoproject.com/download/1.6.5/tarball/', 'local':"Django-1.6.5.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'DJANGO-EXTENSIONS': { 'setup': 'django-extensions', 'url':'https://github.com/django-extensions/django-extensions/tarball/1.3.7', 'local':"django-extensions-1.3.7.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'HTTPLIB2': { 'setup': 'python-httplib2', 'url':'http://code.google.com/p/httplib2/downloads/detail?name=httplib2-0.7.4.tar.gz&can=2&q=', 'local':"httplib2-0.7.4.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'SOUTH': { 'setup': 'South', 'url':'http://www.aeracode.org/releases/south/south-0.8.4.tar.gz', 'local':"south-0.8.4.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'PYCRYPTO': {'setup': 'pycrypto', 'url':'https://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.6.tar.gz', 'local':'pycrypto-2.6.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'SSH': {'setup': 'ssh', 'url':'http://pypi.python.org/packages/source/s/ssh/ssh-1.7.14.tar.gz#md5=4cdd0549ef4699bd67b96264d3b21427', 'local':'ssh-1.7.14.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'FABRIC': {'setup': 'fabric', 'url':'https://github.com/fabric/fabric/tarball/1.4.2', 'local':'fabric-1.4.2.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'MERCURIAL': {'setup': 'mercurial', 'url':'http://mercurial.selenic.com/release/mercurial-2.2.3.tar.gz', 'local':'mercurial-2.2.3.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}},
+    'WHOOSH': {'setup': 'whoosh', 'url':'https://pypi.python.org/packages/source/W/Whoosh/Whoosh-2.5.7.tar.gz', 'local':'whoosh-2.5.7.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
+    'WIKITOOLS' : { 'setup': 'wikitools', 'url': 'wikitools.tar.bz2', 'local': 'wikitools.tar.bz2', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'ISODATE' : {'setup': 'isodate', 'url': 'http://pypi.python.org/packages/source/i/isodate/isodate-0.4.8.tar.gz', 'local': 'isodate-0.4.8.tar.gz', 'install' : {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+    'RDFLIB' : { 'setup': 'rdflib', 'url': 'http://rdflib.googlecode.com/files/rdflib-3.2.0.tar.gz', 'local': 'rdflib-3.2.0.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.0/SPARQLWrapper-1.5.0.tar.gz', 'local' : 'SPARQLWrapper-1.5.0.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},    
+    'REQUESTS' : { 'setup': 'requests', 'url': 'https://github.com/kennethreitz/requests/archive/v2.3.0.tar.gz', 'local' : 'requests-2.3.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}},    
 }
 
 if system_str == 'Windows':
+    
+    size = 8 * struct.calcsize("P")
+    if size==32:
+        mysqlres = "MySQL-python-1.2.3.win32-py2.7.exe"
+    else:
+        mysqlres = "MySQL-python-1.2.3.win-amd64-py2.7.exe"
+    
     URLS.update({
-        'PSYCOPG2': {'setup': 'psycopg2','url': 'psycopg2-2.0.14.win32-py2.6-pg8.4.3-release.zip', 'local':"psycopg2-2.0.14.win32-py2.6-pg8.4.3-release.zip"},
-        'JCC': {'setup': 'jcc', 'url': 'http://pylucene-win32-binary.googlecode.com/files/JCC-2.6-py2.6-win32.egg', 'local':"JCC-2.6-py2.6-win32.egg"},
-        #'PYLUCENE': {'setup': 'pylucene', 'url': 'http://pylucene-win32-binary.googlecode.com/files/lucene-3.0.2-py2.6-win32.egg', 'local':"lucene-3.0.2-py2.6-win32.egg"},
-        'PIL': {'setup': 'pil', 'url': 'http://effbot.org/media/downloads/PIL-1.1.7.win32-py2.6.exe', 'local':"PIL-1.1.7.win32-py2.6.exe"},
-        'LXML': {'setup': 'lxml', 'url': 'http://pypi.python.org/packages/2.6/l/lxml/lxml-2.2.2-py2.6-win32.egg', 'local':"lxml-2.2.2-py2.6-win32.egg"},
-        'PYYAML' : { 'setup': 'PyYAML', 'url': 'http://pyyaml.org/download/pyyaml/PyYAML-3.09.win32-py2.6.exe', 'local': 'PyYAML-3.09.win32-py2.6.exe'},
+        'PSYCOPG2': {'setup': 'psycopg2','url': 'psycopg2-2.0.14.win32-py2.6-pg8.4.3-release.zip', 'local':"psycopg2-2.0.14.win32-py2.6-pg8.4.3-release.zip", 'install': {'method': 'install_psycopg2', 'option_str': None, 'dict_extra_env': None}},
+        'PIL': {'setup': 'pil', 'url': 'http://effbot.org/media/downloads/PIL-1.1.7.win32-py2.6.exe', 'local':"PIL-1.1.7.win32-py2.6.exe", 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}},
+        'LXML': {'setup': 'lxml', 'url': 'http://pypi.python.org/packages/2.6/l/lxml/lxml-2.2.2-py2.6-win32.egg', 'local':"lxml-2.2.2-py2.6-win32.egg", 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}},
+        'PYYAML' : { 'setup': 'PyYAML', 'url': 'http://pyyaml.org/download/pyyaml/PyYAML-3.09.win32-py2.6.exe', 'local': 'PyYAML-3.09.win32-py2.6.exe', 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}},
         'PYSTEMMER' : { 'setup': 'pystemmer', 'url': 'PyStemmer_compiled_for_pc.zip', 'local': 'PyStemmer_compiled_for_pc.zip'},
     })
 else:
+    if system_str == "Darwin":        
+        lxml_options = {'STATIC_DEPS': 'true', 'LIBXML2_VERSION': '2.9.1', 'LIBXSLT_VERSION': '1.1.28', 'LIBICONV_VERSION': '1.14'}
+        lxml_method = 'easy_install'
+        mysql_method = 'install_mysql'
+    else:
+        lxml_options = None
+        lxml_method = 'pip'
+        mysql_method = 'pip'
+
     URLS.update({
-        'PSYCOPG2': {'setup': 'psycopg2','url': 'http://www.psycopg.org/psycopg/tarballs/PSYCOPG-2-4/psycopg2-2.4.tar.gz', 'local':"psycopg2-2.4.tar.gz"},
-        #'PYLUCENE': {'setup': 'pylucene', 'url': 'http://mirrors.ircam.fr/pub/apache/lucene/pylucene/pylucene-4.8.0-1-src.tar.gz', 'local':"pylucene-4.8.0-1-src.tar.gz"},
-        'PIL': {'setup': 'pil', 'url': 'http://effbot.org/downloads/Imaging-1.1.7.tar.gz', 'local':"Imaging-1.1.7.tar.gz"},
-        'LXML': {'setup': 'lxml', 'url':"lxml-3.2.1.tar.bz2", 'local':"lxml-3.2.1.tar.bz2"},
-        'PYYAML' : { 'setup': 'PyYAML', 'url': 'http://pyyaml.org/download/pyyaml/PyYAML-3.09.tar.gz', 'local': 'PyYAML-3.09.tar.gz'},
+        'PSYCOPG2': {'setup': 'psycopg2','url': 'https://pypi.python.org/packages/source/p/psycopg2/psycopg2-2.5.3.tar.gz', 'local':"psycopg2-2.5.3.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
+        'PIL': {'setup': 'pil', 'url': 'http://effbot.org/downloads/Imaging-1.1.7.tar.gz', 'local':"Imaging-1.1.7.tar.gz", 'install': {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}},
+        'LXML': {'setup': 'lxml', 'url':"lxml-3.2.1.tar.bz2", 'local':"lxml-3.2.1.tar.bz2", 'install': {'method': lxml_method, 'option_str': None, 'dict_extra_env': lxml_options}},
+        'PYYAML' : { 'setup': 'PyYAML', 'url': 'http://pyyaml.org/download/pyyaml/PyYAML-3.09.tar.gz', 'local': 'PyYAML-3.09.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}},
     })
-
-
+    
 
 class ResourcesEnv(object):
 
@@ -60,15 +79,17 @@
     def get_src_base_path(self, fpath):
         return os.path.abspath(os.path.join(self.src_base, fpath)).replace("\\","/")
     
-    def __add_package_def(self, key, setup, url, local):
-        self.URLS[key] = {'setup':setup, 'url':url, 'local':self.get_src_base_path(local)}
-
+    def __add_package_def(self, key, dict):
+        self.URLS[key] = dict
+        
     def __init_url(self, urls):
         for key, url_dict in urls.items():
-            url = url_dict['url']
-            if not url.startswith("http://"):
-                url = self.get_src_base_path(url)
-            self.__add_package_def(key, url_dict["setup"], url, url_dict["local"])
+            url_dict_copy = url_dict.copy()
+            if not url_dict['url'].startswith("http://"):
+                url_dict_copy['url'] = self.get_src_base_path(url_dict['url'])
+            url_dict_copy['local'] = self.get_src_base_path(url_dict['local'])            
+            
+            self.__add_package_def(key, url_dict_copy )
 
 def ensure_dir(dir, logger):
     if not os.path.exists(dir):
@@ -86,111 +107,13 @@
         '--type-install',
         metavar='type_install',
         dest='type_install',
-        default='local',
-        help='type install : local, url, setup')
+        help='type install : local, url, setup - default : local')
     parser.add_option(
         '--ignore-packages',
         metavar='ignore_packages',
         dest='ignore_packages',
         default=None,
-        help='list of comma separated keys for package to ignore')
-
-def adjust_options(options, args):
-    pass
-
-
-def install_pylucene(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
-    
-    logger.notify("Get Pylucene from %s " % res_env.URLS['PYLUCENE'][res_source_key])
-    pylucene_src = os.path.join(src_dir,"pylucene.tar.gz")
-    if res_source_key == 'local':
-        shutil.copy(res_env.URLS['PYLUCENE'][res_source_key], pylucene_src)
-    else:
-        urllib.urlretrieve(res_env.URLS['PYLUCENE'][res_source_key], pylucene_src)
-    tf = tarfile.open(pylucene_src,'r:gz')
-    pylucene_base_path = os.path.join(src_dir,"pylucene") 
-    logger.notify("Extract Pylucene to %s " % pylucene_base_path)
-    tf.extractall(pylucene_base_path)
-    tf.close()
-    
-    pylucene_src_path = os.path.join(pylucene_base_path, os.listdir(pylucene_base_path)[0])
-    jcc_src_path = os.path.abspath(os.path.join(pylucene_src_path,"jcc"))
-    
-    #install jcc
-
-    #patch for linux
-    if system_str == 'Linux' :
-        olddir = os.getcwd()
-        setuptools_path = os.path.join(lib_dir, 'site-packages', 'setuptools')
-        if os.path.exists(setuptools_path) and os.path.isdir(setuptools_path):
-            patch_dest_path = os.path.join(lib_dir, 'site-packages')
-        else:
-            patch_dest_path = os.path.join(lib_dir,'site-packages','setuptools-0.6c11-py%s.%s.egg' % (sys.version_info[0], sys.version_info[1]))
-            if os.path.isfile(patch_dest_path):
-                # must unzip egg
-                # rename file and etract all
-                shutil.move(patch_dest_path, patch_dest_path + ".zip")
-                zf = zipfile.ZipFile(patch_dest_path + ".zip",'r')
-                zf.extractall(patch_dest_path)
-                os.remove(patch_dest_path + ".zip")
-        logger.notify("Patch jcc : %s " % (patch_dest_path))
-        os.chdir(patch_dest_path)
-        p = patch.fromfile(os.path.join(jcc_src_path,"jcc","patches","patch.43.0.6c11"))
-        p.apply()
-        os.chdir(olddir)
-
-    logger.notify("Install jcc")
-    call_subprocess([os.path.abspath(os.path.join(home_dir, 'bin', 'python')), 'setup.py', 'install'],
-                    cwd=jcc_src_path,
-                    filter_stdout=filter_python_develop,
-                    show_stdout=True)
-    #install pylucene
-    
-    logger.notify("Install pylucene")
-    #modify makefile
-    makefile_path = os.path.join(pylucene_src_path,"Makefile")
-    logger.notify("Modify makefile %s " % makefile_path)
-    shutil.move( makefile_path, makefile_path+"~" )
-
-    destination= open( makefile_path, "w" )
-    source= open( makefile_path+"~", "r" )
-    destination.write("PREFIX_PYTHON="+os.path.abspath(home_dir)+"\n")
-    destination.write("ANT=ant\n")
-    destination.write("PYTHON=$(PREFIX_PYTHON)/bin/python\n")
-    
-    if system_str == "Darwin":
-        if sys.version_info >= (2,6):
-            destination.write("JCC=$(PYTHON) -m jcc.__main__ --shared --arch x86_64 --arch i386\n")
-        else:
-            destination.write("JCC=$(PYTHON) -m jcc --shared --arch x86_64 --arch i386\n")
-        destination.write("NUM_FILES=2\n")
-    elif system_str == "Windows":
-        destination.write("JCC=$(PYTHON) -m jcc.__main__ --shared --arch x86_64 --arch i386\n")
-        destination.write("NUM_FILES=2\n")
-    else:
-        if sys.version_info >= (2,6) and sys.version_info <= (2,7):
-            destination.write("JCC=$(PYTHON) -m jcc.__main__ --shared\n")
-        else:
-            destination.write("JCC=$(PYTHON) -m jcc --shared\n")
-        destination.write("NUM_FILES=2\n")
-    for line in source:
-        destination.write( line )
-    source.close()
-    destination.close()
-    os.remove(makefile_path+"~" )
-
-    logger.notify("pylucene make")
-    call_subprocess(['make'],
-                    cwd=os.path.abspath(pylucene_src_path),
-                    filter_stdout=filter_python_develop,
-                    show_stdout=True)
-
-    logger.notify("pylucene make install")
-    call_subprocess(['make', 'install'],
-                    cwd=os.path.abspath(pylucene_src_path),
-                    filter_stdout=filter_python_develop,
-                    show_stdout=True)
-    
+        help='list of comma separated keys for package to ignore')    
 
 def install_psycopg2(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
     psycopg2_src = os.path.join(src_dir,"psycopg2.zip")
@@ -203,7 +126,91 @@
     
     psycopg2_src_path = os.path.join(psycopg2_base_path, os.listdir(psycopg2_base_path)[0])
     shutil.copytree(os.path.join(psycopg2_src_path, 'psycopg2'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages', 'psycopg2')))
-    shutil.copy(os.path.join(psycopg2_src_path, 'psycopg2-2.0.14-py2.6.egg-info'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages')))
+    shutil.copy(os.path.join(psycopg2_src_path, 'psycopg2-2.0.14-py2.6.egg-info'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages', 'site-packages')))
+    
+
+def install_mysql(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
+    
+    args = [os.path.abspath(os.path.join(home_dir, 'bin', 'pip')), 'install', res_env.URLS['MYSQL'][res_source_key]]                
+    if option_str :
+        args.insert(4,option_str)
+    call_subprocess(args,
+            cwd=os.path.abspath(tmp_dir),
+            filter_stdout=filter_python_develop,
+            show_stdout=True,
+            extra_env=extra_env)
+
+    mysqlconfig_output = []
+    
+    call_subprocess(['mysql_config', '--libmysqld-libs'],
+        cwd=os.path.abspath(tmp_dir),
+        filter_stdout=lambda line: mysqlconfig_output.append(line),
+        show_stdout=True)
+        
+    mysqlconfig_output = "".join(mysqlconfig_output)
+    m = re.search("\-L[\'\"]?([\w\/]+)[\'\"]?", mysqlconfig_output)
+    if m:
+        repdylibpath = m.group(1)
+    else:
+        repdylibpath = '/usr/local/mysql/lib'
+        
+    dyliblist = glob.glob(repdylibpath+"/libmysqlclient.*.dylib")
+    def key_func(s):
+        m = re.match(repdylibpath+"/libmysqlclient\.([\d]+)\.dylib", s)
+        if m:
+            return int(m.group(1))
+        else:
+            return sys.maxint
+    dyliblist.sort(key=key_func)
+    
+    if dyliblist:
+        dylibpath = dyliblist[0]
+    else:
+        dylibpath = '/usr/local/mysql/lib/libmysqlclient.18.dylib'
+        
+    dylibname = os.path.basename(dylibpath)    
+    sopath = os.path.join(os.path.abspath(lib_dir), 'site-packages', '_mysql.so')
+    
+    call_subprocess(['install_name_tool', '-change', dylibname, dylibpath, sopath],
+        cwd=os.path.abspath(tmp_dir),
+        filter_stdout=filter_python_develop,
+        show_stdout=True)
+
+
+def gen_install_comp_lib(lib_name, lib_key, configure_options=[]):
+    
+    def install_lib(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
+        lib_src = os.path.join(src_dir,lib_name+".tar.gz")
+        shutil.copy(res_env.URLS[lib_key][res_source_key], lib_src)
+        tf = tarfile.open(lib_src,'r:gz')
+        lib_base_path = os.path.join(src_dir, lib_name) 
+        logger.notify("Extract %s to %s " % (lib_name,lib_base_path))
+        tf.extractall(lib_base_path)
+        tf.close()
+        
+        lib_src_path = os.path.join(lib_base_path, os.listdir(lib_base_path)[0])
+    
+        logger.notify(libname + " configure")
+        call_subprocess(['configure', '--prefix='+os.path.abspath(home_dir)] + configure_options,
+                        cwd=os.path.abspath(lib_src_path),
+                        filter_stdout=filter_python_develop,
+                        show_stdout=True)
+        
+        logger.notify(libname + " make")
+        call_subprocess(['make'],
+                        cwd=os.path.abspath(lib_src_path),
+                        filter_stdout=filter_python_develop,
+                        show_stdout=True)
+    
+        logger.notify(libname + "make install")
+        call_subprocess(['make', 'install'],
+                        cwd=os.path.abspath(lib_src_path),
+                        filter_stdout=filter_python_develop,
+                        show_stdout=True)
+        return install_lib
+
+install_libjpeg = gen_install_comp_lib("libjpeg", "LIBJPEG", ['--enable-shared'])
+install_zlib = gen_install_comp_lib("zlib", "ZLIB", [])
 
 def install_pystemmer(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
     print "install PYSTEMMER from " + res_env.URLS['PYSTEMMER'][res_source_key]
@@ -218,45 +225,8 @@
     shutil.copy(os.path.join(pystemmer_base_path, 'Stemmer.pyd'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages')))
     shutil.copy(os.path.join(pystemmer_base_path, 'PyStemmer-1.0.1-py2.6.egg-info'), os.path.abspath(os.path.join(home_dir, 'Lib/site-packages')))
     
-    
-#TO DO does not work in virtual env
-def install_libyaml(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop):
-    logger.notify("Get libyaml from %s " % res_env.URLS['LIBYAML'][res_source_key])
-    libyaml_src = os.path.join(src_dir,"libyaml.tar.gz")
-    if res_source_key == 'local':
-        shutil.copy(res_env.URLS['LIBYAML'][res_source_key], libyaml_src)
-    else:
-        urllib.urlretrieve(res_env.URLS['LIBYAML'][res_source_key], libyaml_src)
-    tf = tarfile.open(pylucene_src,'r:gz')
-    libyaml_base_path = os.path.join(src_dir,"libyaml") 
-    logger.notify("Extract libyaml to %s " % libyaml_base_path)
-    tf.extractall(libyaml_base_path)
-    tf.close()
-    
-    libyaml_src_path = os.path.join(libyaml_base_path, os.listdir(libyaml_base_path)[0])
-    
-    logger.notify("libyaml configure")
-    call_subprocess(['configure'],
-                    cwd=os.path.abspath(libyaml_src_path),
-                    filter_stdout=filter_python_develop,
-                    show_stdout=True)
 
-    logger.notify("libyaml make")
-    call_subprocess(['make'],
-                    cwd=os.path.abspath(libyaml_src_path),
-                    filter_stdout=filter_python_develop,
-                    show_stdout=True)
-
-    logger.notify("libyaml make install")
-    call_subprocess(['make', 'install'],
-                    cwd=os.path.abspath(libyaml_src_path),
-                    filter_stdout=filter_python_develop,
-                    show_stdout=True)
-    
-
-
-
-def lib_generate_install_methods(path_locations, src_base, Logger, call_subprocess, normal_installs, urls=None):
+def lib_generate_install_methods(path_locations, src_base, Logger, call_subprocess, normal_installs, options_to_add=None, urls= None):
     
     all_urls = URLS.copy()
     if urls is not None:
@@ -318,20 +288,38 @@
         ensure_dir(src_dir, logger)
         ensure_dir(tmp_dir, logger)
         system_str = platform.system()
-        
-        res_source_key = options.type_install
+                
+        res_source_key = getattr(options, 'type_install') if hasattr(options, 'type_install') else 'local' #.get('type_install', 'local')
+        if res_source_key is None:
+            res_source_key = local
         
         ignore_packages = []
         
+        if system_str == 'Windows':
+            default_install_options = {'method': 'easy_install', 'option_str': None, 'dict_extra_env': None}
+        else:
+            default_install_options = {'method': 'pip', 'option_str': None, 'dict_extra_env': None}
+            
         if options.ignore_packages :
             ignore_packages = options.ignore_packages.split(",")
         
         logger.indent += 2
         try:    
-            for key, method, option_str, extra_env in res_env.NORMAL_INSTALL:
+            for key in res_env.NORMAL_INSTALL:
+                if key not in res_env.URLS:
+                    logger.notify("%s not found in def : passing" % (key,))
+                install_options = res_env.URLS[key].get('install', None)
+                if install_options is None:
+                    install_options = default_install_options
+                method = install_options.get('method', default_install_options['method'])
+                option_str = install_options.get('option_str', default_install_options['option_str'])
+                extra_env = install_options.get('dict_extra_env', default_install_options['dict_extra_env'])
+                #isinstance(lst, (list, tuple))
                 if key not in ignore_packages:
                     if callable(method):
                         method(option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop)
+                    elif method in globals() and callable(globals()[method]) and method not in ['pip', 'easy_install']:  
+                        globals()[method](option_str, extra_env, res_source_key, home_dir, lib_dir, tmp_dir, src_dir, res_env, logger, call_subprocess, filter_python_develop)
                     else:
                         normal_install(key, method, option_str, extra_env, res_source_key, home_dir, tmp_dir, res_env, logger, call_subprocess)
                             
@@ -344,5 +332,12 @@
         logger.notify('Run "%s Package" to install new packages that provide builds'
                       % join(script_dir, 'easy_install'))
     
+    def adjust_options(options, args):
+        if not options_to_add:
+            pass
+        for opt in options_to_add:
+            test_opt = opt.split('=',1)[0]
+            if not hasattr(options,test_opt) or getattr(options, test_opt) is None:                
+                setattr(options, test_opt,opt.split('=',1)[1] if "=" in opt else True)
 
     return adjust_options, extend_parser, after_install
Binary file virtualenv/res/src/Django-1.4.2.tar.gz has changed
Binary file virtualenv/res/src/JCC-2.6-py2.6-win32.egg has changed
Binary file virtualenv/res/src/distribute-0.6.14.tar.gz has changed
Binary file virtualenv/res/src/distribute-0.6.24.tar.gz has changed
Binary file virtualenv/res/src/django-extensions-0.6.tar.gz has changed
Binary file virtualenv/res/src/django-extensions-0.8.tar.gz has changed
Binary file virtualenv/res/src/django-haystack-v1.2.7.tar.gz has changed
Binary file virtualenv/res/src/django-haystack-v2.0.0.tar.gz has changed
Binary file virtualenv/res/src/fabric-1.4.2.tar.gz has changed
Binary file virtualenv/res/src/httplib2-0.7.4.tar.gz has changed
Binary file virtualenv/res/src/isodate-0.4.8.tar.gz has changed
Binary file virtualenv/res/src/lucene-3.0.2-py2.6-win32.egg has changed
Binary file virtualenv/res/src/lxml-2.3.4.tar.bz2 has changed
Binary file virtualenv/res/src/mercurial-2.2.3.tar.gz has changed
Binary file virtualenv/res/src/psycopg2-2.4.5.tar.gz has changed
Binary file virtualenv/res/src/psycopg2-2.4.tar.gz has changed
Binary file virtualenv/res/src/psycopg2-2.5.3.tar.gz has changed
Binary file virtualenv/res/src/pycrypto-2.6.tar.gz has changed
Binary file virtualenv/res/src/south-0.7.5.tar.gz has changed
Binary file virtualenv/res/src/ssh-1.7.14.tar.gz has changed
Binary file virtualenv/res/src/whoosh-2.5.tar.gz has changed
--- a/virtualenv/web/res/res_create_env.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/virtualenv/web/res/res_create_env.py	Tue Jun 17 10:32:57 2014 +0200
@@ -1,55 +1,37 @@
-from lib_create_env import (lib_generate_install_methods, install_pylucene, 
-    install_psycopg2, install_pystemmer, install_libyaml)
 import platform
 
+from lib_create_env import lib_generate_install_methods
 
 system_str = platform.system()
 
-if system_str == 'Windows':
-    INSTALLS = [
-    ('JCC','easy_install',None,None),
-    ('PSYCOPG2',install_psycopg2,None,None),
-    ('PYLUCENE','easy_install',None,None),
-    ('PYYAML','easy_install',None,None),
-    ('PYSTEMMER',install_pystemmer,None,None),
-    ]
-else:
-    INSTALLS = [
-    #('PYLUCENE',install_pylucene,None,None),
-    ('PSYCOPG2', 'pip', None, None),
-#    ('LIBYAML', install_libyaml, None, None)
-    ('PYYAML', 'pip', None, None),
-    ]
-
-if system_str == 'Linux':
-    INSTALLS.extend([
-    ('DISTRIBUTE', 'pip', None, None),
-    ])
+INSTALLS = [ #(key,method, option_str, dict_extra_env)
+    'LXML',
+    'PSYCOPG2',
+    #'PIL', 
+    'DJANGO',
+    'DJANGO-EXTENSIONS',
+    'SOUTH',
+    'HTTPLIB2',
+    'HAYSTACK',
+    'WHOOSH',
+    'WIKITOOLS',
+    'ISODATE',
+    'RDFLIB',
+    'SPARQLWRAPPER',
+    'PYYAML',
+    'REQUESTS',
+    'PYELASTICSEARCH',
+]
 
-INSTALLS.extend([ #(key,method, option_str, dict_extra_env)
-    #('PIL', 'easy_install', None, None), 
-    ('DJANGO','pip', None, None),
-    ('DJANGO-EXTENSIONS', 'pip', None, None),
-    ('HTTPLIB2', 'pip', None, None),
-    ('SOUTH', 'pip', None, None),
-    ('WHOOSH', 'pip', None, None),
-    ('HAYSTACK', 'pip', None, None),
-    ('WIKITOOLS', 'pip', None, None),
-    ('SPARQLWRAPPER', 'pip', None, None),
-    ('REQUESTS', 'pip', None, None),
-    ('PYELASTICSEARCH', 'pip', None, None),
-])
+if system_str == 'Windows':
+    INSTALLS.append('PYSTEMMER')
 
-if system_str == "Darwin":
-    INSTALLS.extend([
-    #('LXML', 'easy_install', None, {'STATIC_DEPS': 'true', 'LIBXML2_VERSION': '2.7.8', 'LIBXSLT_VERSION': '1.1.26', 'LIBICONV_VERSION': '1.13.1'}),
-    ('LXML', 'easy_install', None, {'STATIC_DEPS': 'true', 'LIBXML2_VERSION': '2.9.1', 'LIBXSLT_VERSION': '1.1.28', 'LIBICONV_VERSION': '1.14'}),
-    ])
-else:
-    INSTALLS.extend([
-    ('LXML', 'easy_install', None, None),
-    ])
+if system_str == "Linux":
+    INSTALLS.insert(2, 'DISTRIBUTE')
 
+OPTIONS_TO_ADD = ['clear', 'type_install=local', 'unzip_setuptools']
+if system_str != 'Linux':
+    OPTIONS_TO_ADD.append('use_distribute')
 
 def generate_install_methods(path_locations, src_base, Logger, call_subprocess):    
-    return lib_generate_install_methods(path_locations, src_base, Logger, call_subprocess, INSTALLS)
+    return lib_generate_install_methods(path_locations, src_base, Logger, call_subprocess, INSTALLS, OPTIONS_TO_ADD)
--- a/virtualenv/web/virtualenv.py	Mon Jun 16 17:37:36 2014 +0200
+++ b/virtualenv/web/virtualenv.py	Tue Jun 17 10:32:57 2014 +0200
@@ -4,13 +4,11 @@
 
 # If you change the version here, change it in setup.py
 # and docs/conf.py as well.
-__version__ = "1.9.1"  # following best practices
-virtualenv_version = __version__  # legacy, again
+virtualenv_version = "1.7.1.2"
 
 import base64
 import sys
 import os
-import codecs
 import optparse
 import re
 import shutil
@@ -18,17 +16,19 @@
 import tempfile
 import zlib
 import errno
-import glob
 import distutils.sysconfig
 from distutils.util import strtobool
-import struct
-import subprocess
 
-if sys.version_info < (2, 5):
-    print('ERROR: %s' % sys.exc_info()[1])
-    print('ERROR: this script requires Python 2.5 or greater.')
-    sys.exit(101)
-
+try:
+    import subprocess
+except ImportError:
+    if sys.version_info <= (2, 3):
+        print('ERROR: %s' % sys.exc_info()[1])
+        print('ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.')
+        print('If you copy subprocess.py from a newer version of Python this script will probably work')
+        sys.exit(101)
+    else:
+        raise
 try:
     set
 except NameError:
@@ -48,13 +48,12 @@
 
 is_jython = sys.platform.startswith('java')
 is_pypy = hasattr(sys, 'pypy_version_info')
-is_win = (sys.platform == 'win32')
-is_cygwin = (sys.platform == 'cygwin')
-is_darwin = (sys.platform == 'darwin')
+is_win  = (sys.platform == 'win32')
 abiflags = getattr(sys, 'abiflags', '')
 
 user_dir = os.path.expanduser('~')
-if is_win:
+if sys.platform == 'win32':
+    user_dir = os.environ.get('APPDATA', user_dir)  # Use %APPDATA% for roaming
     default_storage_dir = os.path.join(user_dir, 'virtualenv')
 else:
     default_storage_dir = os.path.join(user_dir, '.virtualenv')
@@ -90,15 +89,10 @@
     REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
                              '_weakrefset', 'copyreg', 'tempfile', 'random',
                              '__future__', 'collections', 'keyword', 'tarfile',
-                             'shutil', 'struct', 'copy', 'tokenize', 'token',
-                             'functools', 'heapq', 'bisect', 'weakref',
-                             'reprlib'])
+                             'shutil', 'struct', 'copy'])
     if minver >= 2:
         REQUIRED_FILES[-1] = 'config-%s' % majver
     if minver == 3:
-        import sysconfig
-        platdir = sysconfig.get_config_var('PLATDIR')
-        REQUIRED_FILES.append(platdir)
         # The whole list of 3.3 modules is reproduced below - the current
         # uncommented ones are required for 3.3 as of now, but more may be
         # added as 3.3 development continues.
@@ -112,7 +106,7 @@
             "base64",
             #"bdb",
             #"binhex",
-            #"bisect",
+            "bisect",
             #"calendar",
             #"cgi",
             #"cgitb",
@@ -152,15 +146,14 @@
             #"glob",
             #"gzip",
             "hashlib",
-            #"heapq",
+            "heapq",
             "hmac",
             #"html",
             #"http",
             #"idlelib",
             #"imaplib",
             #"imghdr",
-            "imp",
-            "importlib",
+            #"importlib",
             #"inspect",
             #"json",
             #"lib2to3",
@@ -200,7 +193,7 @@
             #"_pyio",
             #"queue",
             #"quopri",
-            #"reprlib",
+            "reprlib",
             "rlcompleter",
             #"runpy",
             #"sched",
@@ -242,7 +235,7 @@
             #"uuid",
             #"uu",
             #"wave",
-            #"weakref",
+            "weakref",
             #"webbrowser",
             #"wsgiref",
             #"xdrlib",
@@ -287,7 +280,7 @@
     def warn(self, msg, *args, **kw):
         self.log(self.WARN, msg, *args, **kw)
     def error(self, msg, *args, **kw):
-        self.log(self.ERROR, msg, *args, **kw)
+        self.log(self.WARN, msg, *args, **kw)
     def fatal(self, msg, *args, **kw):
         self.log(self.FATAL, msg, *args, **kw)
     def log(self, level, msg, *args, **kw):
@@ -450,7 +443,7 @@
         f = open(dest, 'rb')
         c = f.read()
         f.close()
-        if c != content.encode("utf-8"):
+        if c != content:
             if not overwrite:
                 logger.notify('File %s exists with different content; not overwriting', dest)
                 return
@@ -477,10 +470,9 @@
 
 def _find_file(filename, dirs):
     for dir in reversed(dirs):
-        files = glob.glob(os.path.join(dir, filename))
-        if files and os.path.isfile(files[0]):
-            return True, files[0]
-    return False, filename
+        if os.path.exists(join(dir, filename)):
+            return join(dir, filename)
+    return filename
 
 def _install_req(py_executable, unzip=False, distribute=False,
                  search_dirs=None, never_download=False):
@@ -489,29 +481,21 @@
         search_dirs = file_search_dirs()
 
     if not distribute:
-        egg_path = 'setuptools-*-py%s.egg' % sys.version[:3]
-        found, egg_path = _find_file(egg_path, search_dirs)
+        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
         project_name = 'setuptools'
         bootstrap_script = EZ_SETUP_PY
-        tgz_path = None
+        source = None
     else:
-        # Look for a distribute egg (these are not distributed by default,
-        # but can be made available by the user)
-        egg_path = 'distribute-*-py%s.egg' % sys.version[:3]
-        found, egg_path = _find_file(egg_path, search_dirs)
+        setup_fn = None
+        source = 'distribute-0.6.24.tar.gz'
         project_name = 'distribute'
-        if found:
-            tgz_path = None
-            bootstrap_script = DISTRIBUTE_FROM_EGG_PY
-        else:
-            # Fall back to sdist
-            # NB: egg_path is not None iff tgz_path is None
-            # iff bootstrap_script is a generic setup script accepting
-            # the standard arguments.
-            egg_path = None
-            tgz_path = 'distribute-*.tar.gz'
-            found, tgz_path = _find_file(tgz_path, search_dirs)
-            bootstrap_script = DISTRIBUTE_SETUP_PY
+        bootstrap_script = DISTRIBUTE_SETUP_PY
+
+    if setup_fn is not None:
+        setup_fn = _find_file(setup_fn, search_dirs)
+
+    if source is not None:
+        source = _find_file(source, search_dirs)
 
     if is_jython and os._name == 'nt':
         # Jython's .bat sys.executable can't handle a command line
@@ -522,43 +506,43 @@
         cmd = [py_executable, ez_setup]
     else:
         cmd = [py_executable, '-c', bootstrap_script]
-    if unzip and egg_path:
+    if unzip:
         cmd.append('--always-unzip')
     env = {}
-    remove_from_env = ['__PYVENV_LAUNCHER__']
-    if logger.stdout_level_matches(logger.DEBUG) and egg_path:
+    remove_from_env = []
+    if logger.stdout_level_matches(logger.DEBUG):
         cmd.append('-v')
 
     old_chdir = os.getcwd()
-    if egg_path is not None and os.path.exists(egg_path):
-        logger.info('Using existing %s egg: %s' % (project_name, egg_path))
-        cmd.append(egg_path)
+    if setup_fn is not None and os.path.exists(setup_fn):
+        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
+        cmd.append(setup_fn)
         if os.environ.get('PYTHONPATH'):
-            env['PYTHONPATH'] = egg_path + os.path.pathsep + os.environ['PYTHONPATH']
+            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
         else:
-            env['PYTHONPATH'] = egg_path
-    elif tgz_path is not None and os.path.exists(tgz_path):
-        # Found a tgz source dist, let's chdir
-        logger.info('Using existing %s egg: %s' % (project_name, tgz_path))
-        os.chdir(os.path.dirname(tgz_path))
-        # in this case, we want to be sure that PYTHONPATH is unset (not
-        # just empty, really unset), else CPython tries to import the
-        # site.py that it's in virtualenv_support
-        remove_from_env.append('PYTHONPATH')
-    elif never_download:
-        logger.fatal("Can't find any local distributions of %s to install "
-                     "and --never-download is set.  Either re-run virtualenv "
-                     "without the --never-download option, or place a %s "
-                     "distribution (%s) in one of these "
-                     "locations: %r" % (project_name, project_name,
-                                        egg_path or tgz_path,
-                                        search_dirs))
-        sys.exit(1)
-    elif egg_path:
-        logger.info('No %s egg found; downloading' % project_name)
+            env['PYTHONPATH'] = setup_fn
+    else:
+        # the source is found, let's chdir
+        if source is not None and os.path.exists(source):
+            logger.info('Using existing %s egg: %s' % (project_name, source))
+            os.chdir(os.path.dirname(source))
+            # in this case, we want to be sure that PYTHONPATH is unset (not
+            # just empty, really unset), else CPython tries to import the
+            # site.py that it's in virtualenv_support
+            remove_from_env.append('PYTHONPATH')
+        else:
+            if never_download:
+                logger.fatal("Can't find any local distributions of %s to install "
+                             "and --never-download is set.  Either re-run virtualenv "
+                             "without the --never-download option, or place a %s "
+                             "distribution (%s) in one of these "
+                             "locations: %r" % (project_name, project_name,
+                                                setup_fn or source,
+                                                search_dirs))
+                sys.exit(1)
+
+            logger.info('No %s egg found; downloading' % project_name)
         cmd.extend(['--always-copy', '-U', project_name])
-    else:
-        logger.info('No %s tgz found; downloading' % project_name)
     logger.start_progress('Installing %s...' % project_name)
     logger.indent += 2
     cwd = None
@@ -570,11 +554,11 @@
 
     if not os.access(os.getcwd(), os.W_OK):
         cwd = tempfile.mkdtemp()
-        if tgz_path is not None and os.path.exists(tgz_path):
+        if source is not None and os.path.exists(source):
             # the current working dir is hostile, let's copy the
             # tarball to a temp dir
-            target = os.path.join(cwd, os.path.split(tgz_path)[-1])
-            shutil.copy(tgz_path, target)
+            target = os.path.join(cwd, os.path.split(source)[-1])
+            shutil.copy(source, target)
     try:
         call_subprocess(cmd, show_stdout=False,
                         filter_stdout=_filter_ez_setup,
@@ -584,8 +568,6 @@
     finally:
         logger.indent -= 2
         logger.end_progress()
-        if cwd is not None:
-            shutil.rmtree(cwd)
         if os.getcwd() != old_chdir:
             os.chdir(old_chdir)
         if is_jython and os._name == 'nt':
@@ -632,20 +614,11 @@
     else:
         filename = filenames[-1]
     easy_install_script = 'easy_install'
-    if is_win:
+    if sys.platform == 'win32':
         easy_install_script = 'easy_install-script.py'
-    # There's two subtle issues here when invoking easy_install.
-    # 1. On unix-like systems the easy_install script can *only* be executed
-    #    directly if its full filesystem path is no longer than 78 characters.
-    # 2. A work around to [1] is to use the `python path/to/easy_install foo`
-    #    pattern, but that breaks if the path contains non-ASCII characters, as
-    #    you can't put the file encoding declaration before the shebang line.
-    # The solution is to use Python's -x flag to skip the first line of the
-    # script (and any ASCII decoding errors that may have occurred in that line)
-    cmd = [py_executable, '-x', join(os.path.dirname(py_executable), easy_install_script), filename]
-    # jython and pypy don't yet support -x
-    if is_jython or is_pypy:
-        cmd.remove('-x')
+    cmd = [join(os.path.dirname(py_executable), easy_install_script), filename]
+    if sys.platform == 'win32':
+        cmd.insert(0, py_executable)
     if filename == 'pip':
         if never_download:
             logger.fatal("Can't find any local distributions of pip to install "
@@ -745,9 +718,7 @@
                     val = val.split()
                 else:
                     option.nargs = 1
-                if option.action == 'store_false':
-                    val = not strtobool(val)
-                elif option.action in ('store_true', 'count'):
+                if option.action in ('store_true', 'store_false', 'count'):
                     val = strtobool(val)
                 try:
                     val = option.convert_value(key, val)
@@ -783,7 +754,7 @@
             # Old, pre-Optik 1.5 behaviour.
             return optparse.Values(self.defaults)
 
-        defaults = self.update_defaults(self.defaults.copy())  # ours
+        defaults = self.update_defaults(self.defaults.copy()) # ours
         for option in self._get_all_options():
             default = defaults.get(option.dest)
             if isinstance(default, basestring):
@@ -826,13 +797,12 @@
         action='store_true',
         help="Clear out the non-root install and start from scratch")
 
-    parser.set_defaults(system_site_packages=False)
     parser.add_option(
         '--no-site-packages',
-        dest='system_site_packages',
-        action='store_false',
+        dest='no_site_packages',
+        action='store_true',
         help="Don't give access to the global site-packages dir to the "
-             "virtual environment (default)")
+             "virtual environment")
 
     parser.add_option(
         '--system-site-packages',
@@ -855,35 +825,12 @@
         'This fixes up scripts and makes all .pth files relative')
 
     parser.add_option(
-        '--distribute', '--use-distribute',  # the second option is for legacy reasons here. Hi Kenneth!
+        '--distribute',
         dest='use_distribute',
         action='store_true',
         help='Use Distribute instead of Setuptools. Set environ variable '
         'VIRTUALENV_DISTRIBUTE to make it the default ')
 
-    parser.add_option(
-        '--no-setuptools',
-        dest='no_setuptools',
-        action='store_true',
-        help='Do not install distribute/setuptools (or pip) '
-        'in the new virtualenv.')
-
-    parser.add_option(
-        '--no-pip',
-        dest='no_pip',
-        action='store_true',
-        help='Do not install pip in the new virtualenv.')
-
-    parser.add_option(
-        '--setuptools',
-        dest='use_distribute',
-        action='store_false',
-        help='Use Setuptools instead of Distribute.  Set environ variable '
-        'VIRTUALENV_SETUPTOOLS to make it the default ')
-
-    # Set this to True to use distribute by default, even in Python 2.
-    parser.set_defaults(use_distribute=False)
-
     default_search_dirs = file_search_dirs()
     parser.add_option(
         '--extra-search-dir',
@@ -901,7 +848,7 @@
         "if local distributions of setuptools/distribute/pip are not present.")
 
     parser.add_option(
-        '--prompt',
+        '--prompt=',
         dest='prompt',
         help='Provides an alternative prompt prefix for this environment')
 
@@ -916,7 +863,7 @@
         adjust_options(options, args)
 
     verbosity = options.verbose - options.quiet
-    logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
+    logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
 
     if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
         env = os.environ.copy()
@@ -967,6 +914,10 @@
         make_environment_relocatable(home_dir)
         return
 
+    if options.no_site_packages:
+        logger.warn('The --no-site-packages flag is deprecated; it is now '
+                    'the default behavior.')
+
     create_environment(home_dir,
                        site_packages=options.system_site_packages,
                        clear=options.clear,
@@ -974,9 +925,7 @@
                        use_distribute=options.use_distribute,
                        prompt=options.prompt,
                        search_dirs=options.search_dirs,
-                       never_download=options.never_download,
-                       no_setuptools=options.no_setuptools,
-                       no_pip=options.no_pip)
+                       never_download=options.never_download)
     if 'after_install' in globals():
         after_install(options, home_dir)
 
@@ -1063,8 +1012,7 @@
 
 def create_environment(home_dir, site_packages=False, clear=False,
                        unzip_setuptools=False, use_distribute=False,
-                       prompt=None, search_dirs=None, never_download=False,
-                       no_setuptools=False, no_pip=False):
+                       prompt=None, search_dirs=None, never_download=False):
     """
     Creates a new environment in ``home_dir``.
 
@@ -1082,52 +1030,42 @@
 
     install_distutils(home_dir)
 
-    if not no_setuptools:
-        if use_distribute:
-            install_distribute(py_executable, unzip=unzip_setuptools,
-                               search_dirs=search_dirs, never_download=never_download)
-        else:
-            install_setuptools(py_executable, unzip=unzip_setuptools,
-                               search_dirs=search_dirs, never_download=never_download)
+    # use_distribute also is True if VIRTUALENV_DISTRIBUTE env var is set
+    # we also check VIRTUALENV_USE_DISTRIBUTE for backwards compatibility
+    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
+        install_distribute(py_executable, unzip=unzip_setuptools,
+                           search_dirs=search_dirs, never_download=never_download)
+    else:
+        install_setuptools(py_executable, unzip=unzip_setuptools,
+                           search_dirs=search_dirs, never_download=never_download)
 
-        if not no_pip:
-            install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
+    install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
 
     install_activate(home_dir, bin_dir, prompt)
 
-def is_executable_file(fpath):
-    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
-
 def path_locations(home_dir):
     """Return the path locations for the environment (where libraries are,
     where scripts go, etc)"""
     # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
     # prefix arg is broken: http://bugs.python.org/issue3386
-    if is_win:
+    if sys.platform == 'win32':
         # Windows has lots of problems with executables with spaces in
         # the name; this function will remove them (using the ~1
         # format):
         mkdir(home_dir)
         if ' ' in home_dir:
-            import ctypes
-            GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
-            size = max(len(home_dir)+1, 256)
-            buf = ctypes.create_unicode_buffer(size)
             try:
-                u = unicode
-            except NameError:
-                u = str
-            ret = GetShortPathName(u(home_dir), buf, size)
-            if not ret:
+                import win32api
+            except ImportError:
                 print('Error: the path "%s" has a space in it' % home_dir)
-                print('We could not determine the short pathname for it.')
-                print('Exiting.')
+                print('To handle these kinds of paths, the win32api module must be installed:')
+                print('  http://sourceforge.net/projects/pywin32/')
                 sys.exit(3)
-            home_dir = str(buf.value)
+            home_dir = win32api.GetShortPathName(home_dir)
         lib_dir = join(home_dir, 'Lib')
         inc_dir = join(home_dir, 'Include')
         bin_dir = join(home_dir, 'Scripts')
-    if is_jython:
+    elif is_jython:
         lib_dir = join(home_dir, 'Lib')
         inc_dir = join(home_dir, 'Include')
         bin_dir = join(home_dir, 'bin')
@@ -1135,19 +1073,9 @@
         lib_dir = home_dir
         inc_dir = join(home_dir, 'include')
         bin_dir = join(home_dir, 'bin')
-    elif not is_win:
+    else:
         lib_dir = join(home_dir, 'lib', py_version)
-        multiarch_exec = '/usr/bin/multiarch-platform'
-        if is_executable_file(multiarch_exec):
-            # In Mageia (2) and Mandriva distros the include dir must be like:
-            # virtualenv/include/multiarch-x86_64-linux/python2.7
-            # instead of being virtualenv/include/python2.7
-            p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-            stdout, stderr = p.communicate()
-            # stdout.strip is needed to remove newline character
-            inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
-        else:
-            inc_dir = join(home_dir, 'include', py_version + abiflags)
+        inc_dir = join(home_dir, 'include', py_version + abiflags)
         bin_dir = join(home_dir, 'bin')
     return home_dir, lib_dir, inc_dir, bin_dir
 
@@ -1155,31 +1083,21 @@
 def change_prefix(filename, dst_prefix):
     prefixes = [sys.prefix]
 
-    if is_darwin:
+    if sys.platform == "darwin":
         prefixes.extend((
             os.path.join("/Library/Python", sys.version[:3], "site-packages"),
             os.path.join(sys.prefix, "Extras", "lib", "python"),
-            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
-            # Python 2.6 no-frameworks
-            os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"),
-            # System Python 2.7 on OSX Mountain Lion
-            os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages")))
+            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages")))
 
     if hasattr(sys, 'real_prefix'):
         prefixes.append(sys.real_prefix)
-    if hasattr(sys, 'base_prefix'):
-        prefixes.append(sys.base_prefix)
-    prefixes = list(map(os.path.expanduser, prefixes))
     prefixes = list(map(os.path.abspath, prefixes))
-    # Check longer prefixes first so we don't split in the middle of a filename
-    prefixes = sorted(prefixes, key=len, reverse=True)
     filename = os.path.abspath(filename)
     for src_prefix in prefixes:
         if filename.startswith(src_prefix):
             _, relpath = filename.split(src_prefix, 1)
-            if src_prefix != os.sep: # sys.prefix == "/"
-                assert relpath[0] == os.sep
-                relpath = relpath[1:]
+            assert relpath[0] == os.sep
+            relpath = relpath[1:]
             return join(dst_prefix, relpath)
     assert False, "Filename %s does not start with any of these prefixes: %s" % \
         (filename, prefixes)
@@ -1207,12 +1125,7 @@
             else:
                 if f is not None:
                     f.close()
-                # special-case custom readline.so on OS X, but not for pypy:
-                if modname == 'readline' and sys.platform == 'darwin' and not (
-                        is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))):
-                    dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
-                else:
-                    dst_filename = change_prefix(filename, dst_prefix)
+                dst_filename = change_prefix(filename, dst_prefix)
                 copyfile(filename, dst_filename)
                 if filename.endswith('.pyc'):
                     pyfile = filename[:-1]
@@ -1221,17 +1134,6 @@
     finally:
         sys.path = _prev_sys_path
 
-
-def subst_path(prefix_path, prefix, home_dir):
-    prefix_path = os.path.normpath(prefix_path)
-    prefix = os.path.normpath(prefix)
-    home_dir = os.path.normpath(home_dir)
-    if not prefix_path.startswith(prefix):
-        logger.warn('Path not in prefix %r %r', prefix_path, prefix)
-        return
-    return prefix_path.replace(prefix, home_dir, 1)
-
-
 def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
     """Install just the base environment, no distutils patches etc"""
     if sys.executable.startswith(bin_dir):
@@ -1247,17 +1149,14 @@
     if hasattr(sys, 'real_prefix'):
         logger.notify('Using real prefix %r' % sys.real_prefix)
         prefix = sys.real_prefix
-    elif hasattr(sys, 'base_prefix'):
-        logger.notify('Using base prefix %r' % sys.base_prefix)
-        prefix = sys.base_prefix
     else:
         prefix = sys.prefix
     mkdir(lib_dir)
     fix_lib64(lib_dir)
     stdlib_dirs = [os.path.dirname(os.__file__)]
-    if is_win:
+    if sys.platform == 'win32':
         stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
-    elif is_darwin:
+    elif sys.platform == 'darwin':
         stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
     if hasattr(os, 'symlink'):
         logger.info('Symlinking Python bootstrap modules')
@@ -1291,6 +1190,10 @@
     site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
     if not site_packages:
         writefile(site_packages_filename, '')
+    else:
+        if os.path.exists(site_packages_filename):
+            logger.info('Deleting %s' % site_packages_filename)
+            os.unlink(site_packages_filename)
 
     if is_pypy or is_win:
         stdinc_dir = join(prefix, 'include')
@@ -1301,24 +1204,9 @@
     else:
         logger.debug('No include dir %s' % stdinc_dir)
 
-    platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
-    if platinc_dir != stdinc_dir:
-        platinc_dest = distutils.sysconfig.get_python_inc(
-            plat_specific=1, prefix=home_dir)
-        if platinc_dir == platinc_dest:
-            # Do platinc_dest manually due to a CPython bug;
-            # not http://bugs.python.org/issue3386 but a close cousin
-            platinc_dest = subst_path(platinc_dir, prefix, home_dir)
-        if platinc_dest:
-            # PyPy's stdinc_dir and prefix are relative to the original binary
-            # (traversing virtualenvs), whereas the platinc_dir is relative to
-            # the inner virtualenv and ignores the prefix argument.
-            # This seems more evolved than designed.
-            copyfile(platinc_dir, platinc_dest)
-
     # pypy never uses exec_prefix, just ignore it
     if sys.exec_prefix != prefix and not is_pypy:
-        if is_win:
+        if sys.platform == 'win32':
             exec_dir = join(sys.exec_prefix, 'lib')
         elif is_jython:
             exec_dir = join(sys.exec_prefix, 'Lib')
@@ -1344,10 +1232,6 @@
     mkdir(bin_dir)
     py_executable = join(bin_dir, os.path.basename(sys.executable))
     if 'Python.framework' in prefix:
-        # OS X framework builds cause validation to break
-        # https://github.com/pypa/virtualenv/issues/322
-        if os.environ.get('__PYVENV_LAUNCHER__'):
-          os.unsetenv('__PYVENV_LAUNCHER__')
         if re.search(r'/Python(?:-32|-64)*$', py_executable):
             # The name of the python executable is not quite what
             # we want, rename it.
@@ -1366,13 +1250,18 @@
         if os.path.exists(pyd_pth):
             logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth)
             os.unlink(pyd_pth)
-
+        
     if sys.executable != py_executable:
         ## FIXME: could I just hard link?
         executable = sys.executable
+        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
+            # Cygwin misreports sys.executable sometimes
+            executable += '.exe'
+            py_executable += '.exe'
+            logger.info('Executable actually exists in %s' % executable)
         shutil.copyfile(executable, py_executable)
         make_exe(py_executable)
-        if is_win or is_cygwin:
+        if sys.platform == 'win32' or sys.platform == 'cygwin':
             pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
             if os.path.exists(pythonw):
                 logger.info('Also created pythonw.exe')
@@ -1406,17 +1295,9 @@
         if is_pypy:
             # make a symlink python --> pypy-c
             python_executable = os.path.join(os.path.dirname(py_executable), 'python')
-            if sys.platform in ('win32', 'cygwin'):
-                python_executable += '.exe'
             logger.info('Also created executable %s' % python_executable)
             copyfile(py_executable, python_executable)
 
-            if is_win:
-                for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll':
-                    src = join(prefix, name)
-                    if os.path.exists(src):
-                        copyfile(src, join(bin_dir, name))
-
     if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
         secondary_exe = os.path.join(os.path.dirname(py_executable),
                                      expected_exe)
@@ -1459,53 +1340,49 @@
 
         # And then change the install_name of the copied python executable
         try:
-            mach_o_change(py_executable,
-                          os.path.join(prefix, 'Python'),
-                          '@executable_path/../.Python')
+            call_subprocess(
+                ["install_name_tool", "-change",
+                 os.path.join(prefix, 'Python'),
+                 '@executable_path/../.Python',
+                 py_executable])
         except:
-            e = sys.exc_info()[1]
-            logger.warn("Could not call mach_o_change: %s. "
-                        "Trying to call install_name_tool instead." % e)
-            try:
-                call_subprocess(
-                    ["install_name_tool", "-change",
-                     os.path.join(prefix, 'Python'),
-                     '@executable_path/../.Python',
-                     py_executable])
-            except:
-                logger.fatal("Could not call install_name_tool -- you must "
-                             "have Apple's development tools installed")
-                raise
+            logger.fatal(
+                "Could not call install_name_tool -- you must have Apple's development tools installed")
+            raise
 
-    if not is_win:
-        # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
-        py_exe_version_major = 'python%s' % sys.version_info[0]
-        py_exe_version_major_minor = 'python%s.%s' % (
+        # Some tools depend on pythonX.Y being present
+        py_executable_version = '%s.%s' % (
             sys.version_info[0], sys.version_info[1])
-        py_exe_no_version = 'python'
-        required_symlinks = [ py_exe_no_version, py_exe_version_major,
-                         py_exe_version_major_minor ]
-
-        py_executable_base = os.path.basename(py_executable)
+        if not py_executable.endswith(py_executable_version):
+            # symlinking pythonX.Y > python
+            pth = py_executable + '%s.%s' % (
+                    sys.version_info[0], sys.version_info[1])
+            if os.path.exists(pth):
+                os.unlink(pth)
+            os.symlink('python', pth)
+        else:
+            # reverse symlinking python -> pythonX.Y (with --python)
+            pth = join(bin_dir, 'python')
+            if os.path.exists(pth):
+                os.unlink(pth)
+            os.symlink(os.path.basename(py_executable), pth)
 
-        if py_executable_base in required_symlinks:
-            # Don't try to symlink to yourself.
-            required_symlinks.remove(py_executable_base)
-
-        for pth in required_symlinks:
-            full_pth = join(bin_dir, pth)
-            if os.path.exists(full_pth):
-                os.unlink(full_pth)
-            os.symlink(py_executable_base, full_pth)
-
-    if is_win and ' ' in py_executable:
+    if sys.platform == 'win32' and ' ' in py_executable:
         # There's a bug with subprocess on Windows when using a first
         # argument that has a space in it.  Instead we have to quote
         # the value:
         py_executable = '"%s"' % py_executable
-    # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
-    cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
-        'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
+    cmd = [py_executable, '-c', """
+import sys
+prefix = sys.prefix
+if sys.version_info[0] == 3:
+    prefix = prefix.encode('utf8')
+if hasattr(sys.stdout, 'detach'):
+    sys.stdout = sys.stdout.detach()
+elif hasattr(sys.stdout, 'buffer'):
+    sys.stdout = sys.stdout.buffer
+sys.stdout.write(prefix)
+"""]
     logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
     try:
         proc = subprocess.Popen(cmd,
@@ -1517,7 +1394,7 @@
             logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
             sys.exit(100)
         else:
-            raise e
+          raise e
 
     proc_stdout = proc_stdout.strip().decode("utf-8")
     proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
@@ -1532,7 +1409,7 @@
             % (proc_stdout, norm_home_dir))
         logger.fatal(
             'ERROR: virtualenv is not compatible with this system or executable')
-        if is_win:
+        if sys.platform == 'win32':
             logger.fatal(
                 'Note: some Windows users have reported this error when they '
                 'installed Python for "Only this user" or have multiple '
@@ -1551,17 +1428,11 @@
 
     fix_local_scheme(home_dir)
 
-    if site_packages:
-        if os.path.exists(site_packages_filename):
-            logger.info('Deleting %s' % site_packages_filename)
-            os.unlink(site_packages_filename)
-
     return py_executable
 
-
 def install_activate(home_dir, bin_dir, prompt=None):
     home_dir = os.path.abspath(home_dir)
-    if is_win or is_jython and os._name == 'nt':
+    if sys.platform == 'win32' or is_jython and os._name == 'nt':
         files = {
             'activate.bat': ACTIVATE_BAT,
             'deactivate.bat': DEACTIVATE_BAT,
@@ -1573,7 +1444,7 @@
         home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
 
         # Run-time conditional enables (basic) Cygwin compatibility
-        home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" %
+        home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" % 
                        (home_dir, home_dir_msys))
         files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
 
@@ -1642,14 +1513,9 @@
         assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
             "Unexpected python lib dir: %r" % lib_dir)
         lib_parent = os.path.dirname(lib_dir)
-        top_level = os.path.dirname(lib_parent)
-        lib_dir = os.path.join(top_level, 'lib')
-        lib64_link = os.path.join(top_level, 'lib64')
         assert os.path.basename(lib_parent) == 'lib', (
             "Unexpected parent dir: %r" % lib_parent)
-        if os.path.lexists(lib64_link):
-            return
-        os.symlink('lib', lib64_link)
+        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
 
 def resolve_interpreter(exe):
     """
@@ -1699,7 +1565,8 @@
     shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
     # This is what we'll put:
     new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
-    if is_win:
+    activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
+    if sys.platform == 'win32':
         bin_suffix = 'Scripts'
     else:
         bin_suffix = 'bin'
@@ -1733,26 +1600,11 @@
                             % (filename, shebang))
             continue
         logger.notify('Making script %s relative' % filename)
-        script = relative_script([new_shebang] + lines[1:])
+        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
         f = open(filename, 'wb')
-        f.write('\n'.join(script).encode('utf-8'))
+        f.write('\n'.join(lines).encode('utf-8'))
         f.close()
 
-def relative_script(lines):
-    "Return a script that'll work in a relocatable environment."
-    activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
-    # Find the last future statement in the script. If we insert the activation
-    # line before a future statement, Python will raise a SyntaxError.
-    activate_at = None
-    for idx, line in reversed(list(enumerate(lines))):
-        if line.split()[:3] == ['from', '__future__', 'import']:
-            activate_at = idx + 1
-            break
-    if activate_at is None:
-        # Activate after the shebang.
-        activate_at = 1
-    return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
-
 def fixup_pth_and_egg_link(home_dir, sys_path=None):
     """Makes .pth and .egg-link files use relative paths"""
     home_dir = os.path.normcase(os.path.abspath(home_dir))
@@ -1806,7 +1658,7 @@
 
 def fixup_egg_link(filename):
     f = open(filename)
-    link = f.readline().strip()
+    link = f.read().strip()
     f.close()
     if os.path.abspath(link) != link:
         logger.debug('Link in %s already relative' % filename)
@@ -1890,15 +1742,15 @@
         This example immediately installs a package, and runs a setup
         script from that package.
 
-    If you provide something like ``python_version='2.5'`` then the
-    script will start with ``#!/usr/bin/env python2.5`` instead of
+    If you provide something like ``python_version='2.4'`` then the
+    script will start with ``#!/usr/bin/env python2.4`` instead of
     ``#!/usr/bin/env python``.  You can use this when the script must
     be run with a particular Python version.
     """
     filename = __file__
     if filename.endswith('.pyc'):
         filename = filename[:-1]
-    f = codecs.open(filename, 'r', encoding='utf-8')
+    f = open(filename, 'rb')
     content = f.read()
     f.close()
     py_exe = 'python%s' % python_version
@@ -1915,384 +1767,365 @@
 
 ##file site.py
 SITE_PY = convert("""
-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
-UM3ckC/Q8aP8VLy+mjYY5MxOtAdgjULwf2RtvCc=
+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
+Q7wQmAIMcman2gOwRiH4P2ts6wE=
 """)
 
 ##file ez_setup.py
 EZ_SETUP_PY = convert("""
-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
-qL7+C1AkCcw=
-""")
-
-##file distribute_from_egg.py
-DISTRIBUTE_FROM_EGG_PY = convert("""
-eJw9j8tqAzEMRfcG/4MgmxQyptkGusonZBmGoGTUGYFfWPKE6dfXTkM3gqt7rh47OKP3NMF3SQFW
-LlrRU1zhybpAxoKBlIqcrNnBdRjQP3GTocYfzmNrrCPQPN9iwzpxSQfQhWBi0cL3qtRtYIG/4Mv0
-KApY5hooqrOGQ05FQTaxptF9Fnx16Rq0XofjaE1XGXVxHIWK7j8P8EY/rHndLqQ1a0pe3COFgHFy
-hLLdWkDbi/DeEpCjNb3u/zccT2Ob8gtnwVyI
+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
+BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
 """)
 
 ##file distribute_setup.py
 DISTRIBUTE_SETUP_PY = convert("""
-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
+eJztG2tz2zbyu34FTh4PqYSi7TT3GM+pM2nj9DzNJZnYaT8kHhoiIYk1X+XDsvrrb3cBkCAJyc61
+dzM3c7qrIxGLxWLfuwCP/lTs6k2eTabT6Xd5Xld1yQsWxfBvvGxqweKsqnmS8DoGoMnliu3yhm15
+VrM6Z00lWCXqpqjzPKkAFkdLVvDwjq+FU8lBv9h57JemqgEgTJpIsHoTV5NVnCB6+AFIeCpg1VKE
+dV7u2DauNyyuPcaziPEoogm4IMLWecHylVxJ4z8/n0wYfFZlnhrUBzTO4rTIyxqpDTpqCb7/yJ2N
+dliKXxsgi3FWFSKMV3HI7kVZATOQhm6qh98BKsq3WZLzaJLGZZmXHstL4hLPGE9qUWYceKqBuh17
+tGgIUFHOqpwtd6xqiiLZxdl6gpvmRVHmRRnj9LxAYRA/bm+HO7i99SeTa2QX8TekhRGjYGUD3yvc
+SljGBW1PSZeoLNYlj0x5+qgUE8W8vNLfql37tY5Tob+vspTX4aYdEmmBFLS/eUk/Wwk1dYwqI0eT
+fD2Z1OXuvJNiFaP2yeFPVxcfg6vL64uJeAgFkH5Jzy+QxXJKC8EW7F2eCQObJrtZAgtDUVVSVSKx
+YoFU/iBMI/cZL9fVTE7BD/4EZC5s1xcPImxqvkyEN2PPaaiFK4FfZWag90PgqEvY2GLBTid7iT4C
+RQfmg2hAihFbgRQkQeyF/80fSuQR+7XJa1AmfNykIquB9StYPgNd7MDgEWIqwNyBmBTJdwDmmxdO
+t6QmCxEK3OasP6bwOPA/MG4YHw8bbHOmx9XUYccIOIJTMMMhtenPHQXEOviiVqxuhtLJK78qOFid
+C98+BD+/urz22IBp7Jkps9cXb159ensd/HTx8ery/TtYb3rq/8V/8XLaDn36+BYfb+q6OD85KXZF
+7EtR+Xm5PlFOsDqpwFGF4iQ66fzSyXRydXH96cP1+/dvr4I3r368eD1YKDw7m05MoA8//hBcvnvz
+Hsen0y+Tf4qaR7zm85+kOzpnZ/7p5B340XPDhCft6HE1uWrSlINVsAf4TP6Rp2JeAIX0e/KqAcpL
+8/tcpDxO5JO3cSiySoG+FtKBEF58AASBBPftaDKZkBorX+OCJ1jCvzNtA+IBYk5IyknuXQ7TYJ0W
+4CJhy9qb+OldhN/BU+M4uA1/y8vMdS46JKADx5XjqckSME+iYBsBIhD/WtThNlIYWi9BUGC7G5jj
+mlMJihMR0oX5eSGydhctTKD2obbYm+yHSV4JDC+dQa5zRSxuug0ELQD4E7l1IKrg9cb/BeAVYR4+
+TECbDFo/n97MxhuRWLqBjmHv8i3b5uWdyTENbVCphIZhaIzjsh1kr1vddmamO8nyuufAHB2xYTlH
+IXcGHqRb4Ap0FEI/4N+Cy2LbMoevUVNqXTGTE99YeIBFCIIW6HlZCi4atJ7xZX4v9KRVnAEemypI
+zZlpJV42MTwQ67UL/3laWeFLHiDr/q/T/wM6TTKkWJgxkKIF0XcthKHYCNsJQsq749Q+HZ//in+X
+6PtRbejRHH/Bn9JA9EQ1lDuQUU1rVymqJqn7ygNLSWBlg5rj4gGWrmi4W6XkMaSol+8pNXGd7/Mm
+iWgWcUraznqNtqKsIAKiVQ7rqnTYa7PaYMkroTdmPI5EwndqVWTlUA0UvNOFyflxNS92x5EP/0fe
+WRMJ+ByzjgoM6uoHRJxVDjpkeXh2M3s6e5RZAMHtXoyMe8/+99E6+OzhUqdXjzgcAqScDckHfyjK
+2j31WCd/lf326x4jyV/qqk8H6IDS7wWZhpT3oMZQO14MUqQBBxZGmmTlhtzBAlW8KS1MWJz92QPh
+BCt+JxbXZSNa75pyMvGqgcJsS8kz6ShfVnmChoq8mHRLGJoGIPiva3Jvy6tAckmgN3WKu3UAJkVZ
+W0VJLPI3zaMmERVWSl/a3TgdV4aAY0/c+2GIprdeH0Aq54ZXvK5LtwcIhhJERtC1JuE4W3HQnoXT
+UL8CHoIo59DVLi3EvrKmnSlz79/jLfYzr8cMX5Xp7rRjybeL6XO12sxC1nAXfXwqbf4+z1ZJHNb9
+pQVoiawdQvIm7gz8yVBwplaNeY/TIdRBRuJvSyh03RHE9Jo8O20rMnsORm/G/XZxDAUL1PooaH4P
+6TpVMl+y6RgftlJCnjk11pvK1AHzdoNtAuqvqLYAfCubDKOLzz4kAsRjxadbB5yleYmkhpiiaUJX
+cVnVHpgmoLFOdwDxTrscNv9k7MvxLfBfsi+Z+31TlrBKspOI2XE5A+Q9/y98rOIwcxirshRaXLsv
++mMiqSz2ARrIBiZn2PfngZ+4wSkYmamxk9/tK2a/xhqeFEP2WYxVr9tsBlZ9l9dv8iaLfrfRPkqm
+jcRRqnPIXQVhKXgtht4qwM2RBbZZFIarA1H698Ys+lgCl4pXygtDPfy6a/G15kpxtW0kgu0leUil
+C7U5FePjWnbuMqjkZVJ4q2i/ZdWGMrMltiPveRL3sGvLy5p0KUqwaE6m3HoFwoXtP0p6qWPS9iFB
+C2iKYLc9ftwy7HG44CPCjV5dZJEMm9ij5cw5cWY+u5U8ucUVe7k/+BdRCp1Ctv0uvYqIfLlH4mA7
+Xe2BOqxhnkXU6yw4BvqlWKG7wbZmWDc86TqutL8aK6na12L4jyQMvVhEQm1KqIKXFIUEtrlVv7lM
+sKyaGNZojZUGihe2ufX6twDVAVs/veTYxzJs/Rs6QCV92dQue7kqCpI9b7HI/I/fC2DpnhRcg6rs
+sgwRHexLtVYNax3kzRLt7Bx5/uo+j1GrC7TcqCWny3BGIb0tXlrrIR9fTT3cUt9lS6IUl9zR8BH7
+KHh0QrGVYYCB5AxIZ0swuTsPO+xbVEKMhtK1gCaHeVmCuyDrGyCD3ZJWa3uJ8ayjFgSvVVh/sCmH
+CUIZgj7waJBRSTYS0ZJZHptul9MRkEoLEFk3NvKZShKwliXFAAJ0iT6AB/yWcAeLmvBd55QkDHtJ
+yBKUjFUlCO66Au+1zB/cVZOF6M2UE6Rhc5zaqx579uxuOzuQFcvmf1efqOnaMF5rz3Ilnx9KmIew
+mDNDIW1LlpHa+ziXraRRm938FLyqRgPDlXxcBwQ9ft4u8gQcLSxg2j+vwGMXKl2wSHpCYtNNeMMB
+4Mn5/HDefhkq3dEa0RP9o9qslhnTfZhBVhFYkzo7pKn0pt4qRSeqAvQNLpqBB+4CPEBWdyH/Z4pt
+PLxrCvIWK5lYi0zuCCK7DkjkLcG3BQqH9giIeGZ6DeDGGHahl+44dAQ+DqftNPMsPa1XfQizXap2
+3WlDN+sDQmMp4OsJkE1ibAjIGRDFMp8zNwGGtnVswVK5Nc07eya4svkh0u2JIQZYz/Quxoj2TXio
+rNlmFZp2cUPeGzxWqEZ7lggysdWRGZ9ClHX8929f+8cVHmnh6aiPf0ad3Y+ITgY3DCS57ClKEjVO
+1eTF2hZ/urZRtQH9sCU2ze8hWQbTCMwOuVskPBQbUHahO9WDMB5X2Gscg/Wp/5TdQSDsNd8h8VJ7
+MObu168V1h09/4PpqL4QYDSC7aQA1eq02Vf/ujjXM/sxz7BjOMfiYOju9eIjb7kE6d+ZbFn1y6OO
+A12HlFJ489DcXHfAgMlIC0BOqAUiEfJINm9qTHrRe2z5rrM5XecMEzaDPR6Tqq/IH0hUzTc40Tlz
+ZTlAdtCDla6qF0FGk6Q/VDM8ZjmvVJ1txdGRb++4AabAhy7KY31qrMp0BJi3LBG1UzFU/Nb5DvnZ
+KpriN+qaa7bwvEHzT7Xw8SYCfjW4pzEckoeC6R2HDfvMCmRQ7ZreZoRlHNNteglOVTbuga2aWMWJ
+PW1056q7yBMZbQJnsJO+P97na4beeR+c9tV8Bel0e0SM6yumGAEMQdobK23burWRjvdYrgAGPBUD
+/5+mQESQL39xuwNHX/e6CygJoe6Ske2xLkPPuUm6v2ZKz+Wa5IJKWoqpx9ywRdiaObqxMHZBxKnd
+PfEITE5FKvfJpyayIuw2qiKxYUXq0Kbq/CAs8KWnc+6+qwKepO0rnN6AlJH/07wcO0Cr55HgB/zO
+0Id/j/KXkXw0q0uJWgd5OC2yuk8C2J8iSVbVbU60n1WGjHyY4AyTksFW6o3B0W4r6vFjW+mRYXTK
+hvJ6fH+PmdjQ0zwCPuvl823Q63K6IxVKIAKFd6hKMf6y5dd7FVRmwBc//DBHEWIIAXHK71+hoPEo
+hT0YZ/fFhKfGVcO3d7F1T7IPxKd3Ld/6jw6yYvaIaT/Kuf+KTRms6JUdSlvslYca1Pol+5RtRBtF
+s+9kH3NvOLOczCnM1KwNilKs4gdXe/ouuLRBjkKDOpSE+vveOO839oa/1YU6DfhZf4EoGYkHI2w+
+Pzu/abMoGvT0tTuRNakoubyQZ/ZOEFTeWJX51nxewl7lPQi5iWGCDpsAHD6sWdYVtplRiRcYRiQe
+S2OmzgslGZpZJHHtOrjOwpl9ng9O5wwWaPaZiylcwyMiSRWWhpIK64FrApopbxF+K/lj7yH1yK0+
+E+RzC5VfS2lHIzC3qUTp0NFCdzlWHRViG9fasbGt0s62GIbUyJGqDpX9KuR0oGicO+rrkTbb3Xsw
+fqhDdcS2wgGLCoEES5A3sltQSONWT5QLyZRKiBTPGczj0XGXhH5u0Vz6pYK6d4RsGG/IiEOYmMLk
+beVj1tY/0/c/yvNeTLbBK5bgjHrliT1xH2gLxXzEsCA3rjyu4tz1rhAjvmGr0jhIevXh8g8mfNYV
+gUOEoJB9ZTRvc5nvFpgliSzM7aI5YpGohbo1h8EbT+LbCIiaGg1z2PYYbjEkz9dDQ30233kwih65
+NGi3bodYVlG8oEMF6QtRIckXxg9EbFHm93EkIvn6Q7xS8OaLFpXRfIjUhbvU6w41dMfRrDj6gcNG
+mV0KChsw1BsSDIjkWYjtHuhYW+WNcKBlA/XH/hqll4aBVUo5VuZ1PbUlyyZ8kUUqaNCdsT2byuby
+Nl8nvB4daN/7+2hWqerJijTAYfOwlqaKceFzP0n7MiYLKYcTKEWiuy//RJ3rdyO+Igfdm4QeaD4P
+eNOfN24/m7rRHt2hWdP5snR/dNZr+PtMDEXbz/5/rzwH9NJpZyaMhnnCmyzcdClc92QYKT+qkd6e
+MbSxDcfWFr6RJCGo4NdvtEioIi5Yyss7PMvPGacDWN5NWDat8bSp3vk3N5gufHbmoXkjm7IzvGKT
+iLlqAczFA72/BDnzPOUZxO7IuTFCnMZ4etP2A7BpZiaYn/tvXNyw5+20icZB93OsL9O03DMuJVci
+WcnG+WLqTz2WCrw4UC0wpnQnM+oiNR0EKwh5zEiXAErgtmQt/gzlFSN9j1jvr7vQgD4Z3/XKtxlW
+1Wke4Vth0v9js58AClGmcVXRa1rdkZ1GEoMSUsMLZB5VPrvFDTjtxRB8RQuQrgQRMrpGDYQqDsBX
+mKx25KAnlqkpT4iIFF+5o8siwE8imRqAGg/22JUWg8Yud2wtaoXLnfVvUKiELMyLnfkbCjHI+NWN
+QMlQeZ1cAyjGd9cGTQ6APty0eYEWyygf0AMYm5PVpK0+YCXyhxBRFEivclbDqv898EtHmrAePepC
+S8VXAqUqBsf6HaTPC6hAI1et0Xdlmq4FccvHPwcB8T4Z9m1evvwb5S5hnIL4qGgC+k7/enpqJGPJ
+ylei1zil8rc5xUeB1ipYhdw3STYN3+zpsb8z94XHXhocQhvD+aJ0AcOZh3hezKzlQpgWBONjk0AC
++t3p1JBtiNSVmO0ApaTetR09jBDdid1CK6CPx/2gvkizgwQ4M48pbPLqsGYQZG500QNwtRbcWi2q
+LokDU7kh8wZKZ4z3iKRzQGtbQwu8z6DR2TlJOdwAcZ2MFd7ZGLCh88UnAIYb2NkBQFUgmBb7b9x6
+lSqKkxPgfgJV8Nm4AqYbxYPq2nZPgZAF0XLtghJOlWvBN9nwwpPQ4SDlMdXc9x7bc8mvCwSXh153
+JRW44NVOQWnnd/j6v4rxw5fbgLiY7r9g8hRQRR4ESGoQqHcpie42ap6d38wm/wIwBuVg
 """)
 
 ##file activate.sh
 ACTIVATE_SH = convert("""
-eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
-nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
-BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
-M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
-k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
-abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
-MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
-BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
-2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
-4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
-l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
-N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
-Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
-D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
-+n8O9H8f5vsGOWXsL1+1k3g=
+eJytVVFvokAQfudXTLEP2pw1fW3jg01NNGm1KV4vd22zrDDIJrhrYJHay/33m0VEKGpyufIg7s63
+M9/OfDO0YBaKBAIRISzTRMMcIU3Qh0zoEOxEpbGHMBeyxz0t1lyjDRdBrJYw50l4YbVgo1LwuJRK
+Q5xKEBp8EaOno41l+bg7Be0O/LaAnhbEmKAGFfmAci1iJZcoNax5LPg8wiRHiQBeoCvBPmfT+zv2
+PH6afR/cs8fBbGTDG9yADlHmSPOY7f4haInA95WKdQ4s91JpeDQO5fZAnKTxczaaTkbTh+EhMqWx
+QWl/rEGsNJ2kV0cRySKleRGTUKWUVB81pT+vD3Dpw0cSfoMsFF4IIV8jcHqRyVPLpTHrkOu89IUr
+EoDHo4gkoBUsiAFVlP4FKjaLFSeNFEeTS4AfJBOV6sKshVwUbmpAkyA4N8kFL+RygQlkpDfum58N
+GO1QWNLFipij/yn1twOHit5V29UvZ8Seh0/OeDo5kPz8at24lp5jRXSuDlXPuWqUjYCNejlXJwtV
+mHcUtpCddTh53hM7I15EpA+2VNLHRMep6Rn8xK0FDkYB7ABnn6J3jWnXbLvQfyzqz61dxDFGVP1a
+o1Xasx7bsipU+zZjlSVjtlUkoXofq9FHlMZtDxaLCrrH2O14wiaDhyFj1wWs2qIl773iTbZohyza
+iD0TUQQBF5HZr6ISgzKKNZrD5UpvgO5FwoT2tgkIMec+tcYm45sO+fPytqGpBy75aufpTG/gmhRb
++u3AjQtC5l1l7QV1dBAcadt+7UhFGpXONprZRviAWtbY3dgZ3N4P2ePT9OFxdjJiruJSuLk7+31f
+x60HKiWc9eH9SBc04XuPGCVYce1SXlDyJcJrjfKr7ebSNpEaQVpg+l3wiAYOJZ9GCAxoR9JMWAiv
++IyoWBSfhOIIIoRar657vSzLLj9Q0xRZX9Kk6SUq0BmPsceNl179Mi8Vii65Pkj21XXf4MAlSy/t
+Exft7A8WX4/iVRkZprZfNK2/YFL/55T+9wm9m86Uhr8A0Hwt
 """)
 
 ##file activate.fish
 ACTIVATE_FISH = convert("""
-eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5
-3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x
-yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG
-gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD
-2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/
-vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH
-RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo
-9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u
-6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB
-1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC
-OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7
-z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA
-a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b
-vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh
-hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg==
+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
 """)
 
 ##file activate.csh
 ACTIVATE_CSH = convert("""
-eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
-ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
-tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
-r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
-VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
-cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
-tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
-QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
-TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
-n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
-37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
+eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49
+XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp
+kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u
+pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx
+sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM
+yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu
+E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF
+lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7
+r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo=
 """)
 
 ##file activate.bat
 ACTIVATE_BAT = convert("""
-eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
-PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
-r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
-0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
+eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
+qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
+sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
+ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
 """)
 
 ##file deactivate.bat
 DEACTIVATE_BAT = convert("""
-eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho
-cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx
-EchHtwsohN1bILUgw61c/Vy4AJYPYm4=
+eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
+FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
+i2dASrm4rFz9XLgAwJNbyQ==
 """)
 
 ##file activate.ps1
@@ -2388,29 +2221,28 @@
 
 ##file distutils-init.py
 DISTUTILS_INIT = convert("""
-eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E
-UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB
-C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss
-aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT
-0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9
-oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE
-NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c
-f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8
-p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk
-vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw
-hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh
-cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw
-buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ
-5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh
-gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC
-1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL
-MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6
-84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK
-0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO
-kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG
-qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h
-kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9
-GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
+eJytV92L4zYQf/dfMU0ottuse7RvC6FQrg8Lxz2Ugz4si9HacqKuIxlJ2ST313dG8odkO9d7aGBB
+luZLv/nNjFacOqUtKJMIvzK3cXlhWgp5MDBsqK5SNYftsBAGpLLA4F1oe2Ytl+9wUvW55TswCi4c
+KibhbFDSglXQCFmDPXIwtm7FawLRbwtPzg2T9gf4gupKv4GS0N262w7V0NvpbCy8cvTo3eAus6C5
+ETU3ICQZX1hFTw/dzR6V/AW1RCN4/XAtbsVXqIXmlVX6liS4lOzEYY9QFB2zx6LfoSNjz1a0pqT9
+QOIfJWQ2E888NEVZNqLlZZnvIB0NpHkimlFdKn2iRRY7yGG/CCJb6Iz280d34SFXBS2yEYPNF0Q7
+yM7oCjpWvbEDQmnhRwOs6zjThpKE8HogwRAgraqYFZgGZvzmzVh+mgz9vskT3hruwyjdFcqyENJw
+bbMPO5jdzonxK68QKT7B57CMRRG5shRSWDTX3dI8LzRndZbnSWL1zfvriUmK4TcGWSnZiEPCrxXv
+bM+sP7VW2is2WgWXCO3sAu3Rzysz3FiNCA8WPyM4gb1JAAmCiyTZbhFjWx3h9SzauuRXC9MFoVbc
+yNTCm1QXOOIfIn/g1kGMhDUBN72hI5XCBQtIXQw8UEEdma6Jaz4vJIJ51Orc15hzzmu6TdFp3ogr
+Aof0c98tsw1SiaiWotHffk3XYCkqdToxWRfTFXqgpg2khcLluOHMVC0zZhLKIomesfSreUNNgbXi
+Ky9VRzwzkBneNoGQyyvGjbsFQqOZvpWIjqH281lJ/jireFgR3cPzSyTGWzQpDNIU+03Fs4XKLkhp
+/n0uFnuF6VphB44b3uWRneSbBoMSioqE8oeF0JY+qTvYfEK+bPLYdoR4McfYQ7wMZj39q0kfP8q+
+FfsymO0GzNlPh644Jje06ulqHpOEQqdJUfoidI2O4CWx4qOglLye6RrFQirpCRXvhoRqXH3sYdVJ
+AItvc+VUsLO2v2hVAWrNIfVGtkG351cUMNncbh/WdowtSPtCdkzYFv6mwYc9o2Jt68ud6wectBr8
+hYAulPSlgzH44YbV3ikjrulEaNJxt+/H3wZ7bXSXje/YY4tfVVrVmUstaDwwOBLMg6iduDB0lMVC
+UyzYx7Ab4kjCqdViEJmDcdk/SKbgsjYXgfMznUWcrtS4z4fmJ/XOM1LPk/iIpqass5XwNbdnLb1Y
+8h3ERXSWZI6rZJxKs1LBqVH65w0Oy4ra0CBYxEeuOMbDmV5GI6E0Ha/wgVTtkX0+OXvqsD02CKLf
+XHbeft85D7tTCMYy2Njp4DJP7gWJr6paVWXZ1+/6YXLv/iE0M90FktiI7yFJD9e7SOLhEkkaMTUO
+azq9i2woBNR0/0eoF1HFMf0H8ChxH/jgcB34GZIz3Qn4/vid+VEamQrOVqAPTrOfmD4MPdVh09tb
+8dLLjvh/61lEP4yW5vJaH4vHcevG8agXvzPGoOhhXNncpTr99PTHx6e/UvffFLaxUSjuSeP286Dw
+gtEMcW1xKr/he4/6IQ6FUXP+0gkioHY5iwC9Eyx3HKO7af0zPPe+XyLn7fAY78k4aiR387bCr5XT
+5C4rFgwLGfMvJuAMew==
 """)
 
 ##file distutils.cfg
@@ -2434,145 +2266,6 @@
 s3az+sj7eA0jfgPfeoN1
 """)
 
-MH_MAGIC = 0xfeedface
-MH_CIGAM = 0xcefaedfe
-MH_MAGIC_64 = 0xfeedfacf
-MH_CIGAM_64 = 0xcffaedfe
-FAT_MAGIC = 0xcafebabe
-BIG_ENDIAN = '>'
-LITTLE_ENDIAN = '<'
-LC_LOAD_DYLIB = 0xc
-maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
-
-
-class fileview(object):
-    """
-    A proxy for file-like objects that exposes a given view of a file.
-    Modified from macholib.
-    """
-
-    def __init__(self, fileobj, start=0, size=maxint):
-        if isinstance(fileobj, fileview):
-            self._fileobj = fileobj._fileobj
-        else:
-            self._fileobj = fileobj
-        self._start = start
-        self._end = start + size
-        self._pos = 0
-
-    def __repr__(self):
-        return '<fileview [%d, %d] %r>' % (
-            self._start, self._end, self._fileobj)
-
-    def tell(self):
-        return self._pos
-
-    def _checkwindow(self, seekto, op):
-        if not (self._start <= seekto <= self._end):
-            raise IOError("%s to offset %d is outside window [%d, %d]" % (
-                op, seekto, self._start, self._end))
-
-    def seek(self, offset, whence=0):
-        seekto = offset
-        if whence == os.SEEK_SET:
-            seekto += self._start
-        elif whence == os.SEEK_CUR:
-            seekto += self._start + self._pos
-        elif whence == os.SEEK_END:
-            seekto += self._end
-        else:
-            raise IOError("Invalid whence argument to seek: %r" % (whence,))
-        self._checkwindow(seekto, 'seek')
-        self._fileobj.seek(seekto)
-        self._pos = seekto - self._start
-
-    def write(self, bytes):
-        here = self._start + self._pos
-        self._checkwindow(here, 'write')
-        self._checkwindow(here + len(bytes), 'write')
-        self._fileobj.seek(here, os.SEEK_SET)
-        self._fileobj.write(bytes)
-        self._pos += len(bytes)
-
-    def read(self, size=maxint):
-        assert size >= 0
-        here = self._start + self._pos
-        self._checkwindow(here, 'read')
-        size = min(size, self._end - here)
-        self._fileobj.seek(here, os.SEEK_SET)
-        bytes = self._fileobj.read(size)
-        self._pos += len(bytes)
-        return bytes
-
-
-def read_data(file, endian, num=1):
-    """
-    Read a given number of 32-bits unsigned integers from the given file
-    with the given endianness.
-    """
-    res = struct.unpack(endian + 'L' * num, file.read(num * 4))
-    if len(res) == 1:
-        return res[0]
-    return res
-
-
-def mach_o_change(path, what, value):
-    """
-    Replace a given name (what) in any LC_LOAD_DYLIB command found in
-    the given binary with a new name (value), provided it's shorter.
-    """
-
-    def do_macho(file, bits, endian):
-        # Read Mach-O header (the magic number is assumed read by the caller)
-        cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
-        # 64-bits header has one more field.
-        if bits == 64:
-            read_data(file, endian)
-        # The header is followed by ncmds commands
-        for n in range(ncmds):
-            where = file.tell()
-            # Read command header
-            cmd, cmdsize = read_data(file, endian, 2)
-            if cmd == LC_LOAD_DYLIB:
-                # The first data field in LC_LOAD_DYLIB commands is the
-                # offset of the name, starting from the beginning of the
-                # command.
-                name_offset = read_data(file, endian)
-                file.seek(where + name_offset, os.SEEK_SET)
-                # Read the NUL terminated string
-                load = file.read(cmdsize - name_offset).decode()
-                load = load[:load.index('\0')]
-                # If the string is what is being replaced, overwrite it.
-                if load == what:
-                    file.seek(where + name_offset, os.SEEK_SET)
-                    file.write(value.encode() + '\0'.encode())
-            # Seek to the next command
-            file.seek(where + cmdsize, os.SEEK_SET)
-
-    def do_file(file, offset=0, size=maxint):
-        file = fileview(file, offset, size)
-        # Read magic number
-        magic = read_data(file, BIG_ENDIAN)
-        if magic == FAT_MAGIC:
-            # Fat binaries contain nfat_arch Mach-O binaries
-            nfat_arch = read_data(file, BIG_ENDIAN)
-            for n in range(nfat_arch):
-                # Read arch header
-                cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
-                do_file(file, offset, size)
-        elif magic == MH_MAGIC:
-            do_macho(file, 32, BIG_ENDIAN)
-        elif magic == MH_CIGAM:
-            do_macho(file, 32, LITTLE_ENDIAN)
-        elif magic == MH_MAGIC_64:
-            do_macho(file, 64, BIG_ENDIAN)
-        elif magic == MH_CIGAM_64:
-            do_macho(file, 64, LITTLE_ENDIAN)
-
-    assert(len(what) >= len(value))
-    do_file(open(path, 'r+b'))
-
-
 if __name__ == '__main__':
     main()
 
Binary file virtualenv/web/virtualenv_support/distribute-0.6.24.tar.gz has changed
Binary file virtualenv/web/virtualenv_support/pip-1.1.tar.gz has changed
Binary file virtualenv/web/virtualenv_support/setuptools-0.6c11-py2.4.egg has changed
Binary file virtualenv/web/virtualenv_support/setuptools-0.6c11-py2.5.egg has changed
Binary file virtualenv/web/virtualenv_support/setuptools-0.6c11-py2.6.egg has changed
Binary file virtualenv/web/virtualenv_support/setuptools-0.6c11-py2.7.egg has changed