Example #1
0
def check_new_version(myversion, version_url):
    """Compares current web2py's version with the latest stable web2py version.

    Args:
        myversion: the current version as stored in file `web2py/VERSION`
        version_URL: the URL that contains the version
                     of the latest stable release

    Returns:
        tuple: state, version

        - state : `True` if upgrade available, `False` if current
          version is up-to-date, -1 on error
        - version : the most up-to-version available

    """
    try:
        from urllib import urlopen
        version = urlopen(version_url).read()
        pversion = parse_version(version)
        pmyversion = parse_version(myversion)
    except IOError:
        import traceback
        print traceback.format_exc()
        return -1, myversion

    if pversion[:3]+pversion[-6:] > pmyversion[:3]+pmyversion[-6:]:
        return True, version
    else:
        return False, version
Example #2
0
def check_new_version(myversion, version_url):
    """Compares current web2py's version with the latest stable web2py version.

    Args:
        myversion: the current version as stored in file `web2py/VERSION`
        version_URL: the URL that contains the version
                     of the latest stable release

    Returns:
        tuple: state, version

        - state : `True` if upgrade available, `False` if current
          version is up-to-date, -1 on error
        - version : the most up-to-version available

    """
    try:
        from urllib import urlopen
        version = urlopen(version_url).read()
        pversion = parse_version(version)
        pmyversion = parse_version(myversion)
    except IOError:
        import traceback
        print traceback.format_exc()
        return -1, myversion

    if pversion[:3] + pversion[-6:] > pmyversion[:3] + pmyversion[-6:]:
        return True, version
    else:
        return False, version
Example #3
0
 def test_parse_version(self):
     # Legacy
     rtn = parse_version('Version 1.99.0 (2011-09-19 08:23:26)')
     self.assertEqual(rtn, (1, 99, 0, 'dev', datetime.datetime(2011, 9, 19, 8, 23, 26)))
     # Semantic
     rtn = parse_version('Version 1.99.0-rc.1+timestamp.2011.09.19.08.23.26')
     self.assertEqual(rtn, (1, 99, 0, 'rc.1', datetime.datetime(2011, 9, 19, 8, 23, 26)))
     # Semantic Stable
     rtn = parse_version('Version 2.9.11-stable+timestamp.2014.09.15.18.31.17')
     self.assertEqual(rtn, (2, 9, 11, 'stable', datetime.datetime(2014, 9, 15, 18, 31, 17)))
     # Semantic Beta
     rtn = parse_version('Version 2.14.1-beta+timestamp.2016.03.21.22.35.26')
     self.assertEqual(rtn, (2, 14, 1, 'beta', datetime.datetime(2016, 3, 21, 22, 35, 26)))
 def test_parse_version(self):
     # Legacy
     rtn = parse_version('Version 1.99.0 (2011-09-19 08:23:26)')
     self.assertEqual(rtn, (1, 99, 0, 'dev', datetime.datetime(2011, 9, 19, 8, 23, 26)))
     # Semantic
     rtn = parse_version('Version 1.99.0-rc.1+timestamp.2011.09.19.08.23.26')
     self.assertEqual(rtn, (1, 99, 0, 'rc.1', datetime.datetime(2011, 9, 19, 8, 23, 26)))
     # Semantic Stable
     rtn = parse_version('Version 2.9.11-stable+timestamp.2014.09.15.18.31.17')
     self.assertEqual(rtn, (2, 9, 11, 'stable', datetime.datetime(2014, 9, 15, 18, 31, 17)))
     # Semantic Beta
     rtn = parse_version('Version 2.14.1-beta+timestamp.2016.03.21.22.35.26')
     self.assertEqual(rtn, (2, 14, 1, 'beta', datetime.datetime(2016, 3, 21, 22, 35, 26)))
Example #5
0
def version():
    if request.args(0) == 'raw':
        return request.env.web2py_version
    from gluon.fileutils import parse_version
    (a, b, c, pre_release, build) = parse_version(request.env.web2py_version)
    return 'Version %i.%i.%i (%.4i-%.2i-%.2i %.2i:%.2i:%.2i) %s' % \
           (a, b, c, build.year, build.month, build.day, build.hour, build.minute, build.second, pre_release)
Example #6
0
def version():
    if request.args(0) == 'raw':
        return request.env.web2py_version
    from gluon.fileutils import parse_version
    (a, b, c, pre_release, build) = parse_version(request.env.web2py_version)
    return 'Version %i.%i.%i (%.4i-%.2i-%.2i %.2i:%.2i:%.2i) %s' % \
           (a, b, c, build.year, build.month, build.day, build.hour, build.minute, build.second, pre_release)
Example #7
0
def check_new_version(myversion, version_url):
    """Compares current web2py's version with the latest stable web2py version.

    Args:
        myversion: the current version as stored in file `web2py/VERSION`
        version_URL: the URL that contains the version
                     of the latest stable release

    Returns:
        tuple: state, version

        - state : `True` if upgrade available, `False` if current
                  version is up-to-date, -1 on error,
                  -2 when the system is likely to be offline (no
                  internet link available)
        - version : the most up-to-version available

    """
    try:
        version = to_native(urlopen(version_url).read())
        pversion = parse_version(version)
        pmyversion = parse_version(myversion)
    except IOError as e:
        from socket import gaierror
        if isinstance(getattr(e, 'reason', None), gaierror) and \
            e.reason.errno == -2:
            # assuming the version_url is ok the socket.gaierror
            # (gaierror stands for getaddrinfo() error) that
            # originates the exception is probably due to a
            # missing internet link (i.e. the system is offline)
            print('system is offline, cannot retrieve latest web2py version')
            return -2, myversion
        else:
            print(traceback.format_exc())
            return -1, myversion

    if pversion[:3] + pversion[-6:] > pmyversion[:3] + pmyversion[-6:]:
        return True, version
    else:
        return False, version
