Commit 0cc53de7 authored by Laura Médioni's avatar Laura Médioni
Browse files

[views] allow the user to choose the concept hierarchical separator

Also extract a build_result_dict() from add_concepts_from_file() on the way, since this code is used
everywhere

closes #2892966
parent 6339faea7641
......@@ -29,6 +29,15 @@ def _add_concept(scheme, label, language_code, **kwargs):
return concept
class CSVIndentationError(ValueError):
"""hierarchical file has an invalid indentation (level was reduced by more than one indentation)
"""
def __init__(self, line):
super(CSVIndentationError, self).__init__()
self.line = line
class ConceptScheme(AnyEntity):
__regid__ = 'ConceptScheme'
fetch_attrs, cw_fetch_order = fetch_config(('title', 'cwuri'))
......@@ -74,7 +83,7 @@ class ConceptScheme(AnyEntity):
# the conceptscheme to the more recent broader concept. The last element is consequently
# the current parent concept. When de-indenting, the concepts are popped.
broaderconcepts = [(-1, self)]
for line in source_file:
for nline, line in enumerate(source_file):
line = line.rstrip().decode(encoding)
if not line:
continue
......@@ -86,7 +95,7 @@ class ConceptScheme(AnyEntity):
line = line[nb_sep:]
# can't have "concept\n tab tab subconcept"
if nb_sep - broaderconcepts[-1][0] > 1:
raise ValueError('Inconsistent concept indentation')
raise CSVIndentationError(nline + 1)
value = line.strip()
if nb_sep <= broaderconcepts[-1][0]:
# it is possible to de-indent various levels, but always keep the conceptscheme
......
......@@ -15,6 +15,12 @@ msgstr ""
msgid "%(KEY-rtype)s is part of violated unicity constraint"
msgstr ""
msgid ","
msgstr ""
msgid ";"
msgstr ""
# schema pot file, generated on 2015-02-02 14:25:24
#
# singular and plural forms for each entity type
......@@ -45,6 +51,10 @@ msgstr ""
msgid "Import concepts from file"
msgstr ""
#, python-format
msgid "Indentation error line %s"
msgstr ""
msgid "Label"
msgstr ""
......@@ -350,6 +360,9 @@ msgctxt "Concept"
msgid "hidden_label_of_object"
msgstr ""
msgid "hierarchical separator"
msgstr ""
msgid "import concept scheme from SKOS"
msgstr ""
......@@ -478,6 +491,12 @@ msgstr "top concepts"
msgid "some relations violate a unicity constraint"
msgstr ""
msgid "space"
msgstr ""
msgid "tabulation"
msgstr ""
msgctxt "ConceptScheme"
msgid "title"
msgstr ""
......
......@@ -15,6 +15,12 @@ msgstr ""
msgid "%(KEY-rtype)s is part of violated unicity constraint"
msgstr "%(KEY-rtype)s appartient à une contrainte d'unicité transgressée"
msgid ","
msgstr ""
msgid ";"
msgstr ""
# schema pot file, generated on 2015-02-02 14:25:24
#
# singular and plural forms for each entity type
......@@ -45,6 +51,10 @@ msgstr "Import terminé avec succès"
msgid "Import concepts from file"
msgstr "Importer les concepts depuis un fichier"
#, python-format
msgid "Indentation error line %s"
msgstr "Erreur d'indentation ligne %s"
msgid "Label"
msgstr "Libellé"
......@@ -351,6 +361,9 @@ msgctxt "Concept"
msgid "hidden_label_of_object"
msgstr ""
msgid "hierarchical separator"
msgstr "séparateur hiérarchique"
msgid "import concept scheme from SKOS"
msgstr "importer un vocabulaire contrôlé depuis un fichier SKOS"
......@@ -479,6 +492,12 @@ msgstr "concepts racines"
msgid "some relations violate a unicity constraint"
msgstr "certaines relations transgressent une contrainte d'unicité"
msgid "space"
msgstr "espace"
msgid "tabulation"
msgstr "tabulation"
msgctxt "ConceptScheme"
msgid "title"
msgstr ""
......
......@@ -19,6 +19,8 @@ from StringIO import StringIO
from cubicweb.devtools.testlib import CubicWebTC
from cubes.skos.entities import CSVIndentationError
def get_narrower_concepts(concept):
"""Get a dictionnary matching the name of the concept to the dictionnary of its narrower
......@@ -100,9 +102,9 @@ class ConceptSchemeTC(CubicWebTC):
rapport = StringIO('toto\n\ttiti\n\t\t\ttata')
with self.admin_access.web_request() as req:
scheme = req.entity_from_eid(scheme.eid)
with self.assertRaises(ValueError) as ve:
with self.assertRaises(CSVIndentationError) as cie:
scheme.add_concepts_from_file(rapport, u'utf-8', u'fr', u'\t')
self.assertEqual(str(ve.exception), 'Inconsistent concept indentation')
self.assertEqual(cie.exception.line, 3)
def test_add_concepts_from_file_multiple_deindentation(self):
with self.admin_access.client_cnx() as cnx:
......
......@@ -35,6 +35,7 @@ class ViewsTC(CubicWebTC):
'file': ('filename.txt', StringIO('\n\nélectro\nhip-hop\nrap\njazz\nclassique\n')),
'encoding': u'utf-8',
'language': u'fr',
'separator': u'tab',
}, [(scheme, {})])
# now actually tests the import, using scheme.view and not self.view which doesn't like
# exception, even Redirect
......
......@@ -17,6 +17,8 @@
from rql.utils import uquote
from cubicweb import ValidationError
from cubicweb.predicates import (is_instance, has_related_entities, one_line_rset,
score_entity, match_user_groups)
from cubicweb.view import View, AnyRsetView, EntityView
......@@ -26,6 +28,7 @@ from cubicweb.web import (action, component, formfields as ff, formwidgets as fw
from cubicweb.web.views import uicfg, ibreadcrumbs, tableview, forms, tabs, cwsources
from cubes.skos import to_unicode
from cubes.skos.entities import CSVIndentationError
_ = unicode
......@@ -236,6 +239,12 @@ class ImportSchemeConceptsForm(ImportSchemeConceptsMixIn, forms.EntityFieldsForm
internationalizable=True,
choices=[(_('french'), u'fr'),
(_('english'), u'en')], sort=False)
separator = ff.StringField(name='separator', label=_('hierarchical separator'),
internationalizable=True,
choices=[(_('tabulation'), 'tab'),
(_(';'), ';'),
(_(','), ','),
(_('space'), 'space')], sort=False)
form_buttons = [fw.SubmitButton(label=_('to_import'))]
@property
......@@ -250,7 +259,12 @@ class ImportSchemeConceptsView(ImportSchemeConceptsMixIn, EntityView):
form = self._cw.vreg['forms'].select(self.__regid__, self._cw, entity=entity)
if form.posting:
posted = form.process_posted()
entity.add_concepts_from_file(posted['file'], posted['encoding'], posted['language'])
separators = {'tab': '\t', 'space': ' ', ',': ',', ';': ';'}
try:
entity.add_concepts_from_file(posted['file'], posted['encoding'], posted['language'],
separators[posted['separator']])
except CSVIndentationError as ve:
raise ValidationError(entity.eid, {None: self._cw._("Indentation error line %s") % ve.line})
raise Redirect(entity.absolute_url(__message=self._cw._('Import completed')))
else:
form.render(w=self.w)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment