Skip to content

Commit

Permalink
[Fixes #4661] Replace Layer functionality incomplete/broken
Browse files Browse the repository at this point in the history
  • Loading branch information
afabiani committed Oct 31, 2019
1 parent c68389c commit a305f32
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 102 deletions.
19 changes: 19 additions & 0 deletions geonode/geoserver/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
#########################################################################
#
# Copyright (C) 2019 OSGeo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
84 changes: 84 additions & 0 deletions geonode/geoserver/tests/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
#########################################################################
#
# Copyright (C) 2019 OSGeo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
from geonode.tests.base import GeoNodeBaseTestSupport

import os
import gisdata

from geonode import geoserver
from geonode.decorators import on_ogc_backend

from geonode.layers.models import Layer
from geonode.layers.utils import file_upload
from geonode.layers.populate_layers_data import create_layer_data

import logging
logger = logging.getLogger(__name__)


class HelperTest(GeoNodeBaseTestSupport):

type = 'layer'

def setUp(self):
super(HelperTest, self).setUp()
self.user = 'admin'
self.passwd = 'admin'
create_layer_data()

@on_ogc_backend(geoserver.BACKEND_PACKAGE)
def test_replace_layer(self):
"""
Ensures the layer_style_manage route returns a 200.
"""
layer = Layer.objects.all()[0]
logger.debug(Layer.objects.all())
self.assertIsNotNone(layer)

logger.info("Attempting to replace a vector layer with a raster.")
filename = filename = os.path.join(
gisdata.GOOD_DATA,
'vector/san_andres_y_providencia_administrative.shp')
vector_layer = file_upload(filename)
self.assertTrue(vector_layer.is_vector())
filename = os.path.join(gisdata.GOOD_DATA, 'raster/test_grid.tif')
with self.\
assertRaisesRegexp(Exception, "You are attempting to replace a vector layer with a raster."):
file_upload(filename, layer=vector_layer, overwrite=True)

logger.info("Attempting to replace a raster layer with a vector.")
raster_layer = file_upload(filename)
self.assertFalse(raster_layer.is_vector())
filename = filename = os.path.join(
gisdata.GOOD_DATA,
'vector/san_andres_y_providencia_administrative.shp')
with self.\
assertRaisesRegexp(Exception, "You are attempting to replace a raster layer with a vector."):
file_upload(filename, layer=raster_layer, overwrite=True)

logger.info("Attempting to replace a layer with no geometry type.")
with self.\
assertRaisesRegexp(Exception, "Local GeoNode layer has no geometry type."):
replaced = file_upload(filename, layer=vector_layer, overwrite=True)

logger.info("Attempting to replace a vector layer.")
replaced = file_upload(filename, layer=vector_layer, overwrite=True, gtype='LineString')
self.assertIsNotNone(replaced)
self.assertTrue(replaced.is_vector())
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#########################################################################
#
# Copyright (C) 2016 OSGeo
# Copyright (C) 2019 OSGeo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -17,7 +17,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################

from geonode.tests.base import GeoNodeBaseTestSupport

import base64
Expand Down Expand Up @@ -940,7 +939,7 @@ def test_ogc_server_defaults(self):
# Testing OWS endpoints
from urlparse import urljoin
from django.core.urlresolvers import reverse
from .ows import _wcs_get_capabilities, _wfs_get_capabilities, _wms_get_capabilities
from ..ows import _wcs_get_capabilities, _wfs_get_capabilities, _wms_get_capabilities
wcs = _wcs_get_capabilities()
logger.debug(wcs)
self.assertIsNotNone(wcs)
Expand Down
10 changes: 2 additions & 8 deletions geonode/geoserver/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,9 @@ def geoserver_upload(

# Get the helper files if they exist
files = get_files(base_file)

data = files

if 'shp' not in files:
data = base_file

try:
store, gs_resource = create_store_and_resource(name,
data,
Expand Down Expand Up @@ -180,7 +177,6 @@ def geoserver_upload(
assert gs_resource.name == name

# Step 6. Make sure our data always has a valid projection
# FIXME: Put this in gsconfig.py
logger.info('>>> Step 6. Making sure [%s] has a valid projection' % name)
_native_bbox = None
try:
Expand Down Expand Up @@ -210,7 +206,6 @@ def geoserver_upload(
logger.exception('Error occurred while trying to force BBOX on resource', e)

# Step 7. Create the style and assign it to the created resource
# FIXME: Put this in gsconfig.py
logger.info('>>> Step 7. Creating style for [%s]' % name)
cat.save(gs_resource)
publishing = cat.get_layer(name) or gs_resource
Expand Down Expand Up @@ -282,9 +277,8 @@ def geoserver_upload(
e.args = (msg,)
logger.exception(e)

# Step 10. Create the Django record for the layer
logger.info('>>> Step 10. Creating Django record for [%s]', name)
# FIXME: Do this inside the layer object
# Step 8. Create the Django record for the layer
logger.info('>>> Step 8. Creating Django record for [%s]', name)
alternate = workspace.name + ':' + gs_resource.name
layer_uuid = str(uuid.uuid1())

Expand Down
87 changes: 67 additions & 20 deletions geonode/layers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,27 @@
import os
import glob
import sys
import json
import logging
import tarfile

from osgeo import gdal, osr
from itertools import islice
from datetime import datetime
from urlparse import urlparse
from osgeo import gdal, osr, ogr
from zipfile import ZipFile, is_zipfile
from datetime import datetime

# Django functionality
from django.conf import settings
from django.db.models import Q
from django.db import transaction
from django.core.files import File
from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model
from django.template.defaultfilters import slugify
from django.core.exceptions import ObjectDoesNotExist
from django.core.files.storage import default_storage as storage
from django.core.files import File
from django.conf import settings
from django.db import transaction
from django.utils.translation import ugettext as _

# Geonode functionality
from geonode.maps.models import Map
Expand All @@ -53,13 +58,12 @@
TopicCategory, Region, License, ResourceBase
from geonode.layers.models import shp_exts, csv_exts, vec_exts, cov_exts, Layer
from geonode.layers.metadata import set_metadata
from geonode.upload.utils import _fixup_base_file
from geonode.utils import (http_client,
check_ogc_backend,
unzip_file,
extract_tarfile,
bbox_to_projection)
from django.contrib.auth.models import Group
from django.db.models import Q

READ_PERMISSIONS = [
'view_resourcebase'
Expand Down Expand Up @@ -444,6 +448,8 @@ def get_bbox(filename):


def file_upload(filename,
layer=None,
gtype=None,
name=None,
user=None,
title=None,
Expand Down Expand Up @@ -478,7 +484,60 @@ def file_upload(filename,
upload_session = UploadSession.objects.create(user=theuser)

# Get all the files uploaded with the layer
files = get_files(filename)
if os.path.exists(filename):
files = get_files(filename)
else:
raise Exception(
_("You are attempting to replace a vector layer with an unknown format."))

# We are going to replace an existing Layer...
if layer and overwrite:
if layer.is_vector() and is_raster(filename):
raise Exception(_(
"You are attempting to replace a vector layer with a raster."))
elif (not layer.is_vector()) and is_vector(filename):
raise Exception(_(
"You are attempting to replace a raster layer with a vector."))

if layer.is_vector():
absolute_base_file = None
try:
if 'shp' in files and os.path.exists(files['shp']):
absolute_base_file = _fixup_base_file(files['shp'])
elif 'zip' in files and os.path.exists(files['zip']):
absolute_base_file = _fixup_base_file(files['zip'])
except BaseException:
absolute_base_file = None

if not absolute_base_file or \
os.path.splitext(absolute_base_file)[1].lower() != '.shp':
raise Exception(
_("You are attempting to replace a vector layer with an unknown format."))
else:
try:
gtype = layer.gtype if not gtype else gtype
inDataSource = ogr.Open(absolute_base_file)
lyr = inDataSource.GetLayer(str(layer.name))
if not lyr:
raise Exception(
_("You are attempting to replace a vector layer with an incompatible source."))
limit = 1
schema_is_compliant = False
for feat in islice(lyr, 0, limit):
_ff = json.loads(feat.ExportToJson())
if not gtype:
raise Exception(
_("Local GeoNode layer has no geometry type."))
if _ff["geometry"]["type"] in gtype or \
gtype in _ff["geometry"]["type"]:
schema_is_compliant = True
break
if not schema_is_compliant:
raise Exception(
_("You are attempting to replace a vector layer with an incompatible schema."))
except BaseException as e:
raise Exception(
_("Some error occurred while trying to access the uploaded schema: %s" % str(e)))

# Set a default title that looks nice ...
if title is None:
Expand Down Expand Up @@ -565,15 +624,13 @@ def file_upload(filename,
xml_file = f.read()

defaults['metadata_uploaded'] = True

defaults['metadata_uploaded_preserve'] = metadata_uploaded_preserve

# get model properties from XML
identifier, vals, regions, keywords = set_metadata(xml_file)

if defaults['metadata_uploaded_preserve']:
defaults['metadata_xml'] = xml_file

defaults['uuid'] = identifier

for key, value in vals.items():
Expand Down Expand Up @@ -632,27 +689,17 @@ def file_upload(filename,
if not created and overwrite:
# update with new information
defaults['upload_session'] = upload_session

defaults['title'] = defaults.get('title', None) or layer.title

defaults['abstract'] = defaults.get('abstract', None) or layer.abstract

defaults['bbox_x0'] = defaults.get('bbox_x0', None) or layer.bbox_x0

defaults['bbox_x1'] = defaults.get('bbox_x1', None) or layer.bbox_x1

defaults['bbox_y0'] = defaults.get('bbox_y0', None) or layer.bbox_y0

defaults['bbox_y1'] = defaults.get('bbox_y1', None) or layer.bbox_y1

defaults['is_approved'] = defaults.get(
'is_approved', is_approved) or layer.is_approved

defaults['is_published'] = defaults.get(
'is_published', is_published) or layer.is_published

defaults['license'] = defaults.get('license', None) or layer.license

defaults['category'] = defaults.get('category', None) or layer.category

try:
Expand Down
Loading

0 comments on commit a305f32

Please sign in to comment.