Example #8
0
def update_check(environment):
    # Get Web2py environment into our globals.
    globals().update(**environment)

    import os
    app_path_parts = ["applications", request.application]
    app_path = os.path.join(*app_path_parts)

    # Fatal configuration errors.
    errors = []
    # Non-fatal warnings.
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries
    try:
        import dateutil
    except(ImportError):
        errors.append("S3 unresolved dependency: dateutil required for Sahana to run")
    try:
        import lxml
    except(ImportError):
        errors.append("S3XML unresolved dependency: lxml required for Sahana to run")
    try:
        import shapely
    except(ImportError):
        warnings.append("S3GIS unresolved dependency: shapely required for GIS support")
    try:
        import xlrd
    except(ImportError):
        warnings.append("S3XLS unresolved dependency: xlrd required for XLS export")
    try:
        import xlwt
    except(ImportError):
        warnings.append("S3XLS unresolved dependency: xlwt required for XLS export")
    try:
        from PIL import Image
    except(ImportError):
        try:
            import Image
        except(ImportError):
            warnings.append("S3PDF unresolved dependency: Python Imaging required for PDF export")
    try:
        import reportlab
    except(ImportError):
        warnings.append("S3PDF unresolved dependency: reportlab required for PDF export")
    try:
        import matplotlib
    except(ImportError):
        warnings.append("S3Chart unresolved dependency: matplotlib required for charting")
    try:
        import numpy
    except(ImportError):
        warnings.append("S3Cube unresolved dependency: numpy required for pivot table reports")
    try:
        import scipy
    except(ImportError):
        warnings.append("S3Cube unresolved dependency: scipy required for pivot table reports")
    try:
        import tweepy
    except(ImportError):
        warnings.append("S3Msg unresolved dependency: tweepy required for non-Tropo Twitter support")

    # -------------------------------------------------------------------------
    # Check Web2Py

    # Currently, the minimum usable Web2py is determined by the existence of
    # the global "current".
    try:
        from gluon import current
    except ImportError:
        errors.append(
            "The installed version of Web2py is too old -- it does not define current."
            "\nPlease upgrade Web2py to a more recent version.")

    web2py_minimum_version = "Version 1.99.2 (2011-09-26 00:51:34) stable"
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        web2py_minimum_datetime = parse_version(web2py_minimum_version)[3]
        web2py_installed_datetime = request.global_settings.web2py_version[3]
        web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to provide the Scheduler,"
            "\nso scheduled tasks will not be available. If you need scheduled tasks,"
            "\nplease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Copy in Templates
    template_src = os.path.join(app_path, "deployment-templates")
    template_dst = app_path

    template_files = (
        os.path.join("models", "000_config.py"),
        # Deprecated by Scheduler
        #"cron/crontab"
    )

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_src, t)
        dst_path = os.path.join(template_dst, t)
        try:
            os.stat(dst_path)
        except OSError:
            # not found, copy from template
            import shutil
            shutil.copy(src_path, dst_path)
            copied_from_template.append(t)
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # @ToDo: Check if it's up to date (i.e. a critical update requirement)
            #version_pattern = r"VERSION_\w*\s*=\s*([0-9]+)"
            #version_matcher = re.compile(version_pattern).match
            #has_version = False

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s" %
            ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #9
