summaryrefslogtreecommitdiff
path: root/chimere/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'chimere/utils.py')
-rw-r--r--chimere/utils.py106
1 files changed, 85 insertions, 21 deletions
diff --git a/chimere/utils.py b/chimere/utils.py
index 62d3786..b2c8ccc 100644
--- a/chimere/utils.py
+++ b/chimere/utils.py
@@ -21,10 +21,14 @@
Utilitaries
"""
-import urllib2
+import urllib2, re
+from external_utils import OsmApi
from lxml import etree
+from chimere import get_version
+from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
+from django.utils.translation import ugettext_lazy as _
class ImportManager:
u"""
@@ -42,11 +46,10 @@ class ImportManager:
class KMLManager(ImportManager):
u"""
KML importer
- The filtr argument has to be defined as a correct Xpath string pointing
- to Placemark nodes.
- A typical XPath string looks like:
- "//kml:Folder/kml:name[text()='Subcategory 1']/../kml:Placemark"
+ The filtr argument has to be defined as the exact name of the folder to be
+ imported
"""
+ XPATH = '//kml:Folder/kml:name[text()="%s"]/../kml:Placemark'
def __init__(self, importer_instance, ns=''):
self.importer_instance = importer_instance
self.ns = ns
@@ -62,11 +65,11 @@ class KMLManager(ImportManager):
from models import Marker
new_item, updated_item, msg = 0, 0, ''
try:
- source = urllib2.urlopen(self.importer_instance.source_url)
+ source = urllib2.urlopen(self.importer_instance.source)
except ValueError:
# assume it is a local file
try:
- source = open(self.importer_instance.source_url)
+ source = open(self.importer_instance.source)
except IOError, msg:
return (new_item, updated_item, msg)
except urllib2.URLError as error:
@@ -75,10 +78,11 @@ class KMLManager(ImportManager):
# try to get default namespace
if not self.ns:
self.ns = tree.getroot().nsmap[None]
- for placemark in tree.xpath(self.importer_instance.filtr,
+ for placemark in tree.xpath(self.XPATH % self.importer_instance.filtr,
namespaces={'kml':self.ns}):
name, point, linestring = None, None, None
pl_id = placemark.attrib.get('id')
+ pl_key = 'kml-%d' % self.importer_instance.pk
ns = '{%s}' % self.ns
for item in placemark:
if item.tag == ns + 'name':
@@ -97,8 +101,8 @@ class KMLManager(ImportManager):
m = None
if pl_id:
dct_import = {
- 'import_key':pl_id,
- 'import_source':self.importer_instance.source_url}
+ 'import_key__icontains':'%s:%s;' % (pl_key, pl_id),
+ 'import_source':self.importer_instance.source}
try:
m = Marker.objects.get(**dct_import)
for k in dct:
@@ -107,16 +111,23 @@ class KMLManager(ImportManager):
updated_item += 1
except ObjectDoesNotExist:
m = None
- dct.update(dct_import)
+ dct.update({
+ 'import_source':self.importer_instance.source})
if not m:
dct['status'] = 'I'
m = Marker.objects.create(**dct)
new_item += 1
+ if pl_id:
+ m.set_key(pl_key, pl_id)
m.categories.clear()
for cat in self.importer_instance.categories.all():
m.categories.add(cat)
return (new_item, updated_item, msg)
+RE_NODE = re.compile('node\[([^\]]*)\]')
+
+# manage deleted item from OSM
+
class OSMManager(ImportManager):
u"""
OSM importer
@@ -124,23 +135,25 @@ class OSMManager(ImportManager):
The filtr argument is XAPI args or empty if it is an OSM file.
"""
- def get(self):
+ def get(self, get_items=None):
u"""
Get data from the source
Return a tuple with:
- - number of new item ;
- - number of item updated ;
+ - new items or number of new items if nb_only = True;
+ - updated items or number of updated items if nb_only = True;
- error detail on error
"""
from models import Marker
- new_item, updated_item, msg = 0, 0, ''
+ new_item, updated_item = 0 , 0
+ items = []
+ msg = ''
try:
- source = urllib2.urlopen(self.importer_instance.source_url+
+ source = urllib2.urlopen(settings.CHIMERE_XAPI_URL+
self.importer_instance.filtr)
except ValueError:
# assume it is a local file
try:
- source = open(self.importer_instance.source_url)
+ source = open(self.importer_instance.source)
except IOError, msg:
return (new_item, updated_item, msg)
except urllib2.URLError as error:
@@ -163,10 +176,11 @@ class OSMManager(ImportManager):
m = None
if node_id:
dct_import = {
- 'import_key':node_id,
- 'import_source':self.importer_instance.source_url}
+ 'import_key__icontains':'OSM:%s;' % (node_id),
+ 'import_source':self.importer_instance.source}
try:
m = Marker.objects.get(**dct_import)
+ items.append(m)
if version and m.import_version == int(version):
# no update since the last import
continue
@@ -176,12 +190,62 @@ class OSMManager(ImportManager):
updated_item += 1
except ObjectDoesNotExist:
m = None
- dct.update(dct_import)
+ dct.update({
+ 'import_source':self.importer_instance.source})
if not m:
dct['status'] = 'I'
m = Marker.objects.create(**dct)
new_item += 1
+ items.append(m)
+ if node_id:
+ m.set_key('OSM', node_id)
m.categories.clear()
for cat in self.importer_instance.categories.all():
m.categories.add(cat)
- return (new_item, updated_item, msg)
+ if not get_items:
+ return (new_item, updated_item, msg)
+ return (items, new_item, updated_item, msg)
+
+ def put(self):
+ # first of all: reimport in order to verify that no changes has been
+ # made since the last import
+ from models import Marker
+ items, new_item, updated_item, msg = self.get(get_items=True)
+ # check if import is possible
+ if msg:
+ return 0, msg
+ if new_item:
+ return 0, _(u"New items imported - validate them before exporting")
+ if Marker.objects.filter(status='I').count():
+ return 0, _(u"There are items from a former import not yet "
+ u"validated - validate them before exporting")
+ # start import
+ api = OsmApi.OsmApi(api=settings.CHIMERE_OSM_API_URL,
+ username=settings.CHIMERE_OSM_USER,
+ password=settings.CHIMERE_OSM_PASSWORD)
+ api.ChangesetCreate({u"comment": u"Import from Chimère %s" % \
+ get_version()})
+ tag = RE_NODE.finddall(self.importer_instance.filtr)
+ if not tag:
+ return 0, _(u"Bad param")
+ tag = tag[0].split('=')
+ default_dct = {'tag':{tag[0]:tag[1]},
+ 'import_source':self.importer_instance.source}
+ for idx, item in Marker.objects.filter(status='A',
+ categories=self.importer_instance.categories.all()):
+ dct = default_dct.update({
+ 'name':item.name,
+ 'lon':item.point.lon,
+ 'lat':item.point.lat})
+ node = None
+ import_key = marker.get_key('OSM')
+ if not import_key:
+ node = OsmApi.NodeCreate(dct)
+ item.set_key('OSM', node['id'])
+ else:
+ dct['id'] = import_key
+ node = OsmApi.NodeUpdate(dct)
+ item.import_version = node['version']
+ item.save()
+ api.ChangesetClose()
+ return idx+1, None