Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

Commit

Permalink
Moved compatibility shim from geonode.__init__ to geonode.backward_co…
Browse files Browse the repository at this point in the history
…mpatibility. Added test for shim.
  • Loading branch information
JivanAmara committed Nov 9, 2016
1 parent a7112be commit c40c970
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 89 deletions.
91 changes: 2 additions & 89 deletions osgeo_importer/handlers/geonode/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import datetime
import logging
import os
import uuid
Expand All @@ -8,104 +7,18 @@
from django.contrib.auth import get_user_model

from geonode.layers.metadata import set_metadata
from geonode.layers.models import Layer, Attribute
from geonode.layers.models import Layer
from geonode.layers.utils import resolve_regions
from osgeo_importer.handlers import ImportHandlerMixin
from osgeo_importer.handlers import ensure_can_run
from osgeo_importer.importers import UPLOAD_DIR
from osgeo_importer.models import UploadLayer

from backward_compatibility import set_attributes

User = get_user_model()
logger = logging.getLogger(__name__)


# The function set_attributes() is used in GeoNodePublishHandler.handle()
# In case the user is using osgeo_importer with a version of GeoNode older than
# 2016-11-08, commit 005bd559ed97ace87b33d7abd3e84d3e307d4547, duplicate the
# GeoNode-independent set_attributes() here. If the duplicated code is still
# here after 2018-11-01, it should be removed.
try:
from geonode.utils import set_attributes
except ImportError:
def set_attributes(layer, attribute_map, overwrite=False, attribute_stats=None):
""" *layer*: a geonode.layers.models.Layer instance
*attribute_map*: a list of 2-lists specifying attribute names and types,
example: [ ['id', 'Integer'], ... ]
*overwrite*: replace existing attributes with new values if name/type matches.
*attribute_stats*: dictionary of return values from get_attribute_statistics(),
of the form to get values by referencing attribute_stats[<layer_name>][<field_name>].
"""
# we need 3 more items; description, attribute_label, and display_order
attribute_map_dict = {
'field': 0,
'ftype': 1,
'description': 2,
'label': 3,
'display_order': 4,
}
for attribute in attribute_map:
attribute.extend((None, None, 0))

attributes = layer.attribute_set.all()
# Delete existing attributes if they no longer exist in an updated layer
for la in attributes:
lafound = False
for attribute in attribute_map:
field, ftype, description, label, display_order = attribute
if field == la.attribute:
lafound = True
# store description and attribute_label in attribute_map
attribute[attribute_map_dict['description']] = la.description
attribute[attribute_map_dict['label']] = la.attribute_label
attribute[attribute_map_dict['display_order']] = la.display_order
if overwrite or not lafound:
logger.debug(
"Going to delete [%s] for [%s]",
la.attribute,
layer.name.encode('utf-8'))
la.delete()

# Add new layer attributes if they don't already exist
if attribute_map is not None:
iter = len(Attribute.objects.filter(layer=layer)) + 1
for attribute in attribute_map:
field, ftype, description, label, display_order = attribute
if field is not None:
la, created = Attribute.objects.get_or_create(
layer=layer, attribute=field, attribute_type=ftype,
description=description, attribute_label=label,
display_order=display_order)
if created:
if (not attribute_stats or layer.name not in attribute_stats or
field not in attribute_stats[layer.name]):
result = None
else:
result = attribute_stats[layer.name][field]

if result is not None:
logger.debug("Generating layer attribute statistics")
la.count = result['Count']
la.min = result['Min']
la.max = result['Max']
la.average = result['Average']
la.median = result['Median']
la.stddev = result['StandardDeviation']
la.sum = result['Sum']
la.unique_values = result['unique_values']
la.last_stats_updated = datetime.datetime.now()
la.visible = ftype.find("gml:") != 0
la.display_order = iter
la.save()
iter += 1
logger.debug(
"Created [%s] attribute for [%s]",
field,
layer.name.encode('utf-8'))
else:
logger.debug("No attributes found")