0
def update_check(settings):
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Load deployment_settings so that we can configure the update_check
               - need to rework so that 000_config.py is parsed 1st

        @param settings: the deployment_settings
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries
    try:
        import dateutil
    except ImportError:
        errors.append(
            "S3 unresolved dependency: dateutil required for Sahana to run")
    try:
        import lxml
    except ImportError:
        errors.append(
            "S3XML unresolved dependency: lxml required for Sahana to run")
    try:
        import shapely
    except ImportError:
        warnings.append(
            "S3GIS unresolved dependency: shapely required for GIS support")
    try:
        import xlrd
    except ImportError:
        warnings.append(
            "S3XLS unresolved dependency: xlrd required for XLS import")
    try:
        import xlwt
    except ImportError:
        warnings.append(
            "S3XLS unresolved dependency: xlwt required for XLS export")
    try:
        from PIL import Image
    except ImportError:
        try:
            import Image
        except ImportError:
            warnings.append(
                "S3PDF unresolved dependency: Python Imaging required for PDF export"
            )
    try:
        import reportlab
    except ImportError:
        warnings.append(
            "S3PDF unresolved dependency: reportlab required for PDF export")
    try:
        from osgeo import ogr
    except ImportError:
        warnings.append(
            "S3GIS unresolved dependency: GDAL required for Shapefile support")
    try:
        import numpy
    except ImportError:
        warnings.append(
            "Stats unresolved dependency: numpy required for Stats module support"
        )
    try:
        import tweepy
    except ImportError:
        warnings.append(
            "S3Msg unresolved dependency: tweepy required for non-Tropo Twitter support"
        )
    # @ToDo: Load settinmgs before running this
    #if settings.has_module("survey"):
    #    mandatory = True
    #else:
    #    mandatory = False
    try:
        import matplotlib
    except ImportError:
        msg = "S3Chart unresolved dependency: matplotlib required for charting in Survey module"
        #if mandatory:
        #    errors.append(msg)
        #else:
        warnings.append(msg)
    try:
        import PyRTF
    except ImportError:
        msg = "Survey unresolved dependency: PyRTF required if you want to export assessment/survey templates as a Word document"
        #if mandatory:
        #    errors.append(msg)
        #else:
        warnings.append(msg)
    # @ToDo: Load settings before running this
    # for now this is done in s3db.climate_first_run()
    if settings.has_module("climate"):
        if settings.get_database_type() != "postgres":
            errors.append("Climate unresolved dependency: PostgreSQL required")
        try:
            import rpy2
        except ImportError:
            errors.append("Climate unresolved dependency: RPy2 required")
        try:
            from Scientific.IO import NetCDF
        except ImportError:
            warnings.append(
                "Climate unresolved dependency: NetCDF required if you want to import readings"
            )
        try:
            from scipy import stats
        except ImportError:
            warnings.append(
                "Climate unresolved dependency: SciPy required if you want to generate graphs on the map"
            )

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # Currently, the minimum usable Web2py is determined by whether the
    # Scheduler is available
    web2py_minimum_version = "Version 1.99.3 (2011-10-27 13:23:13)"
    # Offset of datetime in return value of parse_version.
    datetime_index = 4
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        web2py_minimum_parsed = parse_version(web2py_minimum_version)
        web2py_minimum_datetime = web2py_minimum_parsed[datetime_index]
        # 2.4.2 & earlier style
        web2py_installed_datetime = request.global_settings.web2py_version[
            datetime_index]
        try:
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
        except:
            # Post 2.4.2
            web2py_installed_parsed = parse_version(
                request.global_settings.web2py_version)
            web2py_installed_datetime = web2py_installed_parsed[datetime_index]
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to provide the Scheduler,"
            "\nso scheduled tasks will not be available. If you need scheduled tasks,"
            "\nplease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    app_path = request.folder
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "private", "templates")

    template_files = {
        # source : destination
        "000_config.py": os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                input = open(src_path)
                output = open(dst_path, "w")
                for line in input:
                    if "akeytochange" in line:
                        # Generate a random hmac_key to secure the passwords in case
                        # the database is compromised
                        import uuid
                        hmac_key = uuid.uuid4()
                        line = 'deployment_settings.auth.hmac_key = "%s"' % hmac_key
                    output.write(line)
                output.close()
                input.close()
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])

            # @ToDo: WebSetup
            #  http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
            #if not os.path.exists("%s/applications/websetup" % os.getcwd()):
            #    # @ToDo: Check Permissions
            #    # Copy files into this folder (@ToDo: Pythonise)
            #    cp -r private/websetup "%s/applications" % os.getcwd()
            # Launch WebSetup
            #redirect(URL(a="websetup", c="default", f="index",
            #             vars=dict(appname=request.application,
            #                       firstTime="True")))
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s"
            % ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #10
0
def update_check(settings):
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Load deployment_settings so that we can configure the update_check
               - need to rework so that 000_config.py is parsed 1st

        @param settings: the deployment_settings
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries
    try:
        import dateutil
    except ImportError:
        errors.append("S3 unresolved dependency: dateutil required for Sahana to run")
    try:
        import lxml
    except ImportError:
        errors.append("S3XML unresolved dependency: lxml required for Sahana to run")
    try:
        import shapely
    except ImportError:
        warnings.append("S3GIS unresolved dependency: shapely required for GIS support")
    try:
        import xlrd
    except ImportError:
        warnings.append("S3XLS unresolved dependency: xlrd required for XLS import")
    try:
        import xlwt
    except ImportError:
        warnings.append("S3XLS unresolved dependency: xlwt required for XLS export")
    try:
        from PIL import Image
    except ImportError:
        try:
            import Image
        except ImportError:
            warnings.append("S3PDF unresolved dependency: Python Imaging required for PDF export")
    try:
        import reportlab
    except ImportError:
        warnings.append("S3PDF unresolved dependency: reportlab required for PDF export")
    try:
        from osgeo import ogr
    except ImportError:
        warnings.append("S3GIS unresolved dependency: GDAL required for Shapefile support")
    try:
        import numpy
    except ImportError:
        warnings.append("Stats unresolved dependency: numpy required for Stats module support")
    try:
        import tweepy
    except ImportError:
        warnings.append("S3Msg unresolved dependency: tweepy required for non-Tropo Twitter support")
    # @ToDo: Load settinmgs before running this
    #if settings.has_module("survey"):
    #    mandatory = True
    #else:
    #    mandatory = False
    try:
        import matplotlib
    except ImportError:
        msg = "S3Chart unresolved dependency: matplotlib required for charting in Survey module"
        #if mandatory:
        #    errors.append(msg)
        #else:
        warnings.append(msg)
    try:
        import PyRTF
    except ImportError:
        msg = "Survey unresolved dependency: PyRTF required if you want to export assessment/survey templates as a Word document"
        #if mandatory:
        #    errors.append(msg)
        #else:
        warnings.append(msg)
    # @ToDo: Load settings before running this
    # for now this is done in s3db.climate_first_run()
    if settings.has_module("climate"):
        if settings.get_database_type() != "postgres":
            errors.append("Climate unresolved dependency: PostgreSQL required")
        try:
           import rpy2
        except ImportError:
           errors.append("Climate unresolved dependency: RPy2 required")
        try:
           from Scientific.IO import NetCDF
        except ImportError:
           warnings.append("Climate unresolved dependency: NetCDF required if you want to import readings")
        try:
           from scipy import stats
        except ImportError:
           warnings.append("Climate unresolved dependency: SciPy required if you want to generate graphs on the map")

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # Currently, the minimum usable Web2py is determined by whether the
    # Scheduler is available
    web2py_minimum_version = "Version 1.99.3 (2011-10-27 13:23:13)"
    # Offset of datetime in return value of parse_version.
    datetime_index = 4
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        web2py_minimum_parsed = parse_version(web2py_minimum_version)
        web2py_minimum_datetime = web2py_minimum_parsed[datetime_index]
        # 2.4.2 & earlier style
        web2py_installed_datetime = request.global_settings.web2py_version[datetime_index]
        try:
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
        except:
            # Post 2.4.2
            web2py_installed_parsed = parse_version(request.global_settings.web2py_version)
            web2py_installed_datetime = web2py_installed_parsed[datetime_index]
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to provide the Scheduler,"
            "\nso scheduled tasks will not be available. If you need scheduled tasks,"
            "\nplease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    app_path = request.folder
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "private", "templates")

    template_files = {
        # source : destination
        "000_config.py" : os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                input = open(src_path)
                output = open(dst_path, "w")
                for line in input:
                    if "akeytochange" in line:
                        # Generate a random hmac_key to secure the passwords in case
                        # the database is compromised
                        import uuid
                        hmac_key = uuid.uuid4()
                        line = 'deployment_settings.auth.hmac_key = "%s"' % hmac_key
                    output.write(line)
                output.close()
                input.close()
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])

            # @ToDo: WebSetup
            #  http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
            #if not os.path.exists("%s/applications/websetup" % os.getcwd()):
            #    # @ToDo: Check Permissions
            #    # Copy files into this folder (@ToDo: Pythonise)
            #    cp -r private/websetup "%s/applications" % os.getcwd()
            # Launch WebSetup
            #redirect(URL(a="websetup", c="default", f="index",
            #             vars=dict(appname=request.application,
            #                       firstTime="True")))
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s" %
            ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #11
