Commit 75c3b58e authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

[views] implement import of concepts from a simple file

parent f1ebb64ec07a
......@@ -19,6 +19,12 @@ from logilab.common.decorators import cachedproperty
from cubicweb.entities import AnyEntity
def _add_concept(scheme, label, language_code, **kwargs):
cnx = scheme._cw
concept = cnx.create_entity('Concept', in_scheme=scheme, **kwargs)
cnx.create_entity('Label', label=label, language_code=language_code,
pref_label_of=concept)
return concept
class ConceptScheme(AnyEntity):
__regid__ = 'ConceptScheme'
......@@ -32,6 +38,9 @@ class ConceptScheme(AnyEntity):
def top_concepts(self):
return list(self.top_concepts_rset.entities())
def add_concept(self, label, language_code=u'en'):
"""Add a top-concept to this scheme"""
_add_concept(self, label, language_code)
class Concept(AnyEntity):
__regid__ = 'Concept'
......@@ -63,6 +72,10 @@ class Concept(AnyEntity):
# pick one random label
return self.labels.values()[0]
def add_concept(self, label, language_code=u'en'):
"""Add a sub-concept to this concept"""
_add_concept(self.scheme, label, language_code, broader_concept=self)
class Label(AnyEntity):
__regid__ = 'Label'
......
......@@ -26,12 +26,21 @@ msgstr ""
msgid "Concept_plural"
msgstr ""
msgid "Concepts file"
msgstr ""
msgid "Expression used to refer to a concept in natural language"
msgstr ""
msgid "Import a SKOS file"
msgstr ""
msgid "Import completed"
msgstr ""
msgid "Import concepts from file"
msgstr ""
msgid "Label"
msgstr ""
......@@ -71,7 +80,8 @@ msgstr ""
msgid "SKOS file"
msgstr ""
msgid "SKOS import completed"
#, python-format
msgid "SKOS import completed: %s"
msgstr ""
msgid "SKOS import failed: "
......@@ -239,6 +249,9 @@ msgctxt "ConceptScheme"
msgid "description_format"
msgstr ""
msgid "english"
msgstr ""
msgid "example"
msgstr ""
......@@ -253,6 +266,12 @@ msgctxt "Concept"
msgid "example_format"
msgstr ""
msgid "file encoding"
msgstr ""
msgid "french"
msgstr ""
msgid "hidden"
msgstr ""
......@@ -284,7 +303,10 @@ msgctxt "Concept"
msgid "hidden_label_of_object"
msgstr ""
msgid "import concept schemes from SKOS"
msgid "import concept scheme from SKOS"
msgstr ""
msgid "import concepts from flat file"
msgstr ""
msgid "in_scheme"
......@@ -314,6 +336,9 @@ msgstr ""
msgid "language code, e.g. \"en\" or \"fr-fr\""
msgstr ""
msgid "language of concepts in the file"
msgstr ""
msgid "language_code"
msgstr ""
......@@ -321,6 +346,9 @@ msgctxt "Label"
msgid "language_code"
msgstr ""
msgid "latin 1"
msgstr ""
msgid "more general concept"
msgstr ""
......@@ -398,5 +426,8 @@ msgstr ""
msgid "to_import"
msgstr ""
msgid "utf-8"
msgstr ""
msgid "xml"
msgstr ""
......@@ -26,12 +26,21 @@ msgstr "Vocabulaires contrôlés"
msgid "Concept_plural"
msgstr "Concepts"
msgid "Concepts file"
msgstr "Fichier contenant les concepts"
msgid "Expression used to refer to a concept in natural language"
msgstr "Expression référrant à un concept en langage naturel"
msgid "Import a SKOS file"
msgstr "Importer un fichier SKOS"
msgid "Import completed"
msgstr "Import terminé avec succès"
msgid "Import concepts from file"
msgstr "Importer les concepts depuis un fichier"
msgid "Label"
msgstr "Libellé"
......@@ -71,8 +80,9 @@ msgstr "format RDF"
msgid "SKOS file"
msgstr "fichier SKOS"
msgid "SKOS import completed"
msgstr "Import SKOS effectué"
#, python-format
msgid "SKOS import completed: %s"
msgstr "Import SKOS effectué : %s"
msgid "SKOS import failed: "
msgstr "Échec de l'import SKOS :"
......@@ -239,6 +249,9 @@ msgctxt "ConceptScheme"
msgid "description_format"
msgstr ""
msgid "english"
msgstr "anglais"
msgid "example"
msgstr "exemple"
......@@ -253,6 +266,12 @@ msgctxt "Concept"
msgid "example_format"
msgstr ""
msgid "file encoding"
msgstr "encodage du fichier"
msgid "french"
msgstr "français"
msgid "hidden"
msgstr "caché"
......@@ -287,6 +306,9 @@ msgstr ""
msgid "import concept scheme from SKOS"
msgstr "importer un vocabulaire contrôlé depuis un fichier SKOS"
msgid "import concepts from flat file"
msgstr "importer les concepts depuis un fichier"
msgid "in_scheme"
msgstr "dans le vocabulaire"
......@@ -314,6 +336,9 @@ msgstr "type de libellé"
msgid "language code, e.g. \"en\" or \"fr-fr\""
msgstr "code langage, e.g. \"en\" ou \"fr-fr\""
msgid "language of concepts in the file"
msgstr "langue des concepts dans le fichier"
msgid "language_code"
msgstr "code langage"
......@@ -321,6 +346,9 @@ msgctxt "Label"
msgid "language_code"
msgstr ""
msgid "latin 1"
msgstr ""
msgid "more general concept"
msgstr "concept plus générique"
......@@ -398,5 +426,8 @@ msgstr ""
msgid "to_import"
msgstr "importer"
msgid "utf-8"
msgstr ""
msgid "xml"
msgstr ""
# coding: utf-8
# copyright 2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr -- mailto:contact@logilab.fr
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from StringIO import StringIO
from cubicweb.web import Redirect, eid_param
from cubicweb.devtools.testlib import CubicWebTC
def fake_form(formid, field_dict, entity_field_dicts):
form = {'__form_id': formid}
fields = []
for field, value in field_dict.items():
fields.append(field)
form[field] = value
def _add_entity_field(entity, field, value):
entity_fields.append(field)
form[eid_param(field, entity.eid)] = value
for entity, field_dict in entity_field_dicts:
if '__maineid' not in form:
form['__maineid'] = entity.eid
entity_fields = []
form.setdefault('eid', []).append(entity.eid)
_add_entity_field(entity, '__type', entity.cw_etype)
for field, value in field_dict.items():
_add_entity_field(entity, field, value)
if entity_fields:
form[eid_param('_cw_entity_fields', entity.eid)] = ','.join(entity_fields)
if fields:
form['_cw_fields'] = ','.join(fields)
return form
# input class="form-control" name="__type:858" type="hidden" value="ConceptScheme" />
# <input class="form-control" name="eid" type="hidden" value="858" />
# <input class="form-control" name="__form_generation_time:858" type="hidden" value="1423044545.187907" />
# <input class="form-control" name="__maineid" type="hidden" value="858" />
# <input class="form-control" name="_cw_fields" type="hidden" value="__maineid,eid,language,file,encoding" />
# <input class="form-control" name="_cw_entity_fields:858" type="hidden" value="__type,__form_generation_time" />
class ViewsTC(CubicWebTC):
def test_scheme_concepts_import(self):
with self.admin_access.client_cnx() as cnx:
scheme = cnx.create_entity('ConceptScheme', title=u'musique')
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)
req.form = fake_form('skos.scheme.import', {
'file': ('filename.txt', StringIO('\n\nélectro\nhip-hop\nrap\njazz\nclassique\n')),
'encoding': u'utf-8',
'language': u'fr',
}, [(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')
self.assertEqual(set(c.dc_title() for c in scheme.top_concepts),
set(u'électro hip-hop rap jazz classique'.split()))
self.assertEqual(set(l.language_code for c in scheme.top_concepts for l in c.pref_label),
set(['fr']))
......@@ -15,8 +15,9 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""cubicweb-skos views"""
from cubicweb.predicates import is_instance, has_related_entities
from cubicweb.view import AnyRsetView, View
from cubicweb.predicates import is_instance, has_related_entities, one_line_rset
from cubicweb.view import View, AnyRsetView, EntityView
from cubicweb.web import Redirect
from cubicweb.web import action, component, formfields as ff, formwidgets as fw
from cubicweb.web.views import uicfg, ibreadcrumbs, tableview, forms, cwsources
......@@ -130,6 +131,60 @@ class ConceptIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
return self.entity.parent_concept or self.entity.scheme
# simple file import ###########################################################
class ImportSchemeConceptsMixIn(object):
__regid__ = 'skos.scheme.import'
__select__ = (is_instance('ConceptScheme')
& match_user_groups('managers')
& one_line_rset())
class ImportSchemeConceptsAction(ImportSchemeConceptsMixIn, action.Action):
title = _('import concepts from flat file')
def url(self):
entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
return entity.absolute_url(vid=self.__regid__)
class ImportSchemeConceptsForm(ImportSchemeConceptsMixIn, forms.EntityFieldsForm):
"""ask for a file to import"""
filefield = ff.FileField(name='file', label=_('Concepts file'), required=True)
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'),
internationalizable=True,
choices=[(_('french'), u'fr'),
(_('english'), u'en')], sort=False)
form_buttons = [fw.SubmitButton(label=_('to_import'))]
@property
def action(self):
return self.edited_entity.absolute_url(vid=self.__regid__)
class ImportSchemeConceptsView(ImportSchemeConceptsMixIn, EntityView):
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()
encoding = posted['encoding']
language_code = posted['language']
for line in posted['file']:
line = line.strip()
if not line:
continue
entity.add_concept(line.decode(encoding), language_code)
raise Redirect(entity.absolute_url(__message=self._cw._('Import completed')))
else:
form.render(w=self.w)
# SKOS import ##################################################################
class ImportConceptSchemeAction(action.Action):
......@@ -146,12 +201,6 @@ class SKOSImportForm(forms.FieldsForm):
"""ask for a file to import"""
__regid__ = 'rdf.skos.import'
__select__ = match_user_groups('managers')
form_buttons = [fw.SubmitButton(label=_('to_import'))]
@property
def action(self):
return self._cw.build_url(vid=self.__regid__)
filefield = ff.FileField(name='file', label=_('SKOS file'), required=True)
formatfield = ff.StringField(name='format', label=_('RDF format'),
internationalizable=True,
......@@ -159,6 +208,11 @@ class SKOSImportForm(forms.FieldsForm):
(_('xml'), u'xml'),
(_('ntriples'), u'nt'),
(_('n3'), u'n3'),], sort=False)
form_buttons = [fw.SubmitButton(label=_('to_import'))]
@property
def action(self):
return self._cw.build_url(vid=self.__regid__)
class SKOSImportResultView(View):
......
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