class GeoNodePublishHandler(ImportHandlerMixin):
"""
Creates a GeoNode Layer from a layer in Geoserver.
Expand Down
104 changes: 104 additions & 0 deletions osgeo_importer/handlers/geonode/backward_compatibility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'''
Created on Nov 9, 2016
@author: jivan
'''
import datetime
import logging

from geonode.layers.models import Attribute


logger = logging.getLogger(__name__)

# The function set_attributes() is used in GeoNodePublishHandler.handle() .
# In case the user is using osgeo_importer with a version of GeoNode older than
# 2016-11-08, commit 005bd559ed97ace87b33d7abd3e84d3e307d4547, duplicate the
# GeoNode-independent set_attributes() here. If this duplicated code is still
# here after 2018-11-01, it should be removed and imports of set_attributes()
# should changed to import from geonode.utils instead of here.
try:
from geonode.utils import set_attributes
except ImportError:
set_attributes = None


def set_attributes_bw_compat(layer, attribute_map, overwrite=False, attribute_stats=None):
""" *layer*: a geonode.layers.models.Layer instance
*attribute_map*: a list of 2-lists specifying attribute names and types,
example: [ ['id', 'Integer'], ... ]
*overwrite*: replace existing attributes with new values if name/type matches.
*attribute_stats*: dictionary of return values from get_attribute_statistics(),
of the form to get values by referencing attribute_stats[<layer_name>][<field_name>].
"""
# we need 3 more items; description, attribute_label, and display_order
attribute_map_dict = {
'field': 0,
'ftype': 1,
'description': 2,
'label': 3,
'display_order': 4,
}
for attribute in attribute_map:
attribute.extend((None, None, 0))

attributes = layer.attribute_set.all()
# Delete existing attributes if they no longer exist in an updated layer
for la in attributes:
lafound = False
for attribute in attribute_map:
field, ftype, description, label, display_order = attribute
if field == la.attribute:
lafound = True
# store description and attribute_label in attribute_map
attribute[attribute_map_dict['description']] = la.description
attribute[attribute_map_dict['label']] = la.attribute_label
attribute[attribute_map_dict['display_order']] = la.display_order
if overwrite or not lafound:
logger.debug(
"Going to delete [%s] for [%s]",
la.attribute,
layer.name.encode('utf-8'))
la.delete()

# Add new layer attributes if they don't already exist
if attribute_map is not None:
iter = len(Attribute.objects.filter(layer=layer)) + 1
for attribute in attribute_map:
field, ftype, description, label, display_order = attribute
if field is not None:
la, created = Attribute.objects.get_or_create(
layer=layer, attribute=field, attribute_type=ftype,
description=description, attribute_label=label,
display_order=display_order)
if created:
if (not attribute_stats or layer.name not in attribute_stats or
field not in attribute_stats[layer.name]):
result = None
else:
result = attribute_stats[layer.name][field]

if result is not None:
logger.debug("Generating layer attribute statistics")
la.count = result['Count']
la.min = result['Min']
la.max = result['Max']
la.average = result['Average']
la.median = result['Median']
la.stddev = result['StandardDeviation']
la.sum = result['Sum']
la.unique_values = result['unique_values']
la.last_stats_updated = datetime.datetime.now()
la.visible = ftype.find("gml:") != 0
la.display_order = iter
la.save()
iter += 1
logger.debug(
"Created [%s] attribute for [%s]",
field,
layer.name.encode('utf-8'))
else:
logger.debug("No attributes found")

if set_attributes is None:
set_attributes = set_attributes_bw_compat
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'''
Created on Nov 9, 2016
@author: jivan
'''
import copy

from django.contrib.auth import get_user_model
from django.db.models import signals
from django.test import TestCase
from geonode.geoserver.signals import geoserver_post_save

from geonode.layers.models import Layer
from osgeo_importer.handlers.geonode.backward_compatibility import set_attributes_bw_compat as set_attributes


class TestSetAttributes(TestCase):
""" This is copied & modified from geonode.tests.utils.
@see backward_compatibility for details.
"""
def setUp(self):
# Load users to log in as
# call_command('loaddata', 'people_data', verbosity=0)
User = get_user_model()
User.objects.create_superuser(username='norman', password='norman', email='')

def test_set_attributes_creates_attributes(self):
""" Test utility function set_attributes() which creates Attribute instances attached
to a Layer instance.
"""
# Creating a layer requires being logged in
self.client.login(username='norman', password='norman')

# Disconnect the geoserver-specific post_save signal attached to Layer creation.
# The geoserver signal handler assumes things about the store where the Layer is placed.
# this is a workaround.
disconnected_post_save = signals.post_save.disconnect(geoserver_post_save, sender=Layer)

# Create dummy layer to attach attributes to
l = Layer.objects.create(name='dummy_layer')

# Reconnect the signal if it was disconnected
if disconnected_post_save:
signals.post_save.connect(geoserver_post_save, sender=Layer)

attribute_map = [
['id', 'Integer'],
['date', 'IntegerList'],
['enddate', 'Real'],
['date_as_date', 'xsd:dateTime'],
]

# attribute_map gets modified as a side-effect of the call to set_attributes()
expected_results = copy.deepcopy(attribute_map)

# set attributes for resource
set_attributes(l, attribute_map)

# 2 items in attribute_map should translate into 2 Attribute instances
self.assertEquals(l.attributes.count(), len(expected_results))

# The name and type should be set as provided by attribute map
for a in l.attributes:
self.assertIn([a.attribute, a.attribute_type], expected_results)

0 comments on commit c40c970

Please sign in to comment.