0
if not on_rtd:  # only import and set the theme if we're building docs locally
    import sphinx_rtd_theme
    html_theme = 'sphinx_rtd_theme'
    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('..'))
shutil.copy(os.path.join('..', 'VERSION'), 'VERSION')
from gluon.fileutils import parse_version
vfile = open('VERSION')
contents = vfile.read()
vfile.close()
version_tuple = parse_version(contents)
_version = "%s-%s" % ('.'.join(['%s' % a
                                for a in version_tuple[:3]]), version_tuple[3])
_release = _version
# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
    'sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.viewcode',
    'sphinxcontrib.napoleon'
]
Example #12
0
def update_check():
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Integrate into WebSetup:
               http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries
    try:
        import dateutil
    except(ImportError):
        errors.append("S3 unresolved dependency: dateutil required for Sahana to run")
    try:
        import lxml
    except(ImportError):
        errors.append("S3XML unresolved dependency: lxml required for Sahana to run")
    try:
        import shapely
    except(ImportError):
        warnings.append("S3GIS unresolved dependency: shapely required for GIS support")
    try:
        import xlrd
    except(ImportError):
        warnings.append("S3XLS unresolved dependency: xlrd required for XLS import")
    try:
        import xlwt
    except(ImportError):
        warnings.append("S3XLS unresolved dependency: xlwt required for XLS export")
    try:
        from PIL import Image
    except(ImportError):
        try:
            import Image
        except(ImportError):
            warnings.append("S3PDF unresolved dependency: Python Imaging required for PDF export")
    try:
        import reportlab
    except(ImportError):
        warnings.append("S3PDF unresolved dependency: reportlab required for PDF export")
    try:
        import matplotlib
    except(ImportError):
        warnings.append("S3Chart unresolved dependency: matplotlib required for charting")
    try:
        import numpy
    except(ImportError):
        warnings.append("S3Report unresolved dependency: numpy required for pivot table reports")
    try:
        import tweepy
    except(ImportError):
        warnings.append("S3Msg unresolved dependency: tweepy required for non-Tropo Twitter support")
    try:
        import PyRTF
    except(ImportError):
        warnings.append("Survey unresolved dependency: PyRTF required if you want to export assessment templates as a Word document")

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # Currently, the minimum usable Web2py is determined by whether the
    # Scheduler is available
    web2py_minimum_version = "Version 1.99.3 (2011-10-27 13:23:13)"
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        web2py_minimum_datetime = parse_version(web2py_minimum_version)[3]
        web2py_installed_datetime = request.global_settings.web2py_version[3]
        web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to provide the Scheduler,"
            "\nso scheduled tasks will not be available. If you need scheduled tasks,"
            "\nplease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    app_path = request.folder
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "private", "templates")

    template_files = {
        # source : destination
        "000_config.py" : os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                input = open(src_path)
                output = open(dst_path, "w")
                for line in input:
                    if "akeytochange" in line:
                        # Generate a random hmac_key to secure the passwords in case
                        # the database is compromised
                        import uuid
                        hmac_key = uuid.uuid4()
                        line = 'deployment_settings.auth.hmac_key = "%s"' % hmac_key
                    output.write(line)
                output.close()
                input.close()
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s" %
            ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #13
0
def update_check(settings):
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Load deployment_settings so that we can configure the update_check
               - need to rework so that 000_config.py is parsed 1st

        @param settings: the deployment_settings
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries

    # Get mandatory global dependencies
    app_path = request.folder

    gr_path = os.path.join(app_path, "requirements.txt")
    or_path = os.path.join(app_path, "optional_requirements.txt")

    global_dep = parse_requirements({}, gr_path)
    optional_dep = parse_requirements({}, or_path)

    templates = settings.get_template()
    location = settings.get_template_location()
    if not isinstance(templates, (tuple, list)):
        templates = (templates,)
    template_dep = {}
    template_optional_dep = {}
    for template in templates:
        tr_path = os.path.join(app_path, location, "templates", template, "requirements.txt")
        tor_path = os.path.join(app_path, location, "templates", template, "optional_requirements.txt")
        parse_requirements(template_dep, tr_path)
        parse_requirements(template_optional_dep, tor_path)

    # Remove optional dependencies which are already accounted for in template dependencies
    unique = set(optional_dep.keys()).difference(set(template_dep.keys()))
    for dependency in optional_dep.keys():
        if dependency not in unique:
            del optional_dep[dependency]

    # Override optional dependency messages from template
    unique = set(optional_dep.keys()).difference(set(template_optional_dep.keys()))
    for dependency in optional_dep.keys():
        if dependency not in unique:
            del optional_dep[dependency]

    errors, warnings = s3_check_python_lib(global_dep, template_dep, template_optional_dep, optional_dep)
    # @ToDo: Move these to Template
    # for now this is done in s3db.climate_first_run()
    if settings.has_module("climate"):
        if settings.get_database_type() != "postgres":
            errors.append("Climate unresolved dependency: PostgreSQL required")
        try:
           import rpy2
        except ImportError:
           errors.append("Climate unresolved dependency: RPy2 required")
        try:
           from Scientific.IO import NetCDF
        except ImportError:
           warnings.append("Climate unresolved dependency: NetCDF required if you want to import readings")
        try:
           from scipy import stats
        except ImportError:
           warnings.append("Climate unresolved dependency: SciPy required if you want to generate graphs on the map")

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # Currently, the minimum usable Web2py is determined by whether the
    # Scheduler is available
    web2py_minimum_version = "Version 2.4.7-stable+timestamp.2013.05.27.11.49.44"
    # Offset of datetime in return value of parse_version.
    datetime_index = 4
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        try:
            web2py_minimum_parsed = parse_version(web2py_minimum_version)
            web2py_minimum_datetime = web2py_minimum_parsed[datetime_index]
            version_info = open("VERSION", "r")
            web2py_installed_version = version_info.read().split()[-1].strip()
            version_info.close()
            if isinstance(web2py_installed_version, str):
                # Post 2.4.2, global_settings.web2py_version is unparsed
                web2py_installed_parsed = parse_version(web2py_installed_version)
                web2py_installed_datetime = web2py_installed_parsed[datetime_index]
            else:
                # 2.4.2 & earlier style
                web2py_installed_datetime = web2py_installed_version[datetime_index]
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
        except:
            # Will get AttributeError if Web2py's parse_version is too old for
            # its current version format, which changed in 2.3.2.
            web2py_version_ok = False
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to support the current version of Sahana Eden."
            "\nPlease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "modules", "templates")

    template_files = {
        # source : destination
        "000_config.py" : os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                input = open(src_path)
                output = open(dst_path, "w")
                for line in input:
                    if "akeytochange" in line:
                        # Generate a random hmac_key to secure the passwords in case
                        # the database is compromised
                        import uuid
                        hmac_key = uuid.uuid4()
                        line = 'settings.auth.hmac_key = "%s"' % hmac_key
                    output.write(line)
                output.close()
                input.close()
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])

            # @ToDo: WebSetup
            #  http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
            #if not os.path.exists("%s/applications/websetup" % os.getcwd()):
            #    # @ToDo: Check Permissions
            #    # Copy files into this folder (@ToDo: Pythonise)
            #    cp -r private/websetup "%s/applications" % os.getcwd()
            # Launch WebSetup
            #redirect(URL(a="websetup", c="default", f="index",
            #             vars=dict(appname=request.application,
            #                       firstTime="True")))
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s" %
            ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #14
