diff --git a/.travis.yml b/.travis.yml
index f45510c7..84be7c79 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -70,10 +70,9 @@ deploy:
on:
tags: true
all_branches: true
- condition: $TRAVIS_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+
+ condition: $TRAVIS_TAG =~ ^v([0-9]+\.?){2,3}(b[0-9]+|rc[0-9]+){0,1}
notifications:
email:
- hisham.karam@cartologic.com
- - hishamwaleedkaram@gmail.com
- ahmednosman@cartologic.com
- ahmedNourElDeen@cartologic.com
diff --git a/Dockerfile b/Dockerfile
index aa2677d8..72217d0e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,40 +1,18 @@
-FROM ubuntu:16.04
+FROM python:2.7-slim
LABEL "MAINTAINER"="Cartologic Development Team"
-ENV TERM xterm
-RUN apt-get update
-RUN apt-get install locales -y
-RUN locale-gen en_US.UTF-8 && update-locale
-ENV LANG en_US.UTF-8
-ENV LANGUAGE en_US:en
-ENV LC_ALL en_US.UTF-8
-RUN apt-get install software-properties-common python-software-properties -y
-RUN add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
-RUN apt-get update
-RUN apt-get upgrade -y
-RUN apt-get update && apt-get install -y \
- gcc gettext \
- python-pip libpq-dev \
- sqlite3 git gdal-bin lsof psmisc \
- python-gdal python-psycopg2 \
- python-imaging python-lxml \
- python-dev libgdal-dev libgeoip-dev \
- python-ldap libxml2 libxml2-dev libxslt-dev \
- libmemcached-dev libsasl2-dev zlib1g-dev \
- python-pylibmc python-setuptools \
- curl build-essential build-essential python-dev \
- --no-install-recommends
-RUN mkdir /code
-WORKDIR /code
-RUN pip install --upgrade pip
-RUN pip install --ignore-installed geoip django-geonode-client \
- geonode==2.8rc11 django-jsonfield django-jsonfield-compat \
- cartoview==1.8.3 cherrypy==11.0.0 cheroot==5.8.3 \
- django-autocomplete-light==2.3.3 --no-cache-dir
-RUN pip install git+https://github.com/GeoNode/django-osgeo-importer.git
-RUN apt autoremove --purge -y && apt autoclean -y
-RUN rm -rf ~/.cache/pip
-RUN rm -rf /var/lib/apt/lists/* && apt-get clean && \
- rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-RUN echo "Yes, do as I say!" | apt-get remove --force-yes login \
- && dpkg --remove --force-depends wget unzip
+ENV PYTHONUNBUFFERED 1
+ARG GEONODE_DEV=true
+ARG GEONODE_SHA1=992daf724e83cdb0c1eb776d147eba841ad02cd9
+ARG APP_DIR=/usr/src/carto_app
+# include GDAL HEADER Files
+# CPATH specifies a list of directories to be searched as if specified with -I,
+# but after any paths given with -I options on the command line.
+# This environment variable is used regardless of which language is being preprocessed.
+ENV CPATH "$CPATH:/usr/include/gdal:/usr/include"
+COPY scripts/docker/setup.sh ./
+COPY . /cartoview
+RUN chmod +x setup.sh
+RUN ./setup.sh
+# switch to project dir
+WORKDIR ${APP_DIR}
CMD ["/bin/bash"]
diff --git a/README.md b/README.md
index a372c2f3..12df7d74 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,9 @@
+| WARNING: be careful this version(1.10.x) of Cartoview is compatibile with geonode 2.10.x only,if you want to install another version please take alook on [this section](https://github.com/cartologic/cartoview/blob/hisham-dev/README.md#previous-versions) |
+| --- |
+
---
## What is Cartoview?
- CartoView is a GIS Web Mapping Application Market.
@@ -43,7 +46,7 @@
## How To Add Cartoview To Existing Geonode:
- install cartoview with pip:
- - `pip install cartoview==1.8.5 --no-cache-dir`
+ - `pip install cartoview --no-cache-dir`
- open geonode `settings.py` and add the following lines at the end of the file:
```python
from cartoview import settings as cartoview_settings
@@ -84,3 +87,9 @@
```sh
paver run_test
```
+ ___
+# Previous Versions
+| Cartoview Version | Geonode Version | docs Link |
+|-------------------|-----------------|---------------------------------------------------------------------------------|
+| 1.8.x | 2.8.x | [Here](https://github.com/cartologic/cartoview/blob/1.8.x/README.md) |
+| 1.6.x | 2.6.x | [Here](https://github.com/cartologic/cartoview/blob/2.6.x_compatible/README.md) |
diff --git a/cartoview/__init__.py b/cartoview/__init__.py
index ad89171e..7099e15c 100644
--- a/cartoview/__init__.py
+++ b/cartoview/__init__.py
@@ -1,4 +1,4 @@
-__version__ = (1, 8, 6, 'unstable', 0)
+__version__ = (1, 10, 0, 'beta', 0)
__compatible_with__ = []
diff --git a/cartoview/app_manager/decorators.py b/cartoview/app_manager/decorators.py
index 43ad3cb1..6e233b28 100644
--- a/cartoview/app_manager/decorators.py
+++ b/cartoview/app_manager/decorators.py
@@ -1,7 +1,9 @@
-from .utils import resolve_appinstance
from django.conf import settings
from django.utils.translation import ugettext as _
+from .exceptions import AppAlreadyInstalledException
+from .utils import resolve_appinstance
+
PERMISSION_MSG_DELETE = _("You are not permitted to delete this Instance")
PERMISSION_MSG_GENERIC = _("You do not have permissions for this Instance.")
PERMISSION_MSG_MODIFY = _("You are not permitted to modify this Instance")
@@ -40,9 +42,6 @@ def restart_enabled(func):
def wrap(*args, **kwargs):
if not getattr(settings, "CARTOVIEW_TEST", False):
return func(*args, **kwargs)
- else:
- pass
-
return wrap
@@ -52,8 +51,9 @@ def wrap(*args, **kwargs):
try:
return func(*args, **kwargs)
except BaseException as e:
- if hasattr(this, '_rollback'):
- this._rollback()
- raise e
+ if not isinstance(e, AppAlreadyInstalledException):
+ if hasattr(this, '_rollback'):
+ this._rollback()
+ raise e
return wrap
diff --git a/cartoview/app_manager/exceptions.py b/cartoview/app_manager/exceptions.py
new file mode 100644
index 00000000..88479836
--- /dev/null
+++ b/cartoview/app_manager/exceptions.py
@@ -0,0 +1,2 @@
+class AppAlreadyInstalledException(BaseException):
+ message = "Application is already installed."
diff --git a/cartoview/app_manager/installer.py b/cartoview/app_manager/installer.py
index 8951a471..a8f0d78d 100644
--- a/cartoview/app_manager/installer.py
+++ b/cartoview/app_manager/installer.py
@@ -10,7 +10,6 @@
import threading
import zipfile
from io import BytesIO
-from os import R_OK, access
from sys import executable, exit
from threading import Timer
@@ -25,9 +24,12 @@
from cartoview.log_handler import get_logger
from cartoview.store_api.api import StoreAppResource, StoreAppVersion
+from ..apps_handler.req_installer import (ReqFileException,
+ ReqFilePermissionException,
+ ReqInstaller)
from .decorators import restart_enabled, rollback_on_failure
+from .exceptions import AppAlreadyInstalledException
from .models import App, AppStore, AppType
-from .req_installer import ReqInstaller
logger = get_logger(__name__)
install_app_batch = getattr(settings, 'INSTALL_APP_BAT', None)
@@ -118,10 +120,6 @@ def get_property_value(self, p):
return getattr(self, p, None)
-class AppAlreadyInstalledException(BaseException):
- message = "Application is already installed."
-
-
class AppInstaller(object):
def __init__(self, name, store_id=None, version=None, user=None):
self.user = user
@@ -277,12 +275,14 @@ def install(self, restart=True):
@rollback_on_failure
def _install_requirements(self):
- # TODO:add requirement file name as settings var
- req_file = os.path.join(self.app_dir, "req.txt")
- libs_dir = os.path.join(self.app_dir, "libs")
- if os.path.exists(req_file) and access(req_file, R_OK):
- req_installer = ReqInstaller(req_file, target=libs_dir)
+ try:
+ libs_dir = os.path.join(self.app_dir, 'libs')
+ req_installer = ReqInstaller(self.app_dir, target=libs_dir)
req_installer.install_all()
+ except BaseException as e:
+ if not (isinstance(e, ReqFileException) or
+ isinstance(e, ReqFilePermissionException)):
+ raise e
@rollback_on_failure
def check_then_finlize(self, restart, installed_apps):
diff --git a/cartoview/app_manager/management/commands/install_app.py b/cartoview/app_manager/management/commands/install_app.py
index ad8be793..98c71aa2 100644
--- a/cartoview/app_manager/management/commands/install_app.py
+++ b/cartoview/app_manager/management/commands/install_app.py
@@ -2,6 +2,7 @@
from __future__ import print_function
from django.core.management.base import BaseCommand
+from pkg_resources import parse_version
from cartoview.app_manager.installer import AppInstaller
from cartoview.app_manager.models import App, AppStore
@@ -10,6 +11,10 @@
logger = get_logger(__name__)
+def compare_version(v1, v2):
+ return parse_version(v1) < parse_version(v2)
+
+
class Command(BaseCommand):
help = 'Install App'
@@ -29,8 +34,9 @@ def handle(self, *args, **options):
store = AppStore.objects.get(is_default=True)
q = App.objects.filter(name=app_name)
try:
- if q.count() == 0 or (q.first()
- and q.first().version < app_version):
+ if q.count() == 0 or (q.first() and
+ compare_version(q.first().version,
+ app_version)):
installer = AppInstaller(app_name, store.id, app_version)
installer.install()
except Exception as ex:
diff --git a/cartoview/app_manager/management/commands/update_current_apps.py b/cartoview/app_manager/management/commands/update_current_apps.py
index 853732c8..6349cdcc 100644
--- a/cartoview/app_manager/management/commands/update_current_apps.py
+++ b/cartoview/app_manager/management/commands/update_current_apps.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
import requests
from cartoview.app_manager.installer import AppJson, remove_unwanted
from cartoview.app_manager.models import App
diff --git a/cartoview/app_manager/migrations/0010_auto_20181118_1333.py b/cartoview/app_manager/migrations/0010_auto_20181118_1333.py
new file mode 100644
index 00000000..a26727da
--- /dev/null
+++ b/cartoview/app_manager/migrations/0010_auto_20181118_1333.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.16 on 2018-11-18 13:33
+from __future__ import unicode_literals
+
+from django.db import migrations
+import django.db.models.manager
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('app_manager', '0009_auto_20180920_1659'),
+ ]
+
+ operations = [
+ migrations.AlterModelManagers(
+ name='appinstance',
+ managers=[
+ ('objects', django.db.models.manager.Manager()),
+ ('base_objects', django.db.models.manager.Manager()),
+ ],
+ ),
+ migrations.RenameField(
+ model_name='appinstance',
+ old_name='map',
+ new_name='related_map',
+ ),
+ ]
diff --git a/cartoview/app_manager/models.py b/cartoview/app_manager/models.py
index 1f50abd7..9f26685e 100644
--- a/cartoview/app_manager/models.py
+++ b/cartoview/app_manager/models.py
@@ -136,6 +136,7 @@ def get_app_logo_path(instance, filename):
])
+@python_2_unicode_compatible
class AppInstance(ResourceBase):
"""
An App Instance is any kind of App Instance that can be created
@@ -146,7 +147,7 @@ class AppInstance(ResourceBase):
app = models.ForeignKey(
App, null=True, blank=True, on_delete=models.CASCADE)
config = models.TextField(null=True, blank=True)
- map = models.ForeignKey(
+ related_map = models.ForeignKey(
GeonodeMap, null=True, blank=True, on_delete=models.CASCADE)
logo = models.ImageField(
upload_to=get_app_logo_path, blank=True, null=True)
@@ -154,6 +155,9 @@ class AppInstance(ResourceBase):
def get_absolute_url(self):
return reverse('appinstance_detail', args=(self.id, ))
+ def __str__(self):
+ return self.title
+
@property
def name_long(self):
if not self.title:
@@ -161,6 +165,24 @@ def name_long(self):
else:
return '%s (%s)' % (self.title, self.id)
+ # NOTE:backward compatibility for old map field use by apps \
+ # in StandardAppViews
+ @property
+ def map_id(self):
+ return self.related_map_id
+
+ @map_id.setter
+ def map_id(self, value):
+ self.related_map_id = value
+
+ @property
+ def map(self):
+ return self.related_map
+
+ @map.setter
+ def map(self, value):
+ self.rerelated_map = value
+
@property
def config_obj(self):
try:
diff --git a/cartoview/app_manager/req_installer.py b/cartoview/app_manager/req_installer.py
deleted file mode 100644
index 42a5fbbd..00000000
--- a/cartoview/app_manager/req_installer.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-import os
-from os import R_OK, access
-
-
-class ReqFileException(Exception):
- message = "requirement file doesn't exists!"
-
-
-class ReqFilePermissionException(Exception):
- message = "can not read requirement file!"
-
-
-class ReqInstaller(object):
- def __init__(self, reqfile, target=None):
- if not os.path.exists(reqfile):
- raise ReqFileException()
- if not access(reqfile, R_OK):
- raise ReqFilePermissionException()
- self.file = reqfile
- self.requirements = []
- self.target = target
-
- def install_all(self, *args, **kwargs):
- from subprocess import call
- command = ["pip", "install", "-r", self.file]
- if self.target:
- command.extend(["-t", self.target])
- call(command)
diff --git a/cartoview/app_manager/rest.py b/cartoview/app_manager/rest.py
index 8aeca15a..928ce427 100644
--- a/cartoview/app_manager/rest.py
+++ b/cartoview/app_manager/rest.py
@@ -10,13 +10,6 @@
from django.core.urlresolvers import reverse
from django.db import transaction
from future import standard_library
-from geonode.api.api import ProfileResource
-from geonode.api.authorization import GeoNodeAuthorization
-from geonode.api.resourcebase_api import (CommonMetaApi, LayerResource,
- MapResource)
-from geonode.layers.models import Attribute
-from geonode.maps.models import MapLayer
-from geonode.people.models import Profile
from guardian.shortcuts import get_objects_for_user
from taggit.models import Tag
from tastypie import fields, http
@@ -27,6 +20,12 @@
from cartoview.app_manager.models import App, AppInstance, AppStore, AppType
from cartoview.apps_handler.handlers import CartoApps
from cartoview.log_handler import get_logger
+from geonode.api.api import ProfileResource
+from geonode.api.authorization import GeoNodeAuthorization
+from geonode.api.resourcebase_api import (CommonMetaApi, LayerResource,
+ MapResource)
+from geonode.maps.models import MapLayer
+from geonode.people.models import Profile
from .installer import AppInstaller, RestartHelper
from .resources import FileUploadResource
@@ -54,7 +53,8 @@ def build_filters(self, filters=None, **kwargs):
return orm_filters
def apply_filters(self, request, applicable_filters):
- permission = applicable_filters.pop('permission', None)
+ permission = applicable_filters.pop(
+ 'permission', None)
# NOTE: We change this filter name from type to geom_type because it
# overrides geonode type filter(vector,raster)
layer_geom_type = applicable_filters.pop('geom_type', None)
@@ -62,18 +62,17 @@ def apply_filters(self, request, applicable_filters):
request, applicable_filters)
if layer_geom_type:
filtered = filtered.filter(
- attribute_set__in=Attribute.objects.filter(
- attribute_type__icontains=layer_geom_type))
+ attribute_set__attribute_type__icontains=layer_geom_type)
if permission is not None:
- filtered = get_objects_for_user(
- request.user, permission, klass=filtered)
+ permitted_ids = get_objects_for_user(
+ request.user, permission, klass=filtered).values('id')
+ filtered = filtered.filter(id__in=permitted_ids)
return filtered
class Meta(LayerResource.Meta):
resource_name = "layers"
- filtering = dict(LayerResource.Meta.filtering.items() +
- {'typename': ALL}.items())
+ filtering = dict(LayerResource.Meta.filtering, **dict(typename=ALL))
class GeonodeMapLayerResource(ModelResource):
@@ -294,7 +293,7 @@ class AppInstanceResource(ModelResource):
launch_app_url = fields.CharField(null=True, blank=True)
edit_url = fields.CharField(null=True, blank=True)
app = fields.ForeignKey(AppResource, 'app', full=True, null=True)
- map = fields.ForeignKey(MapResource, 'map', full=True, null=True)
+ map = fields.ForeignKey(MapResource, 'related_map', full=True, null=True)
owner = fields.ForeignKey(
ProfileResource, 'owner', full=True, null=True, blank=True)
keywords = fields.ListField(null=True, blank=True)
diff --git a/cartoview/app_manager/settings.py b/cartoview/app_manager/settings.py
index 8f85a066..980d102d 100644
--- a/cartoview/app_manager/settings.py
+++ b/cartoview/app_manager/settings.py
@@ -7,10 +7,6 @@
import sys
from future import standard_library
-from past.builtins import execfile
-
-from cartoview.apps_handler.handlers import CartoApps, apps_orm
-from cartoview.apps_handler.utils import create_apps_dir
from cartoview.log_handler import get_logger
logger = get_logger(__name__, with_formatter=True)
@@ -24,6 +20,8 @@
def load_apps(APPS_DIR):
+ from cartoview.apps_handler.utils import create_apps_dir
+ from cartoview.apps_handler.handlers import CartoApps, apps_orm
global CARTOVIEW_APPS
global APPS_SETTINGS
create_apps_dir(APPS_DIR)
@@ -49,7 +47,6 @@ def load_apps(APPS_DIR):
# circular imports.
app_settings_file = os.path.realpath(app_settings_file)
APPS_SETTINGS += (app_settings_file, )
- # execfile(app_settings_file)
if os.path.exists(libs_dir) and libs_dir not in sys.path:
logger.info("Install {} libs folder to the system.\n".format(
app.name))
diff --git a/cartoview/app_manager/templates/app_instance/_resourcebase_snippet.html b/cartoview/app_manager/templates/app_instance/_resourcebase_snippet.html
index 85e32808..7a6d8d72 100644
--- a/cartoview/app_manager/templates/app_instance/_resourcebase_snippet.html
+++ b/cartoview/app_manager/templates/app_instance/_resourcebase_snippet.html
@@ -27,13 +27,13 @@