Commit b920a832 authored by Erica Marco's avatar Erica Marco
Browse files

Create a view for LCSV Import

closes #3121346
parent ca0271e8eaf4
......@@ -59,6 +59,9 @@ msgstr ""
msgid "Indentation error line %s"
msgstr ""
msgid "LCSV"
msgstr "Linked CSV"
msgid "Label"
msgstr ""
......@@ -330,6 +333,9 @@ msgstr ""
msgid "file encoding"
msgstr ""
msgid "file format"
msgstr ""
msgid "french"
msgstr ""
......@@ -370,7 +376,7 @@ msgstr ""
msgid "import concept scheme from SKOS"
msgstr ""
msgid "import concepts from flat file"
msgid "import concepts from a file"
msgstr ""
msgid "in_scheme"
......@@ -486,6 +492,9 @@ msgstr ""
msgid "scheme the concept has been attached to"
msgstr ""
msgid "simple"
msgstr ""
msgid "skos_sub_concepts_tab"
msgstr "narrow concepts"
......
......@@ -59,6 +59,9 @@ msgstr "Importer les concepts depuis un fichier"
msgid "Indentation error line %s"
msgstr "Erreur d'indentation ligne %s"
msgid "LCSV"
msgstr "Linked CSV"
msgid "Label"
msgstr "Libellé"
......@@ -331,6 +334,9 @@ msgstr ""
msgid "file encoding"
msgstr "encodage du fichier"
msgid "file format"
msgstr "format du fichier"
msgid "french"
msgstr "français"
......@@ -371,7 +377,7 @@ msgstr "séparateur hiérarchique"
msgid "import concept scheme from SKOS"
msgstr "importer un vocabulaire contrôlé depuis un fichier SKOS"
msgid "import concepts from flat file"
msgid "import concepts from a file"
msgstr "importer les concepts depuis un fichier"
msgid "in_scheme"
......@@ -487,6 +493,9 @@ msgstr ""
msgid "scheme the concept has been attached to"
msgstr "vocabulaire auquel le concept est attaché"
msgid "simple"
msgstr ""
msgid "skos_sub_concepts_tab"
msgstr "sous-concepts"
......
......@@ -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',
'format': u'simple',
'separator': u'tab',
}, [(scheme, {})])
# now actually tests the import, using scheme.view and not self.view which doesn't like
......@@ -45,6 +46,43 @@ class ViewsTC(CubicWebTC):
self.assertEqual(set(l.language_code for c in scheme.top_concepts for l in c.pref_label),
set(['fr']))
def test_lcsv_scheme_concepts_import(self):
with self.admin_access.client_cnx() as cnx:
scheme = cnx.create_entity('ConceptScheme', title=u'gni')
cnx.commit()
with self.admin_access.web_request() as req:
scheme = req.entity_from_eid(scheme.eid)
# simply test the form properly render and is well formed
self.view('skos.scheme.import', rset=scheme.as_rset(), req=req,
template=None)
fname = 'lcsv_example_shortened.csv'
posted = {'file': (fname, open(self.datapath(fname))),
'encoding': u'utf-8',
'language': u'fr',
'separator': u'tab',
'format': u'lcsv'}
req.form = self.fake_form('skos.scheme.import', posted, [(scheme, {})])
# now actually tests the import, using scheme.view and not self.view which doesn't like
# exception, even Redirect
self.assertRaises(Redirect, scheme.view, 'skos.scheme.import')
# check that the concept were added
with self.admin_access.client_cnx() as cnx:
scheme = cnx.find('ConceptScheme', title=u'gni').one()
self.assertEqual(len(scheme.top_concepts), 2)
concepts = cnx.find('Concept')
self.assertEqual(len(concepts), 5)
concept1 = cnx.find('Concept',
definition="Définition de l'organisation politique de l'organisme,"
).one()
label = concept1.pref_label[0]
self.assertEqual(len(concept1.pref_label), 1)
self.assertEqual((label.label,label.language_code),('Vie politique', 'fr'))
self.assertEqual(len(concept1.narrower_concept), 2)
concept2 = cnx.find('Concept',
definition="Création volontaire ou en application de la loi").one()
self.assertEqual(concept2.broader_concept[0], concept1)
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
......
......@@ -27,7 +27,7 @@ from cubicweb.web import (action, component, formfields as ff, formwidgets as fw
facet)
from cubicweb.web.views import uicfg, ibreadcrumbs, tableview, forms, tabs, cwsources
from cubes.skos import to_unicode
from cubes.skos import to_unicode, lcsv
from cubes.skos.entities import CSVIndentationError, CSVDecodeError
......@@ -206,7 +206,7 @@ class ImportSchemeConceptsMixIn(object):
class ImportSchemeConceptsAction(ImportSchemeConceptsMixIn, action.Action):
title = _('import concepts from flat file')
title = _('import concepts from a file')
def url(self):
entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
......@@ -216,20 +216,25 @@ class ImportSchemeConceptsAction(ImportSchemeConceptsMixIn, action.Action):
class ImportSchemeConceptsForm(ImportSchemeConceptsMixIn, forms.EntityFieldsForm):
"""ask for a file to import"""
filefield = ff.FileField(name='file', label=_('Concepts file'), required=True)
formatfield = ff.StringField(name='format', label=_('file format'),
required=True, internationalizable=True,
choices=[(_('simple'), u'simple'),
(_(u'LCSV'), u'lcsv')], sort=False)
encoding = ff.StringField(name='encoding', label=_('file encoding'),
internationalizable=True,
choices=[(_('utf-8'), u'utf-8'),
(_('latin 1'), u'latin1')], sort=False)
language = ff.StringField(name='language', label=_('language of concepts in the file'),
language = ff.StringField(name='language',
label=_('language of concepts in the file'),
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)
internationalizable=True,
choices=[(_('tabulation'), 'tab'),
(_(';'), ';'),
(_(','), ','),
(_('space'), 'space')], sort=False)
form_buttons = [fw.SubmitButton(label=_('to_import'))]
@property
......@@ -239,23 +244,46 @@ class ImportSchemeConceptsForm(ImportSchemeConceptsMixIn, forms.EntityFieldsForm
class ImportSchemeConceptsView(ImportSchemeConceptsMixIn, EntityView):
separators = {'tab': '\t', 'space': ' ', ',': ',', ';': ';'}
def entity_call(self, entity):
self.w('<h1>%s</h1>' % self._cw._('Import concepts from file'))
form = self._cw.vreg['forms'].select(self.__regid__, self._cw, entity=entity)
if form.posting:
posted = form.process_posted()
separators = {'tab': '\t', 'space': ' ', ',': ',', ';': ';'}
try:
entity.add_concepts_from_file(posted['file'], posted['encoding'], posted['language'],
separators[posted['separator']])
except CSVIndentationError as exc:
raise ValidationError(entity.eid, {None: self._cw._("Indentation error line %s") % exc.line})
except CSVDecodeError as exc:
raise ValidationError(entity.eid, {None: self._cw._("Encoding error line %s") % exc.line})
if posted.pop('format') == 'simple':
self._simple_import(entity, posted)
else:
self._lcsv_import(entity, posted)
raise Redirect(entity.absolute_url(__message=self._cw._('Import completed')))
else:
form.render(w=self.w)
def _simple_import(self, entity, posted):
delimiter = self.separators[posted['separator']]
try:
entity.add_concepts_from_file(posted['file'], posted['encoding'],
posted['language'], delimiter)
except CSVIndentationError as exc:
raise ValidationError(entity.eid,
{None: self._cw._("Indentation error line %s") % exc.line})
except CSVDecodeError as exc:
raise ValidationError(entity.eid,
{None: self._cw._("Encoding error line %s") % exc.line})
def _lcsv_import(self, entity, posted):
delimiter = self.separators[posted['separator']]
try:
self._cw.cnx.call_service('lcsv.skos.import',
scheme_uri=entity.cwuri,
stream=posted['file'],
encoding=posted['encoding'],
delimiter=delimiter,
default_lang = posted['language'])
except Exception as exc:
# XXX No localization here.
raise ValidationError(entity.eid, {None: to_unicode(exc)})
# SKOS import ##################################################################
......
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