0
def update_check(settings):
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Load deployment_settings so that we can configure the update_check
               - need to rework so that 000_config.py is parsed 1st

        @param settings: the deployment_settings
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries

    # Get mandatory global dependencies
    app_path = request.folder

    gr_path = os.path.join(app_path, "requirements.txt")
    or_path = os.path.join(app_path, "optional_requirements.txt")

    global_dep = parse_requirements({}, gr_path)
    optional_dep = parse_requirements({}, or_path)

    templates = settings.get_template()
    if not isinstance(templates, (tuple, list)):
        templates = (templates, )
    template_dep = {}
    template_optional_dep = {}
    for template in templates:
        tr_path = os.path.join(app_path, "modules", "templates", template,
                               "requirements.txt")
        parse_requirements(template_dep, tr_path)
        tor_path = os.path.join(app_path, "modules", "templates", template,
                                "optional_requirements.txt")
        parse_requirements(template_optional_dep, tor_path)

    # Drop optional dependencies that are already accounted for in template dependencies
    tr = set(template_dep.keys()) | set(template_optional_dep.keys())
    optional_dep = {k: optional_dep[k] for k in optional_dep if k not in tr}

    errors, warnings = s3_check_python_lib(global_dep, template_dep,
                                           template_optional_dep, optional_dep)

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # We require web2py-2.14.6 or later for PyDAL compatibility
    web2py_minimum_version = "Version 2.14.6-stable+timestamp.2016.05.09.19.18.48"
    # Offset of datetime in return value of parse_version.
    datetime_index = 4
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        try:
            web2py_minimum_parsed = parse_version(web2py_minimum_version)
            web2py_minimum_datetime = web2py_minimum_parsed[datetime_index]
            version_info = open("VERSION", "r")
            web2py_installed_version = version_info.read().split()[-1].strip()
            version_info.close()
            if isinstance(web2py_installed_version, str):
                # Post 2.4.2, global_settings.web2py_version is unparsed
                web2py_installed_parsed = parse_version(
                    web2py_installed_version)
                web2py_installed_datetime = web2py_installed_parsed[
                    datetime_index]
            else:
                # 2.4.2 & earlier style
                web2py_installed_datetime = web2py_installed_version[
                    datetime_index]
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
        except:
            # Will get AttributeError if Web2py's parse_version is too old for
            # its current version format, which changed in 2.3.2.
            web2py_version_ok = False
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to support the current version of Sahana Eden."
            "\nPlease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "modules", "templates")

    template_files = {
        # source: destination
        "000_config.py": os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                with open(src_path) as src:
                    with open(dst_path, "w") as dst:
                        for line in src:
                            if "akeytochange" in line:
                                # Generate a random hmac_key to secure the passwords in case
                                # the database is compromised
                                import uuid
                                hmac_key = uuid.uuid4()
                                line = 'settings.auth.hmac_key = "%s"' % hmac_key
                            dst.write(line)
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])

            # @ToDo: WebSetup
            #  http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
            #if not os.path.exists("%s/applications/websetup" % os.getcwd()):
            #    # @ToDo: Check Permissions
            #    # Copy files into this folder (@ToDo: Pythonise)
            #    cp -r private/websetup "%s/applications" % os.getcwd()
            # Launch WebSetup
            #redirect(URL(a="websetup", c="default", f="index",
            #             vars=dict(appname=request.application,
            #                       firstTime="True")))
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s"
            % ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #15
0
def update_check():
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Integrate into WebSetup:
               http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries
    try:
        import dateutil
    except (ImportError):
        errors.append(
            "S3 unresolved dependency: dateutil required for Sahana to run")
    try:
        import lxml
    except (ImportError):
        errors.append(
            "S3XML unresolved dependency: lxml required for Sahana to run")
    try:
        import shapely
    except (ImportError):
        warnings.append(
            "S3GIS unresolved dependency: shapely required for GIS support")
    try:
        import xlrd
    except (ImportError):
        warnings.append(
            "S3XLS unresolved dependency: xlrd required for XLS import")
    try:
        import xlwt
    except (ImportError):
        warnings.append(
            "S3XLS unresolved dependency: xlwt required for XLS export")
    try:
        from PIL import Image
    except (ImportError):
        try:
            import Image
        except (ImportError):
            warnings.append(
                "S3PDF unresolved dependency: Python Imaging required for PDF export"
            )
    try:
        import reportlab
    except (ImportError):
        warnings.append(
            "S3PDF unresolved dependency: reportlab required for PDF export")
    try:
        import matplotlib
    except (ImportError):
        warnings.append(
            "S3Chart unresolved dependency: matplotlib required for charting")
    try:
        import numpy
    except (ImportError):
        warnings.append(
            "S3Report unresolved dependency: numpy required for pivot table reports"
        )
    try:
        import tweepy
    except (ImportError):
        warnings.append(
            "S3Msg unresolved dependency: tweepy required for non-Tropo Twitter support"
        )
    try:
        import PyRTF
    except (ImportError):
        warnings.append(
            "Survey unresolved dependency: PyRTF required if you want to export assessment templates as a Word document"
        )

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # Currently, the minimum usable Web2py is determined by whether the
    # Scheduler is available
    web2py_minimum_version = "Version 1.99.3 (2011-10-27 13:23:13)"
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        web2py_minimum_datetime = parse_version(web2py_minimum_version)[3]
        web2py_installed_datetime = request.global_settings.web2py_version[3]
        web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to provide the Scheduler,"
            "\nso scheduled tasks will not be available. If you need scheduled tasks,"
            "\nplease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    app_path = request.folder
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "private", "templates")

    template_files = {
        # source : destination
        "000_config.py": os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                input = open(src_path)
                output = open(dst_path, "w")
                for line in input:
                    if "akeytochange" in line:
                        # Generate a random hmac_key to secure the passwords in case
                        # the database is compromised
                        import uuid
                        hmac_key = uuid.uuid4()
                        line = 'deployment_settings.auth.hmac_key = "%s"' % hmac_key
                    output.write(line)
                output.close()
                input.close()
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s"
            % ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #16
0
def update_check(settings):
    """
        Check whether the dependencies are sufficient to run Eden

        @ToDo: Load deployment_settings so that we can configure the update_check
               - need to rework so that 000_config.py is parsed 1st

        @param settings: the deployment_settings
    """

    # Get Web2py environment into our globals.
    #globals().update(**environment)
    request = current.request

    # Fatal errors
    errors = []
    # Non-fatal warnings
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries

    # Get mandatory global dependencies
    app_path = request.folder

    template = settings.get_template()
    location = settings.get_template_location()
    gr_path = os.path.join(app_path, "requirements.txt")
    tr_path = os.path.join(app_path, location, "templates", template,
                           "requirements.txt")
    or_path = os.path.join(app_path, "optional_requirements.txt")
    tor_path = os.path.join(app_path, location, "templates", template,
                            "optional_requirements.txt")

    global_dep = parse_requirements(gr_path)
    template_dep = parse_requirements(tr_path)
    optional_dep = parse_requirements(or_path)
    template_optional_dep = parse_requirements(tor_path)

    # remove optional dependencies which are already accounted for in template dependencies
    unique = set(optional_dep.keys()).difference(set(template_dep.keys()))
    for dependency in optional_dep.keys():
        if dependency not in unique:
            del optional_dep[dependency]

    # override optional dependency messages from template
    unique = set(optional_dep.keys()).difference(
        set(template_optional_dep.keys()))
    for dependency in optional_dep.keys():
        if dependency not in unique:
            del optional_dep[dependency]

    errors, warnings = s3_check_python_lib(global_dep, template_dep,
                                           template_optional_dep, optional_dep)
    # @ToDo: Move these to Template
    # for now this is done in s3db.climate_first_run()
    if settings.has_module("climate"):
        if settings.get_database_type() != "postgres":
            errors.append("Climate unresolved dependency: PostgreSQL required")
        try:
            import rpy2
        except ImportError:
            errors.append("Climate unresolved dependency: RPy2 required")
        try:
            from Scientific.IO import NetCDF
        except ImportError:
            warnings.append(
                "Climate unresolved dependency: NetCDF required if you want to import readings"
            )
        try:
            from scipy import stats
        except ImportError:
            warnings.append(
                "Climate unresolved dependency: SciPy required if you want to generate graphs on the map"
            )

    # -------------------------------------------------------------------------
    # Check Web2Py version
    #
    # Currently, the minimum usable Web2py is determined by whether the
    # Scheduler is available
    web2py_minimum_version = "Version 2.4.7-stable+timestamp.2013.05.27.11.49.44"
    # Offset of datetime in return value of parse_version.
    datetime_index = 4
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        try:
            web2py_minimum_parsed = parse_version(web2py_minimum_version)
            web2py_minimum_datetime = web2py_minimum_parsed[datetime_index]
            web2py_installed_version = request.global_settings.web2py_version
            if isinstance(web2py_installed_version, str):
                # Post 2.4.2, request.global_settings.web2py_version is unparsed
                web2py_installed_parsed = parse_version(
                    web2py_installed_version)
                web2py_installed_datetime = web2py_installed_parsed[
                    datetime_index]
            else:
                # 2.4.2 & earlier style
                web2py_installed_datetime = web2py_installed_version[
                    datetime_index]
            web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
        except:
            # Will get AttributeError if Web2py's parse_version is too old for
            # its current version format, which changed in 2.3.2.
            web2py_version_ok = False
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to support the current version of Sahana Eden."
            "\nPlease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Create required directories if needed
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    # - 000_config.py (machine-specific settings)
    # - rest are run in-place
    #
    template_folder = os.path.join(app_path, "modules", "templates")

    template_files = {
        # source : destination
        "000_config.py": os.path.join("models", "000_config.py"),
    }

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_folder, t)
        dst_path = os.path.join(app_path, template_files[t])
        try:
            os.stat(dst_path)
        except OSError:
            # Not found, copy from template
            if t == "000_config.py":
                input = open(src_path)
                output = open(dst_path, "w")
                for line in input:
                    if "akeytochange" in line:
                        # Generate a random hmac_key to secure the passwords in case
                        # the database is compromised
                        import uuid
                        hmac_key = uuid.uuid4()
                        line = 'settings.auth.hmac_key = "%s"' % hmac_key
                    output.write(line)
                output.close()
                input.close()
            else:
                import shutil
                shutil.copy(src_path, dst_path)
            copied_from_template.append(template_files[t])

            # @ToDo: WebSetup
            #  http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/WebSetup
            #if not os.path.exists("%s/applications/websetup" % os.getcwd()):
            #    # @ToDo: Check Permissions
            #    # Copy files into this folder (@ToDo: Pythonise)
            #    cp -r private/websetup "%s/applications" % os.getcwd()
            # Launch WebSetup
            #redirect(URL(a="websetup", c="default", f="index",
            #             vars=dict(appname=request.application,
            #                       firstTime="True")))
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # Check if it's up to date (i.e. a critical update requirement)
            version_pattern = r"VERSION =\s*([0-9]+)"
            version_matcher = re.compile(version_pattern).match
            has_version = False
            with open(dst_path) as f:
                for line in f:
                    version_result = version_matcher(line)
                    if version_result:
                        has_version = True
                        version = version_result.group(1)
                        break
            if not has_version:
                error = "Your %s is using settings from the old templates system. Please switch to the new templates system: http://eden.sahanafoundation.org/wiki/DeveloperGuidelines/Templates" % t
                errors.append(error)
            elif int(version) != VERSION:
                error = "Your %s is using settings from template version %s. Please update with new settings from template version %s before starting the system." % \
                                (t, version, VERSION)
                errors.append(error)

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s"
            % ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #17
0
def update_check(environment):
    # Get Web2py environment into our globals.
    globals().update(**environment)

    import os
    app_path_parts = ["applications", request.application]
    app_path = os.path.join(*app_path_parts)

    # Fatal configuration errors.
    errors = []
    # Non-fatal warnings.
    warnings = []

    # -------------------------------------------------------------------------
    # Check Python libraries
    try:
        import dateutil
    except (ImportError):
        errors.append(
            "S3 unresolved dependency: dateutil required for Sahana to run")
    try:
        import lxml
    except (ImportError):
        errors.append(
            "S3XML unresolved dependency: lxml required for Sahana to run")
    try:
        import shapely
    except (ImportError):
        warnings.append(
            "S3GIS unresolved dependency: shapely required for GIS support")
    try:
        import xlrd
    except (ImportError):
        warnings.append(
            "S3XLS unresolved dependency: xlrd required for XLS export")
    try:
        import xlwt
    except (ImportError):
        warnings.append(
            "S3XLS unresolved dependency: xlwt required for XLS export")
    try:
        from PIL import Image
    except (ImportError):
        try:
            import Image
        except (ImportError):
            warnings.append(
                "S3PDF unresolved dependency: Python Imaging required for PDF export"
            )
    try:
        import reportlab
    except (ImportError):
        warnings.append(
            "S3PDF unresolved dependency: reportlab required for PDF export")
    try:
        import matplotlib
    except (ImportError):
        warnings.append(
            "S3Chart unresolved dependency: matplotlib required for charting")
    try:
        import numpy
    except (ImportError):
        warnings.append(
            "S3Cube unresolved dependency: numpy required for pivot table reports"
        )
    try:
        import tweepy
    except (ImportError):
        warnings.append(
            "S3Msg unresolved dependency: tweepy required for non-Tropo Twitter support"
        )
    try:
        import PyRTF
    except (ImportError):
        warnings.append(
            "Survey unresolved dependency: PyRTF required if you want to export assessment templates as a Word document"
        )

    # -------------------------------------------------------------------------
    # Check Web2Py

    # Currently, the minimum usable Web2py is determined by the existence of
    # the global "current".
    try:
        from gluon import current
    except ImportError:
        errors.append(
            "The installed version of Web2py is too old -- it does not define current."
            "\nPlease upgrade Web2py to a more recent version.")

    web2py_minimum_version = "Version 1.99.2 (2011-09-26 00:51:34) stable"
    web2py_version_ok = True
    try:
        from gluon.fileutils import parse_version
    except ImportError:
        web2py_version_ok = False
    if web2py_version_ok:
        web2py_minimum_datetime = parse_version(web2py_minimum_version)[3]
        web2py_installed_datetime = request.global_settings.web2py_version[3]
        web2py_version_ok = web2py_installed_datetime >= web2py_minimum_datetime
    if not web2py_version_ok:
        warnings.append(
            "The installed version of Web2py is too old to provide the Scheduler,"
            "\nso scheduled tasks will not be available. If you need scheduled tasks,"
            "\nplease upgrade Web2py to at least version: %s" % \
            web2py_minimum_version)

    # -------------------------------------------------------------------------
    # Add required directories if needed
    databases_dir = os.path.join(app_path, "databases")
    try:
        os.stat(databases_dir)
    except OSError:
        # not found, create it
        os.mkdir(databases_dir)

    # -------------------------------------------------------------------------
    # Copy in Templates
    template_src = os.path.join(app_path, "deployment-templates")
    template_dst = app_path

    template_files = (
        os.path.join("models", "000_config.py"),
        # Deprecated by Scheduler
        #"cron/crontab"
    )

    copied_from_template = []

    for t in template_files:
        src_path = os.path.join(template_src, t)
        dst_path = os.path.join(template_dst, t)
        try:
            os.stat(dst_path)
        except OSError:
            # not found, copy from template
            import shutil
            shutil.copy(src_path, dst_path)
            copied_from_template.append(t)
        else:
            # Found the file in the destination
            # Check if it has been edited
            import re
            edited_pattern = r"FINISHED_EDITING_\w*\s*=\s*(True|False)"
            edited_matcher = re.compile(edited_pattern).match
            has_edited = False
            with open(dst_path) as f:
                for line in f:
                    edited_result = edited_matcher(line)
                    if edited_result:
                        has_edited = True
                        edited = edited_result.group(1)
                        break
            if has_edited and (edited != "True"):
                errors.append("Please edit %s before starting the system." % t)
            # @ToDo: Check if it's up to date (i.e. a critical update requirement)
            #version_pattern = r"VERSION_\w*\s*=\s*([0-9]+)"
            #version_matcher = re.compile(version_pattern).match
            #has_version = False

    if copied_from_template:
        errors.append(
            "The following files were copied from templates and should be edited: %s"
            % ", ".join(copied_from_template))

    return {"error_messages": errors, "warning_messages": warnings}
Example #18
0
if not on_rtd:  # only import and set the theme if we're building docs locally
    import sphinx_rtd_theme
    html_theme = 'sphinx_rtd_theme'
    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('..'))
shutil.copy(os.path.join('..', 'VERSION'), 'VERSION')
from gluon.fileutils import parse_version
vfile = open('VERSION')
contents = vfile.read()
vfile.close()
version_tuple = parse_version(contents)
_version = "%s-%s" % ('.'.join(['%s' % a for a in version_tuple[:3]]), version_tuple[3])
_release = _version
# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', 'sphinxcontrib.napoleon']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.