<commit_before>import os

PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    # ("Your Name", "your_email@example.com"),
)

MANAGERS = ADMINS

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": "valuenetwork.sqlite",
    }
}

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# On Unix systems, a value of None will cause Django to use the same
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = "UTC"

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = "en-us"

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.join(PACKAGE_ROOT, "site_media", "media")

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = "/site_media/media/"

# Absolute path to the directory static files should be collected to.
# Don"t put anything in this directory yourself; store your static files
# in apps" "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = os.path.join(PACKAGE_ROOT, "site_media", "static")
#STATIC_ROOT = os.path.join(PACKAGE_ROOT, "static")

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = "/site_media/static/"
#STATIC_URL = "/static/"

# Additional locations of static files
STATICFILES_DIRS = [
    os.path.join(PACKAGE_ROOT, "static"),
]

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = [
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]

# Make this unique, and don't share it with anybody.
SECRET_KEY = "use ./manage.py generate_secret_key to make this"

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = [
    "django.template.loaders.filesystem.Loader",
    "django.template.loaders.app_directories.Loader",
]

TEMPLATE_CONTEXT_PROCESSORS = [
    "django.contrib.auth.context_processors.auth",
    #"django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.static",
    "django.core.context_processors.tz",
    "django.core.context_processors.request",
    "django.contrib.messages.context_processors.messages",
    "pinax_utils.context_processors.settings",
    "account.context_processors.account",
]

LOGIN_URL = '/account/login/'

LOGIN_EXEMPT_URLS = (
    r"^$",
    r'^membership/',
    r'^membershipthanks/',
    r'^account/password/reset/',
    r'^account/password_reset_sent/',
    r'^captcha/image/',
)

MIDDLEWARE_CLASSES = [
    'corsheaders.middleware.CorsMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'valuenetwork.login_required_middleware.LoginRequiredMiddleware',
    #'debug_toolbar.middleware.DebugToolbarMiddleware',
]

ROOT_URLCONF = "valuenetwork.urls"

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = "valuenetwork.wsgi.application"

TEMPLATE_DIRS = [
    os.path.join(PACKAGE_ROOT, "templates"),
]

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.sites",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.humanize",
    "django_comments",

    # theme
    "pinax_theme_bootstrap_account",
    "pinax_theme_bootstrap",
    "django_forms_bootstrap",

    # external
    #'debug_toolbar',
    'django_extensions',
    'easy_thumbnails',
    #'report_builder',
    'notification',
    'corsheaders',
    #'django_filters',
    'rest_framework',
    'captcha',

    # project
    'valuenetwork.valueaccounting',
    'valuenetwork.equipment',
    'valuenetwork.board',
    'valuenetwork.api',
    'account',
    'work',

]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticatedOrReadOnly',),
    'PAGINATE_BY': 10,
   'URL_FIELD_NAME': 'api_url',
}

# valueaccounting settings
USE_WORK_NOW = True
SUBSTITUTABLE_DEFAULT = True
MAP_LATITUDE = 45.5601062
MAP_LONGITUDE = -73.7120832
MAP_ZOOM = 11

NOTIFICATION_QUEUE_ALL = True

THUMBNAIL_DEBUG = True

#SOUTH_MIGRATION_MODULES = {
#    'easy_thumbnails': 'easy_thumbnails.south_migrations',
#}

INTERNAL_IPS = ('127.0.0.1',)

DEBUG_TOOLBAR_CONFIG = {
    'INTERCEPT_REDIRECTS': False,
}

# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse"
        }
    },
    "handlers": {
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler"
        }
    },
    "loggers": {
        "django.request": {
            "handlers": ["mail_admins"],
            "level": "ERROR",
            "propagate": True,
        },
    }
}

#LOGGING_CONFIG = None

FIXTURE_DIRS = [
    os.path.join(PROJECT_ROOT, "fixtures"),
]

ACCOUNT_OPEN_SIGNUP = False
ACCOUNT_USE_OPENID = False
ACCOUNT_REQUIRED_EMAIL = False
ACCOUNT_EMAIL_VERIFICATION = False
ACCOUNT_EMAIL_AUTHENTICATION = False
ACCOUNT_LOGIN_REDIRECT_URL = "/accounting/start/"
WORKER_LOGIN_REDIRECT_URL = "/work/my-dashboard/"
WORKER_LOGOUT_REDIRECT_URL = "/work/work-home/"
ACCOUNT_LOGOUT_REDIRECT_URL = "home"
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 2
LOGIN_URL = '/account/login/'
AUTH_USER_MODEL = "auth.User"

CORS_URLS_REGEX = r'^/api/.*$'
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

BROADCAST_FAIRCOINS_LOCK_WAIT_TIMEOUT = None

import re
IGNORABLE_404_URLS = (
    re.compile(r'\.(php|cgi)$'),
    re.compile(r'^/phpmyadmin/'),
    re.compile(r'^/apple-touch-icon.*\.png$'),
    re.compile(r'^/favicon\.ico$'),
    re.compile(r'^/robots\.txt$'),
    re.compile(r'^/accounting/timeline/__history__.html\?0$'),
    re.compile(r'^/accounting/timeline/__history__.html$')
)

ALL_WORK_PAGE = "/accounting/work/"

try:
    from local_settings import *
except ImportError:
    pass

# updating to django 1.5
USE_TZ = True

# updating to prep for django 1.8
TEST_RUNNER = 'django.test.runner.DiscoverRunner'

# Translations directory
LOCALE_PATHS = [
    os.path.join(PACKAGE_ROOT, "locale"),
]

# Captcha settings
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
CAPTCHA_LETTER_ROTATION = (-15,15)
CAPTCHA_MATH_CHALLENGE_OPERATOR = 'x'
CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots','captcha.helpers.noise_dots',)
<commit_msg>Adding LANGUAGES and cleaning settings.py<commit_after>import os
from django.utils.translation import ugettext_lazy as _

PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    # ("Your Name", "your_email@example.com"),
)

MANAGERS = ADMINS

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": "valuenetwork.sqlite",
    }
}

TIME_ZONE = "UTC"

SITE_ID = 1

USE_TZ = True

MEDIA_ROOT = os.path.join(PACKAGE_ROOT, "site_media", "media")

MEDIA_URL = "/site_media/media/"

STATIC_ROOT = os.path.join(PACKAGE_ROOT, "site_media", "static")

STATIC_URL = "/site_media/static/"

STATICFILES_DIRS = [
    os.path.join(PACKAGE_ROOT, "static"),
]

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = [
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]

# Make this unique, and don't share it with anybody.
SECRET_KEY = "use ./manage.py generate_secret_key to make this"

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = [
    "django.template.loaders.filesystem.Loader",
    "django.template.loaders.app_directories.Loader",
]

TEMPLATE_CONTEXT_PROCESSORS = [
    "django.contrib.auth.context_processors.auth",
    #"django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.static",
    "django.core.context_processors.tz",
    "django.core.context_processors.request",
    "django.contrib.messages.context_processors.messages",
    "pinax_utils.context_processors.settings",
    "account.context_processors.account",
]

LOGIN_URL = '/account/login/'

LOGIN_EXEMPT_URLS = (
    r"^$",
    r'^membership/',
    r'^membershipthanks/',
    r'^account/password/reset/',
    r'^account/password_reset_sent/',
    r'^captcha/image/',
)

MIDDLEWARE_CLASSES = [
    'corsheaders.middleware.CorsMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'valuenetwork.login_required_middleware.LoginRequiredMiddleware',
    #'debug_toolbar.middleware.DebugToolbarMiddleware',
]

ROOT_URLCONF = "valuenetwork.urls"

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = "valuenetwork.wsgi.application"

TEMPLATE_DIRS = [
    os.path.join(PACKAGE_ROOT, "templates"),
]

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.sites",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.humanize",
    "django_comments",

    # theme
    "pinax_theme_bootstrap_account",
    "pinax_theme_bootstrap",
    "django_forms_bootstrap",

    # external
    #'debug_toolbar',
    'django_extensions',
    'easy_thumbnails',
    #'report_builder',
    'notification',
    'corsheaders',
    #'django_filters',
    'rest_framework',
    'captcha',

    # project
    'valuenetwork.valueaccounting',
    'valuenetwork.equipment',
    'valuenetwork.board',
    'valuenetwork.api',
    'account',
    'work',

]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticatedOrReadOnly',),
    'PAGINATE_BY': 10,
   'URL_FIELD_NAME': 'api_url',
}

# valueaccounting settings
USE_WORK_NOW = True
SUBSTITUTABLE_DEFAULT = True
MAP_LATITUDE = 45.5601062
MAP_LONGITUDE = -73.7120832
MAP_ZOOM = 11

NOTIFICATION_QUEUE_ALL = True

THUMBNAIL_DEBUG = True

#SOUTH_MIGRATION_MODULES = {
#    'easy_thumbnails': 'easy_thumbnails.south_migrations',
#}

INTERNAL_IPS = ('127.0.0.1',)

DEBUG_TOOLBAR_CONFIG = {
    'INTERCEPT_REDIRECTS': False,
}

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse"
        }
    },
    "handlers": {
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler"
        }
    },
    "loggers": {
        "django.request": {
            "handlers": ["mail_admins"],
            "level": "ERROR",
            "propagate": True,
        },
    }
}

#LOGGING_CONFIG = None

FIXTURE_DIRS = [
    os.path.join(PROJECT_ROOT, "fixtures"),
]

ACCOUNT_OPEN_SIGNUP = False
ACCOUNT_USE_OPENID = False
ACCOUNT_REQUIRED_EMAIL = False
ACCOUNT_EMAIL_VERIFICATION = False
ACCOUNT_EMAIL_AUTHENTICATION = False
ACCOUNT_LOGIN_REDIRECT_URL = "/accounting/start/"
WORKER_LOGIN_REDIRECT_URL = "/work/my-dashboard/"
WORKER_LOGOUT_REDIRECT_URL = "/work/work-home/"
ACCOUNT_LOGOUT_REDIRECT_URL = "home"
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 2
LOGIN_URL = '/account/login/'
AUTH_USER_MODEL = "auth.User"

CORS_URLS_REGEX = r'^/api/.*$'
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

BROADCAST_FAIRCOINS_LOCK_WAIT_TIMEOUT = None

import re
IGNORABLE_404_URLS = (
    re.compile(r'\.(php|cgi)$'),
    re.compile(r'^/phpmyadmin/'),
    re.compile(r'^/apple-touch-icon.*\.png$'),
    re.compile(r'^/favicon\.ico$'),
    re.compile(r'^/robots\.txt$'),
    re.compile(r'^/accounting/timeline/__history__.html\?0$'),
    re.compile(r'^/accounting/timeline/__history__.html$')
)

ALL_WORK_PAGE = "/accounting/work/"

try:
    from local_settings import *
except ImportError:
    pass

# updating to django 1.5
USE_TZ = True

# updating to prep for django 1.8
TEST_RUNNER = 'django.test.runner.DiscoverRunner'

# Translations and localization settings
USE_I18N = True
USE_L10N = True
LOCALE_PATHS = [
    os.path.join(PACKAGE_ROOT, "locale"),
]
LANGUAGE_CODE = 'en'
LANGUAGES = (
  ('en',  _('English')),
  ('es',  _('Spanish')),
)

# Captcha settings
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
CAPTCHA_LETTER_ROTATION = (-15,15)
CAPTCHA_MATH_CHALLENGE_OPERATOR = 'x'
CAPTCHA_NOISE_FUNCTIONS = (
  'captcha.helpers.noise_dots',
  'captcha.helpers.noise_dots',
)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

""" License

    Copyright (C) 2013 YunoHost

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program; if not, see http://www.gnu.org/licenses

"""

""" yunohost_hook.py

    Manage hooks
"""
import os
import sys
import re
import json
import errno
import subprocess
from glob import iglob

from moulinette.core import MoulinetteError
from moulinette.utils import log

hook_folder = '/usr/share/yunohost/hooks/'
custom_hook_folder = '/etc/yunohost/hooks.d/'

logger = log.getActionLogger('yunohost.hook')

def hook_add(app, file):
    """
    Store hook script to filsystem

    Keyword argument:
        app -- App to link with
        file -- Script to add (/path/priority-file)

    """
    path, filename = os.path.split(file)
    priority, action = _extract_filename_parts(filename)

    try: os.listdir(custom_hook_folder + action)
    except OSError: os.makedirs(custom_hook_folder + action)

    finalpath = custom_hook_folder + action +'/'+ priority +'-'+ app
    os.system('cp %s %s' % (file, finalpath))
    os.system('chown -hR admin: %s' % hook_folder)

    return { 'hook': finalpath }

def hook_remove(app):
    """
    Remove hooks linked to a specific app

    Keyword argument:
        app -- Scripts related to app will be removed

    """
    try:
        for action in os.listdir(custom_hook_folder):
            for script in os.listdir(custom_hook_folder + action):
                if script.endswith(app):
                    os.remove(custom_hook_folder + action +'/'+ script)
    except OSError: pass

def hook_info(action, name):
    """
    Get information about a given hook

    Keyword argument:
        action -- Action name
        name -- Hook name

    """
    hooks = []
    priorities = set()

    # Search in custom folder first
    for h in iglob('{:s}{:s}/*-{:s}'.format(
            custom_hook_folder, action, name)):
        priority, _ = _extract_filename_parts(os.path.basename(h))
        priorities.add(priority)
        hooks.append({
            'priority': priority,
            'path': h,
        })
    # Append non-overwritten system hooks
    for h in iglob('{:s}{:s}/*-{:s}'.format(
            hook_folder, action, name)):
        priority, _ = _extract_filename_parts(os.path.basename(h))
        if priority not in priorities:
            hooks.append({
                'priority': priority,
                'path': h,
            })

    if not hooks:
        raise MoulinetteError(errno.EINVAL, m18n.n('hook_name_unknown', name=name))
    return {
        'action': action,
        'name': name,
        'hooks': hooks,
    }

def hook_list(action, list_by='name', show_info=False):
    """
    List available hooks for an action

    Keyword argument:
        action -- Action name
        list_by -- Property to list hook by
        show_info -- Show hook information

    """
    result = {}

    # Process the property to list hook by
    if list_by == 'priority':
        if show_info:
            def _append_hook(d, priority, name, path):
                # Use the priority as key and a dict of hooks names
                # with their info as value
                value = { 'path': path }
                try:
                    d[priority][name] = value
                except KeyError:
                    d[priority] = { name: value }
        else:
            def _append_hook(d, priority, name, path):
                # Use the priority as key and the name as value
                try:
                    d[priority].add(name)
                except KeyError:
                    d[priority] = set([name])
    elif list_by == 'name' or list_by == 'folder':
        if show_info:
            def _append_hook(d, priority, name, path):
                # Use the name as key and a list of hooks info - the
                # executed ones with this name - as value
                l = d.get(name, list())
                for h in l:
                    # Only one priority for the hook is accepted
                    if h['priority'] == priority:
                        # Custom hooks overwrite system ones and they
                        # are appended at the end - so overwite it
                        if h['path'] != path:
                            h['path'] = path
                        return
                l.append({ 'priority': priority, 'path': path })
                d[name] = l
        else:
            if list_by == 'name':
                result = set()
            def _append_hook(d, priority, name, path):
                # Add only the name
                d.add(name)
    else:
        raise MoulinetteError(errno.EINVAL, m18n.n('hook_list_by_invalid'))

    def _append_folder(d, folder):
        # Iterate over and add hook from a folder
        for f in os.listdir(folder + action):
            if f[0] == '.' or f[-1] == '~':
                continue
            path = '%s%s/%s' % (folder, action, f)
            priority, name = _extract_filename_parts(f)
            _append_hook(d, priority, name, path)

    try:
        # Append system hooks first
        if list_by == 'folder':
            result['system'] = dict() if show_info else set()
            _append_folder(result['system'], hook_folder)
        else:
            _append_folder(result, hook_folder)
    except OSError:
        logger.debug("system hook folder not found for action '%s' in %s",
                     action, hook_folder)

    try:
        # Append custom hooks
        if list_by == 'folder':
            result['custom'] = dict() if show_info else set()
            _append_folder(result['custom'], custom_hook_folder)
        else:
            _append_folder(result, custom_hook_folder)
    except OSError:
        logger.debug("custom hook folder not found for action '%s' in %s",
                     action, custom_hook_folder)

    return { 'hooks': result }

def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None,
                  pre_callback=None, post_callback=None):
    """
    Execute all scripts binded to an action

    Keyword argument:
        action -- Action name
        hooks -- List of hooks names to execute
        args -- Ordered list of arguments to pass to the scripts
        no_trace -- Do not print each command that will be executed
        chdir -- The directory from where the scripts will be executed
        pre_callback -- An object to call before each script execution with
            (name, priority, path, args) as arguments and which must return
            the arguments to pass to the script
        post_callback -- An object to call after each script execution with
            (name, priority, path, succeed) as arguments

    """
    result = { 'succeed': {}, 'failed': {} }
    hooks_dict = {}

    # Retrieve hooks
    if not hooks:
        hooks_dict = hook_list(action, list_by='priority',
                               show_info=True)['hooks']
    else:
        hooks_names = hook_list(action, list_by='name',
                                show_info=True)['hooks']

        # Add similar hooks to the list
        # For example: Having a 16-postfix hook in the list will execute a
        # xx-postfix_dkim as well
        all_hooks = []
        for n in hooks:
            for key in hooks_names.keys():
                if key == n or key.startswith("%s_" % n) \
                  and key not in all_hooks:
                    all_hooks.append(key)

        # Iterate over given hooks names list
        for n in all_hooks:
            try:
                hl = hooks_names[n]
            except KeyError:
                raise MoulinetteError(errno.EINVAL,
                                      m18n.n('hook_name_unknown', n))
            # Iterate over hooks with this name
            for h in hl:
                # Update hooks dict
                d = hooks_dict.get(h['priority'], dict())
                d.update({ n: { 'path': h['path'] }})
                hooks_dict[h['priority']] = d
    if not hooks_dict:
        return result

    # Validate callbacks
    if not callable(pre_callback):
        pre_callback = lambda name, priority, path, args: args
    if not callable(post_callback):
        post_callback = lambda name, priority, path, succeed: None

    # Iterate over hooks and execute them
    for priority in sorted(hooks_dict):
        for name, info in iter(hooks_dict[priority].items()):
            state = 'succeed'
            path = info['path']
            try:
                hook_args = pre_callback(name=name, priority=priority,
                                         path=path, args=args)
                hook_exec(path, args=hook_args, chdir=chdir,
                          no_trace=no_trace, raise_on_error=True)
            except MoulinetteError as e:
                state = 'failed'
                logger.error(str(e))
                post_callback(name=name, priority=priority, path=path,
                              succeed=False)
            else:
                post_callback(name=name, priority=priority, path=path,
                              succeed=True)
            try:
                result[state][name].append(path)
            except KeyError:
                result[state][name] = [path]
    return result

def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
              chdir=None, env=None):
    """
    Execute hook from a file with arguments

    Keyword argument:
        path -- Path of the script to execute
        args -- Ordered list of arguments to pass to the script
        raise_on_error -- Raise if the script returns a non-zero exit code
        no_trace -- Do not print each command that will be executed
        chdir -- The directory from where the script will be executed
        env -- Dictionnary of environment variables to export

    """
    from moulinette.utils.process import call_async_output
    from yunohost.app import _value_for_locale

    # Validate hook path
    if path[0] != '/':
        path = os.path.realpath(path)
    if not os.path.isfile(path):
        raise MoulinetteError(errno.EIO, m18n.g('file_not_exist'))

    # Construct command variables
    cmd_args = ''
    if args and isinstance(args, list):
        # Concatenate arguments and escape them with double quotes to prevent
        # bash related issue if an argument is empty and is not the last
        cmd_args = '"{:s}"'.format('" "'.join(str(s) for s in args))
    if not chdir:
        # use the script directory as current one
        chdir, cmd_script = os.path.split(path)
        cmd_script = './{0}'.format(cmd_script)
    else:
        cmd_script = path

    # Construct command to execute
    command = ['sudo', '-n', '-u', 'admin', '-H', 'sh', '-c']
    if no_trace:
        cmd = '/bin/bash "{script}" {args}'
    else:
        # use xtrace on fd 7 which is redirected to stdout
        cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1'
    if env:
        # prepend environment variables
        cmd = '{0} {1}'.format(
            ' '.join(['{0}="{1}"'.format(k, v) for k, v in env.items()]), cmd)
    command.append(cmd.format(script=cmd_script, args=cmd_args))

    if logger.isEnabledFor(log.DEBUG):
        logger.info(m18n.n('executing_command', command=' '.join(command)))
    else:
        logger.info(m18n.n('executing_script', script=path))

    # Define output callbacks and call command
    callbacks = (
        lambda l: logger.info(l.rstrip()),
        lambda l: logger.warning(l.rstrip()),
    )
    returncode = call_async_output(
        command, callbacks, shell=False, cwd=chdir
    )

    # Check and return process' return code
    if returncode is None:
        if raise_on_error:
            raise MoulinetteError(m18n.n('hook_exec_not_terminated', path=path))
        else:
            logger.error(m18n.n('hook_exec_not_terminated', path=path))
            return 1
    elif raise_on_error and returncode != 0:
        raise MoulinetteError(m18n.n('hook_exec_failed', path=path))
    return returncode

def _extract_filename_parts(filename):
    """Extract hook parts from filename"""
    if '-' in filename:
        priority, action = filename.split('-', 1)
    else:
        priority = '50'
        action = filename
    return priority, action
<commit_msg>[enh] Allow to set env var for executed hooks in hooks_callback<commit_after># -*- coding: utf-8 -*-

""" License

    Copyright (C) 2013 YunoHost

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program; if not, see http://www.gnu.org/licenses

"""

""" yunohost_hook.py

    Manage hooks
"""
import os
import sys
import re
import json
import errno
import subprocess
from glob import iglob

from moulinette.core import MoulinetteError
from moulinette.utils import log

hook_folder = '/usr/share/yunohost/hooks/'
custom_hook_folder = '/etc/yunohost/hooks.d/'

logger = log.getActionLogger('yunohost.hook')

def hook_add(app, file):
    """
    Store hook script to filsystem

    Keyword argument:
        app -- App to link with
        file -- Script to add (/path/priority-file)

    """
    path, filename = os.path.split(file)
    priority, action = _extract_filename_parts(filename)

    try: os.listdir(custom_hook_folder + action)
    except OSError: os.makedirs(custom_hook_folder + action)

    finalpath = custom_hook_folder + action +'/'+ priority +'-'+ app
    os.system('cp %s %s' % (file, finalpath))
    os.system('chown -hR admin: %s' % hook_folder)

    return { 'hook': finalpath }

def hook_remove(app):
    """
    Remove hooks linked to a specific app

    Keyword argument:
        app -- Scripts related to app will be removed

    """
    try:
        for action in os.listdir(custom_hook_folder):
            for script in os.listdir(custom_hook_folder + action):
                if script.endswith(app):
                    os.remove(custom_hook_folder + action +'/'+ script)
    except OSError: pass

def hook_info(action, name):
    """
    Get information about a given hook

    Keyword argument:
        action -- Action name
        name -- Hook name

    """
    hooks = []
    priorities = set()

    # Search in custom folder first
    for h in iglob('{:s}{:s}/*-{:s}'.format(
            custom_hook_folder, action, name)):
        priority, _ = _extract_filename_parts(os.path.basename(h))
        priorities.add(priority)
        hooks.append({
            'priority': priority,
            'path': h,
        })
    # Append non-overwritten system hooks
    for h in iglob('{:s}{:s}/*-{:s}'.format(
            hook_folder, action, name)):
        priority, _ = _extract_filename_parts(os.path.basename(h))
        if priority not in priorities:
            hooks.append({
                'priority': priority,
                'path': h,
            })

    if not hooks:
        raise MoulinetteError(errno.EINVAL, m18n.n('hook_name_unknown', name=name))
    return {
        'action': action,
        'name': name,
        'hooks': hooks,
    }

def hook_list(action, list_by='name', show_info=False):
    """
    List available hooks for an action

    Keyword argument:
        action -- Action name
        list_by -- Property to list hook by
        show_info -- Show hook information

    """
    result = {}

    # Process the property to list hook by
    if list_by == 'priority':
        if show_info:
            def _append_hook(d, priority, name, path):
                # Use the priority as key and a dict of hooks names
                # with their info as value
                value = { 'path': path }
                try:
                    d[priority][name] = value
                except KeyError:
                    d[priority] = { name: value }
        else:
            def _append_hook(d, priority, name, path):
                # Use the priority as key and the name as value
                try:
                    d[priority].add(name)
                except KeyError:
                    d[priority] = set([name])
    elif list_by == 'name' or list_by == 'folder':
        if show_info:
            def _append_hook(d, priority, name, path):
                # Use the name as key and a list of hooks info - the
                # executed ones with this name - as value
                l = d.get(name, list())
                for h in l:
                    # Only one priority for the hook is accepted
                    if h['priority'] == priority:
                        # Custom hooks overwrite system ones and they
                        # are appended at the end - so overwite it
                        if h['path'] != path:
                            h['path'] = path
                        return
                l.append({ 'priority': priority, 'path': path })
                d[name] = l
        else:
            if list_by == 'name':
                result = set()
            def _append_hook(d, priority, name, path):
                # Add only the name
                d.add(name)
    else:
        raise MoulinetteError(errno.EINVAL, m18n.n('hook_list_by_invalid'))

    def _append_folder(d, folder):
        # Iterate over and add hook from a folder
        for f in os.listdir(folder + action):
            if f[0] == '.' or f[-1] == '~':
                continue
            path = '%s%s/%s' % (folder, action, f)
            priority, name = _extract_filename_parts(f)
            _append_hook(d, priority, name, path)

    try:
        # Append system hooks first
        if list_by == 'folder':
            result['system'] = dict() if show_info else set()
            _append_folder(result['system'], hook_folder)
        else:
            _append_folder(result, hook_folder)
    except OSError:
        logger.debug("system hook folder not found for action '%s' in %s",
                     action, hook_folder)

    try:
        # Append custom hooks
        if list_by == 'folder':
            result['custom'] = dict() if show_info else set()
            _append_folder(result['custom'], custom_hook_folder)
        else:
            _append_folder(result, custom_hook_folder)
    except OSError:
        logger.debug("custom hook folder not found for action '%s' in %s",
                     action, custom_hook_folder)

    return { 'hooks': result }

def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None,
                  env=None, pre_callback=None, post_callback=None):
    """
    Execute all scripts binded to an action

    Keyword argument:
        action -- Action name
        hooks -- List of hooks names to execute
        args -- Ordered list of arguments to pass to the scripts
        no_trace -- Do not print each command that will be executed
        chdir -- The directory from where the scripts will be executed
        env -- Dictionnary of environment variables to export
        pre_callback -- An object to call before each script execution with
            (name, priority, path, args) as arguments and which must return
            the arguments to pass to the script
        post_callback -- An object to call after each script execution with
            (name, priority, path, succeed) as arguments

    """
    result = { 'succeed': {}, 'failed': {} }
    hooks_dict = {}

    # Retrieve hooks
    if not hooks:
        hooks_dict = hook_list(action, list_by='priority',
                               show_info=True)['hooks']
    else:
        hooks_names = hook_list(action, list_by='name',
                                show_info=True)['hooks']

        # Add similar hooks to the list
        # For example: Having a 16-postfix hook in the list will execute a
        # xx-postfix_dkim as well
        all_hooks = []
        for n in hooks:
            for key in hooks_names.keys():
                if key == n or key.startswith("%s_" % n) \
                  and key not in all_hooks:
                    all_hooks.append(key)

        # Iterate over given hooks names list
        for n in all_hooks:
            try:
                hl = hooks_names[n]
            except KeyError:
                raise MoulinetteError(errno.EINVAL,
                                      m18n.n('hook_name_unknown', n))
            # Iterate over hooks with this name
            for h in hl:
                # Update hooks dict
                d = hooks_dict.get(h['priority'], dict())
                d.update({ n: { 'path': h['path'] }})
                hooks_dict[h['priority']] = d
    if not hooks_dict:
        return result

    # Validate callbacks
    if not callable(pre_callback):
        pre_callback = lambda name, priority, path, args: args
    if not callable(post_callback):
        post_callback = lambda name, priority, path, succeed: None

    # Iterate over hooks and execute them
    for priority in sorted(hooks_dict):
        for name, info in iter(hooks_dict[priority].items()):
            state = 'succeed'
            path = info['path']
            try:
                hook_args = pre_callback(name=name, priority=priority,
                                         path=path, args=args)
                hook_exec(path, args=hook_args, chdir=chdir, env=env,
                          no_trace=no_trace, raise_on_error=True)
            except MoulinetteError as e:
                state = 'failed'
                logger.error(str(e))
                post_callback(name=name, priority=priority, path=path,
                              succeed=False)
            else:
                post_callback(name=name, priority=priority, path=path,
                              succeed=True)
            try:
                result[state][name].append(path)
            except KeyError:
                result[state][name] = [path]
    return result

def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
              chdir=None, env=None):
    """
    Execute hook from a file with arguments

    Keyword argument:
        path -- Path of the script to execute
        args -- Ordered list of arguments to pass to the script
        raise_on_error -- Raise if the script returns a non-zero exit code
        no_trace -- Do not print each command that will be executed
        chdir -- The directory from where the script will be executed
        env -- Dictionnary of environment variables to export

    """
    from moulinette.utils.process import call_async_output
    from yunohost.app import _value_for_locale

    # Validate hook path
    if path[0] != '/':
        path = os.path.realpath(path)
    if not os.path.isfile(path):
        raise MoulinetteError(errno.EIO, m18n.g('file_not_exist'))

    # Construct command variables
    cmd_args = ''
    if args and isinstance(args, list):
        # Concatenate arguments and escape them with double quotes to prevent
        # bash related issue if an argument is empty and is not the last
        cmd_args = '"{:s}"'.format('" "'.join(str(s) for s in args))
    if not chdir:
        # use the script directory as current one
        chdir, cmd_script = os.path.split(path)
        cmd_script = './{0}'.format(cmd_script)
    else:
        cmd_script = path

    # Construct command to execute
    command = ['sudo', '-n', '-u', 'admin', '-H', 'sh', '-c']
    if no_trace:
        cmd = '/bin/bash "{script}" {args}'
    else:
        # use xtrace on fd 7 which is redirected to stdout
        cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1'
    if env:
        # prepend environment variables
        cmd = '{0} {1}'.format(
            ' '.join(['{0}="{1}"'.format(k, v) for k, v in env.items()]), cmd)
    command.append(cmd.format(script=cmd_script, args=cmd_args))

    if logger.isEnabledFor(log.DEBUG):
        logger.info(m18n.n('executing_command', command=' '.join(command)))
    else:
        logger.info(m18n.n('executing_script', script=path))

    # Define output callbacks and call command
    callbacks = (
        lambda l: logger.info(l.rstrip()),
        lambda l: logger.warning(l.rstrip()),
    )
    returncode = call_async_output(
        command, callbacks, shell=False, cwd=chdir
    )

    # Check and return process' return code
    if returncode is None:
        if raise_on_error:
            raise MoulinetteError(m18n.n('hook_exec_not_terminated', path=path))
        else:
            logger.error(m18n.n('hook_exec_not_terminated', path=path))
            return 1
    elif raise_on_error and returncode != 0:
        raise MoulinetteError(m18n.n('hook_exec_failed', path=path))
    return returncode

def _extract_filename_parts(filename):
    """Extract hook parts from filename"""
    if '-' in filename:
        priority, action = filename.split('-', 1)
    else:
        priority = '50'
        action = filename
    return priority, action
<|endoftext|>


<commit_before>import logging
import optparse
import os
import json
from shutil import copyfile
from os.path import join as pjoin
import tarfile

import errno
from utils import sha1_for_path, canonical_path, makedirs, mygzip

from .models import (ZincIndex, load_index, ZincError, ZincErrors,
        ZincOperation, ZincConfig, load_config, ZincManifest, load_manifest,
        CreateBundleVersionOperation, ZincCatalog, create_catalog_at_path)
from .defaults import defaults

logging.basicConfig(level=logging.DEBUG,
        format='%(asctime)s %(levelname)s %(message)s')

### Commands #################################################################

def _cmd_verify(path):
    catalog = ZincCatalog(path)
    results = catalog.verify()
    error_count = total_count = 0
    for (file, error) in results.items():
        if error.code != ZincErrors.OK.code:
            print error.message + " : " + file
            error_count = error_count + 1
        total_count = total_count + 1
    print "Verified %d files, %d errors" % (total_count, error_count)

### Main #####################################################################

def main():

    #commands = {
    #        "catalog" : ("create", "verify"),
    #        #"bundle": ("create", "commit"),
    #        }

    commands = ("catalog:create",
            "catalog:verify",
            "bundle:update",
            "distro:update",
            )

    usage = "usage: %prog <command> [options]"
    parser = optparse.OptionParser(usage)
    parser.add_option("-i", "--input", dest="input_path",
                    action="store",
                    help="Input (source) path")
    parser.add_option("-o", "--output", dest="output_path",
                    action="store",
                    help="Output (destination) path")
    parser.add_option("-u", "--url", dest="url_root",
                    action="store",
                    help="Root deployment URL")

#    parser.add_option("-c", "--config", dest="config",
#                    action="store",
#                    default=default_config,
#                    help="Config file")
#    parser.add_option("-d", "--deploy-config", dest="deploy_config",
#                    action="store",
#                    default="live",
#                    type="choice",
#                    choices=("dev", "live"),
#                    help="Choose 'dev' or 'live' deployment. Default: 'live'")
#    parser.add_option("-D", "--delete", dest="delete",
#                    action="store_true",
#                    default=False,
#                    help="Delete existing local files first.")
#
    options, args = parser.parse_args()

    if len(args) == 0 or args[0] not in commands:
        parser.print_usage()
        exit(1)

    # TODO: better command parsing
    command = args[0]
    if command == "catalog:verify":
        if len(args) < 2:
            parser.print_usage()
            exit(1)
        path = args[1]
        _cmd_verify(path)
        exit(0)
    elif command == "catalog:create":
        if len(args) < 3:
            parser.print_usage()
            exit(1)
        id = args[1]
        path = args[2]
        create_catalog_at_path(path, id)
        exit(0)
    elif command == "bundle:update":
        if len(args) < 3:
            #parser.print_usage()
            print "bundle:update <bundle name> <path>"
            exit(1)
        catalog = ZincCatalog(".")
        bundle_name = args[1]
        path = args[2]
        manifest = catalog.create_bundle_version(bundle_name, path)
        print "Updated %s v%d" % (manifest.bundle_id, manifest.version)
        exit(0)
    elif command == "distro:update":
        if len(args) < 4:
            #parser.print_usage()
            print "distro:update <distro name> <bundle name> <bundle version>"
            exit(1)
        catalog = ZincCatalog(".")
        distro_name = args[1]
        bundle_name = args[2]
        bundle_version = args[3]
        catalog.update_distribution(distro_name, bundle_name, bundle_version)
        exit(0)

if __name__ == "__main__":
    main()

<commit_msg>Fixing some references to bundle name<commit_after>import logging
import optparse
import os
import json
from shutil import copyfile
from os.path import join as pjoin
import tarfile

import errno
from utils import sha1_for_path, canonical_path, makedirs, mygzip

from .models import (ZincIndex, load_index, ZincError, ZincErrors,
        ZincOperation, ZincConfig, load_config, ZincManifest, load_manifest,
        CreateBundleVersionOperation, ZincCatalog, create_catalog_at_path)
from .defaults import defaults

logging.basicConfig(level=logging.DEBUG,
        format='%(asctime)s %(levelname)s %(message)s')

### Commands #################################################################

def _cmd_verify(path):
    catalog = ZincCatalog(path)
    results = catalog.verify()
    error_count = total_count = 0
    for (file, error) in results.items():
        if error.code != ZincErrors.OK.code:
            print error.message + " : " + file
            error_count = error_count + 1
        total_count = total_count + 1
    print "Verified %d files, %d errors" % (total_count, error_count)

### Main #####################################################################

def main():

    #commands = {
    #        "catalog" : ("create", "verify"),
    #        #"bundle": ("create", "commit"),
    #        }

    commands = ("catalog:create",
            "catalog:verify",
            "bundle:update",
            "distro:update",
            )

    usage = "usage: %prog <command> [options]"
    parser = optparse.OptionParser(usage)
    parser.add_option("-i", "--input", dest="input_path",
                    action="store",
                    help="Input (source) path")
    parser.add_option("-o", "--output", dest="output_path",
                    action="store",
                    help="Output (destination) path")
    parser.add_option("-u", "--url", dest="url_root",
                    action="store",
                    help="Root deployment URL")

#    parser.add_option("-c", "--config", dest="config",
#                    action="store",
#                    default=default_config,
#                    help="Config file")
#    parser.add_option("-d", "--deploy-config", dest="deploy_config",
#                    action="store",
#                    default="live",
#                    type="choice",
#                    choices=("dev", "live"),
#                    help="Choose 'dev' or 'live' deployment. Default: 'live'")
#    parser.add_option("-D", "--delete", dest="delete",
#                    action="store_true",
#                    default=False,
#                    help="Delete existing local files first.")
#
    options, args = parser.parse_args()

    if len(args) == 0 or args[0] not in commands:
        parser.print_usage()
        exit(1)

    # TODO: better command parsing
    command = args[0]
    if command == "catalog:verify":
        if len(args) < 2:
            parser.print_usage()
            exit(1)
        path = args[1]
        _cmd_verify(path)
        exit(0)
    elif command == "catalog:create":
        if len(args) < 3:
            parser.print_usage()
            exit(1)
        id = args[1]
        path = args[2]
        create_catalog_at_path(path, id)
        exit(0)
    elif command == "bundle:update":
        if len(args) < 3:
            #parser.print_usage()
            print "bundle:update <bundle id> <path>"
            exit(1)
        catalog = ZincCatalog(".")
        bundle_id = args[1]
        path = args[2]
        manifest = catalog.create_bundle_version(bundle_id, path)
        print "Updated %s v%d" % (manifest.bundle_id, manifest.version)
        exit(0)
    elif command == "distro:update":
        if len(args) < 4:
            #parser.print_usage()
            print "distro:update <distro name> <bundle id> <bundle version>"
            exit(1)
        catalog = ZincCatalog(".")
        distro_name = args[1]
        bundle_id = args[2]
        bundle_version = args[3]
        catalog.update_distribution(distro_name, bundle_id, bundle_version)
        exit(0)

if __name__ == "__main__":
    main()

<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# __COPYRIGHT__
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"

"""
Test Environment's FindSourceFiles method.
"""

import TestSCons

test = TestSCons.TestSCons()

# Quite complex, but real-life test.
# 0. Setup VariantDir, "var", without duplication. The "src" is source dir.
# 1. Generate souce file var/foo.c from src/foo.c.in. Define program foo.
# 2. Gather all sources necessary to create '.' node and create source
#    tarball. We expect 'src/foo.c.in' file within tarbal, and no content
#    under 'var' directory.
test.subdir('src')
test.subdir('variant')

test.write('SConstruct', """
VariantDir(src_dir = 'src', variant_dir = 'var', duplicate = 0)
env = Environment(tools = ['default','textfile','packaging'])
SConscript(['var/SConscript'], exports = 'env')
sources = env.FindSourceFiles('.')
pkg = env.Package( NAME = 'foo', VERSION = '1.0', PACKAGETYPE = 'src_tarbz2',
                   source = sources )
Ignore( '.', pkg )
""")

test.write('src/SConscript', """
Import('env')
foo_c = env.Substfile('foo.c.in', SUBST_DICT = {'__A__' : '0' })
foo = env.Program(foo_c)
""")

test.write('src/foo.c.in', """ int main() { return __A__;}
""")

test.run(arguments = 'package')

test.must_exist('foo-1.0/src/SConscript')
test.must_exist('foo-1.0/src/foo.c.in')
test.must_not_exist('foo-1.0/var/SConscript')
test.must_not_exist('foo-1.0/var/foo.c.in')

test.pass_test()

# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:
<commit_msg>Removed unnecessary line in test/FindSourceFiles.py<commit_after>#!/usr/bin/env python
#
# __COPYRIGHT__
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"

"""
Test Environment's FindSourceFiles method.
"""

import TestSCons

test = TestSCons.TestSCons()

# Quite complex, but real-life test.
# 0. Setup VariantDir, "var", without duplication. The "src" is source dir.
# 1. Generate souce file var/foo.c from src/foo.c.in. Define program foo.
# 2. Gather all sources necessary to create '.' node and create source
#    tarball. We expect 'src/foo.c.in' file within tarbal, and no content
#    under 'var' directory.
test.subdir('src')

test.write('SConstruct', """
VariantDir(src_dir = 'src', variant_dir = 'var', duplicate = 0)
env = Environment(tools = ['default','textfile','packaging'])
SConscript(['var/SConscript'], exports = 'env')
sources = env.FindSourceFiles('.')
pkg = env.Package( NAME = 'foo', VERSION = '1.0', PACKAGETYPE = 'src_tarbz2',
                   source = sources )
Ignore( '.', pkg )
""")

test.write('src/SConscript', """
Import('env')
foo_c = env.Substfile('foo.c.in', SUBST_DICT = {'__A__' : '0' })
foo = env.Program(foo_c)
""")

test.write('src/foo.c.in', """ int main() { return __A__;}
""")

test.run(arguments = 'package')

test.must_exist('foo-1.0/src/SConscript')
test.must_exist('foo-1.0/src/foo.c.in')
test.must_not_exist('foo-1.0/var/SConscript')
test.must_not_exist('foo-1.0/var/foo.c.in')

test.pass_test()

# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:
<|endoftext|>


<commit_before># Orca
#
# Copyright 2005-2009 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

"""Custom script for StarOffice and OpenOffice."""

__id__        = "$Id$"
__version__   = "$Revision$"
__date__      = "$Date$"
__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc."
__license__   = "LGPL"

import pyatspi

import orca.speech_generator as speech_generator
import orca.settings as settings

from orca.orca_i18n import _ # for gettext support

import script_settings

class SpeechGenerator(speech_generator.SpeechGenerator):

    # pylint: disable-msg=W0142

    def __init__(self, script):
        speech_generator.SpeechGenerator.__init__(self, script)

    def __overrideParagraph(self, obj, **args):
        # Treat a paragraph which is serving as a text entry in a dialog
        # as a text object.
        #
        role = args.get('role', obj.getRole())
        override = \
            role == "text frame" \
            or (role == pyatspi.ROLE_PARAGRAPH \
                and self._script.getAncestor(obj,
                                             [pyatspi.ROLE_DIALOG],
                                             [pyatspi.ROLE_APPLICATION]))
        return override

    def _getRoleName(self, obj, **args):
        result = []
        role = args.get('role', obj.getRole())
        if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
           and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
            # We don't speak roles for the objects in the toolbar.
            #
            pass
        else:
            # Treat a paragraph which is serving as a text entry in a dialog
            # as a text object.
            #
            override = self.__overrideParagraph(obj, **args)
            if override:
                oldRole = self._overrideRole(pyatspi.ROLE_TEXT, args)
            result.extend(speech_generator.SpeechGenerator._getRoleName(
                          self, obj, **args))
            if override:
                self._restoreRole(oldRole, args)
        return result

    def _getTextRole(self, obj, **args):
        result = []
        role = args.get('role', obj.getRole())
        if role != pyatspi.ROLE_PARAGRAPH \
           or self.__overrideParagraph(obj, **args):
            result.extend(self._getRoleName(obj, **args))
        return result

    def _getLabelOrName(self, obj, **args):
        """Gets the label or the name if the label is not preset."""
        result = []
        override = self.__overrideParagraph(obj, **args)
        # Treat a paragraph which is serving as a text entry in a dialog
        # as a text object.
        #
        if override:
            result.extend(self._getLabel(obj, **args))
            if len(result) == 0 and obj.parent:
                parentLabel = self._getLabel(obj.parent, **args)
                # If we aren't already focused, we will have spoken the
                # parent as part of the speech context and do not want
                # to repeat it.
                #
                already_focused = args.get('already_focused', False)
                if already_focused:
                    result.extend(parentLabel)
                # If we still don't have a label, look to the name.
                #
                if not parentLabel and obj.name and len(obj.name):
                    result.append(obj.name)
        else:
            result.extend(speech_generator.SpeechGenerator._getLabelOrName(
                self, obj, **args))
        return result

    def _getToggleState(self, obj, **args):
        """Treat push buttons (which act like toggle buttons) and toggle
        buttons in the toolbar specially.  This is so we can have more
        natural sounding speech such as "bold on", "bold off", etc."""
        result = []
        role = args.get('role', obj.getRole())
        if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
           and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
            if obj.getState().contains(pyatspi.STATE_CHECKED):
                # Translators: this represents the state of a check box
                #
                result.append(_("on"))
            else:
                # Translators: this represents the state of a check box
                #
                result.append(_("off"))
        elif role == pyatspi.ROLE_TOGGLE_BUTTON:
            result.extend(speech_generator.SpeechGenerator._getToggleState(
                self, obj, **args))
        return result

    def _getNewRowHeader(self, obj, **args):
        result = []
        # Check to see if this spread sheet cell has either a dynamic
        # row heading associated with it.
        #
        table = self._script.getTable(obj)
        parent = obj.parent
        try:
            parentTable = parent.queryTable()
        except NotImplementedError:
            parentTable = None
        index = self._script.getCellIndex(obj)
        if "lastRow" in self._script.pointOfReference and \
           self._script.pointOfReference["lastRow"] != \
           parentTable.getRowAtIndex(index):
            if table in self._script.dynamicRowHeaders:
                column = self._script.dynamicRowHeaders[table]
                header = self._script.getDynamicColumnHeaderCell(obj, column)
                try:
                    headerText = header.queryText()
                except:
                    headerText = None
                if header.childCount > 0:
                    for child in header:
                        text = self._script.getText(child, 0, -1)
                        if text:
                            result.append(text)
                elif headerText:
                    text = self._script.getText(header, 0, -1)
                    if text:
                        result.append(text)
        return result

    def _getNewColumnHeader(self, obj, **args):
        result = []
        # Check to see if this spread sheet cell has either a dynamic
        # row heading associated with it.
        #
        table = self._script.getTable(obj)
        parent = obj.parent
        try:
            parentTable = parent.queryTable()
        except NotImplementedError:
            parentTable = None
        index = self._script.getCellIndex(obj)
        if "lastColumn" in self._script.pointOfReference and \
           self._script.pointOfReference["lastColumn"] != \
           parentTable.getColumnAtIndex(index):
            if table in self._script.dynamicColumnHeaders:
                row = self._script.dynamicColumnHeaders[table]
                header = self._script.getDynamicRowHeaderCell(obj, row)
                try:
                    headerText = header.queryText()
                except:
                    headerText = None
                if header.childCount > 0:
                    for child in header:
                        text = self._script.getText(child, 0, -1)
                        if text:
                            result.append(text)
                elif headerText:
                    text = self._script.getText(header, 0, -1)
                    if text:
                        result.append(text)
        return result

    def _getSpreadSheetCell(self, obj, **args):
        result = []
        if self._script.inputLineForCell == None:
            self._script.inputLineForCell = \
                self._script.locateInputLine(obj)
        try:
            if obj.queryText():
                objectText = self._script.getText(obj, 0, -1)
                if not script_settings.speakCellCoordinates \
                   and len(objectText) == 0:
                    # Translators: this indicates an empty (blank) spread
                    # sheet cell.
                    #
                    objectText = _("blank")
                    result.append(objectText)
        except NotImplementedError:
            pass

        if script_settings.speakCellCoordinates:
            nameList = obj.name.split()
            # We were assuming that the word for "cell" would always
            # precede the coordinates. This is not the case for all
            # languages (e.g. Hungarian). See bug #562532. Therefore
            # examine each item and choose the one which contains a
            # digit.
            #
            for name in nameList:
                for char in name.decode("UTF-8"):
                    if char.isdigit():
                        result.append(name)
        return result

    def _getRealTableCell(self, obj, **args):
        """Get the speech for a table cell. If this isn't inside a
        spread sheet, just return the utterances returned by the default
        table cell speech handler.

        Arguments:
        - obj: the table cell
        - already_focused: False if object just received focus

        Returns a list of utterances to be spoken for the object.
        """
        result = []
        if self._script.isSpreadSheetCell(obj):
            result.extend(self._getSpreadSheetCell(obj, **args))
        else:
            # Check to see how many children this table cell has. If it's
            # just one (or none), then pass it on to the superclass to be
            # processed.
            #
            # If it's more than one, then get the speech for each child,
            # and call this method again.
            #
            if obj.childCount <= 1:
                result.extend(speech_generator.SpeechGenerator.\
                              _getRealTableCell(self, obj, **args))
            else:
                for child in obj:
                    result.extend(self._getRealTableCell(child, **args))
        return result

    def _getTableCellRow(self, obj, **args):
        """Get the speech for a table cell row or a single table cell
        if settings.readTableCellRow is False. If this isn't inside a
        spread sheet, just return the utterances returned by the default
        table cell speech handler.

        Arguments:
        - obj: the table cell
        - already_focused: False if object just received focus

        Returns a list of utterances to be spoken for the object.
        """
        result = []
        if self._script.isSpreadSheetCell(obj):
            if settings.readTableCellRow:
                parent = obj.parent
                parentTable = parent.queryTable()
                index = self._script.getCellIndex(obj)
                row = parentTable.getRowAtIndex(index)
                column = parentTable.getColumnAtIndex(index)
                # This is an indication of whether we should speak all the
                # table cells (the user has moved focus up or down a row),
                # or just the current one (focus has moved left or right in
                # the same row).
                #
                speakAll = True
                if "lastRow" in self._script.pointOfReference and \
                    "lastColumn" in self._script.pointOfReference:
                    pointOfReference = self._script.pointOfReference
                    speakAll = (pointOfReference["lastRow"] != row) or \
                           ((row == 0 or row == parentTable.nRows-1) and \
                            pointOfReference["lastColumn"] == column)
                if speakAll:
                    [startIndex, endIndex] = \
                        self._script.getSpreadSheetRowRange(obj)
                    for i in range(startIndex, endIndex+1):
                        cell = parentTable.getAccessibleAt(row, i)
                        showing = cell.getState().contains( \
                                      pyatspi.STATE_SHOWING)
                        if showing:
                            result.extend(self._getRealTableCell(cell, **args))
                else:
                    result.extend(self._getRealTableCell(obj, **args))
            else:
                result.extend(self._getRealTableCell(obj, **args))
        else:
            print "HERE", settings.readTableCellRow
            result.extend(speech_generator.SpeechGenerator._getTableCellRow(
                          self, obj, **args))
        return result
<commit_msg>Fix speaking of spreadsheet cell contents<commit_after># Orca
#
# Copyright 2005-2009 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

"""Custom script for StarOffice and OpenOffice."""

__id__        = "$Id$"
__version__   = "$Revision$"
__date__      = "$Date$"
__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc."
__license__   = "LGPL"

import pyatspi

import orca.speech_generator as speech_generator
import orca.settings as settings

from orca.orca_i18n import _ # for gettext support

import script_settings

class SpeechGenerator(speech_generator.SpeechGenerator):

    # pylint: disable-msg=W0142

    def __init__(self, script):
        speech_generator.SpeechGenerator.__init__(self, script)

    def __overrideParagraph(self, obj, **args):
        # Treat a paragraph which is serving as a text entry in a dialog
        # as a text object.
        #
        role = args.get('role', obj.getRole())
        override = \
            role == "text frame" \
            or (role == pyatspi.ROLE_PARAGRAPH \
                and self._script.getAncestor(obj,
                                             [pyatspi.ROLE_DIALOG],
                                             [pyatspi.ROLE_APPLICATION]))
        return override

    def _getRoleName(self, obj, **args):
        result = []
        role = args.get('role', obj.getRole())
        if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
           and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
            # We don't speak roles for the objects in the toolbar.
            #
            pass
        else:
            # Treat a paragraph which is serving as a text entry in a dialog
            # as a text object.
            #
            override = self.__overrideParagraph(obj, **args)
            if override:
                oldRole = self._overrideRole(pyatspi.ROLE_TEXT, args)
            result.extend(speech_generator.SpeechGenerator._getRoleName(
                          self, obj, **args))
            if override:
                self._restoreRole(oldRole, args)
        return result

    def _getTextRole(self, obj, **args):
        result = []
        role = args.get('role', obj.getRole())
        if role != pyatspi.ROLE_PARAGRAPH \
           or self.__overrideParagraph(obj, **args):
            result.extend(self._getRoleName(obj, **args))
        return result

    def _getLabelOrName(self, obj, **args):
        """Gets the label or the name if the label is not preset."""
        result = []
        override = self.__overrideParagraph(obj, **args)
        # Treat a paragraph which is serving as a text entry in a dialog
        # as a text object.
        #
        if override:
            result.extend(self._getLabel(obj, **args))
            if len(result) == 0 and obj.parent:
                parentLabel = self._getLabel(obj.parent, **args)
                # If we aren't already focused, we will have spoken the
                # parent as part of the speech context and do not want
                # to repeat it.
                #
                already_focused = args.get('already_focused', False)
                if already_focused:
                    result.extend(parentLabel)
                # If we still don't have a label, look to the name.
                #
                if not parentLabel and obj.name and len(obj.name):
                    result.append(obj.name)
        else:
            result.extend(speech_generator.SpeechGenerator._getLabelOrName(
                self, obj, **args))
        return result

    def _getToggleState(self, obj, **args):
        """Treat push buttons (which act like toggle buttons) and toggle
        buttons in the toolbar specially.  This is so we can have more
        natural sounding speech such as "bold on", "bold off", etc."""
        result = []
        role = args.get('role', obj.getRole())
        if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
           and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
            if obj.getState().contains(pyatspi.STATE_CHECKED):
                # Translators: this represents the state of a check box
                #
                result.append(_("on"))
            else:
                # Translators: this represents the state of a check box
                #
                result.append(_("off"))
        elif role == pyatspi.ROLE_TOGGLE_BUTTON:
            result.extend(speech_generator.SpeechGenerator._getToggleState(
                self, obj, **args))
        return result

    def _getNewRowHeader(self, obj, **args):
        result = []
        # Check to see if this spread sheet cell has either a dynamic
        # row heading associated with it.
        #
        table = self._script.getTable(obj)
        parent = obj.parent
        try:
            parentTable = parent.queryTable()
        except NotImplementedError:
            parentTable = None
        index = self._script.getCellIndex(obj)
        if "lastRow" in self._script.pointOfReference and \
           self._script.pointOfReference["lastRow"] != \
           parentTable.getRowAtIndex(index):
            if table in self._script.dynamicRowHeaders:
                column = self._script.dynamicRowHeaders[table]
                header = self._script.getDynamicColumnHeaderCell(obj, column)
                try:
                    headerText = header.queryText()
                except:
                    headerText = None
                if header.childCount > 0:
                    for child in header:
                        text = self._script.getText(child, 0, -1)
                        if text:
                            result.append(text)
                elif headerText:
                    text = self._script.getText(header, 0, -1)
                    if text:
                        result.append(text)
        return result

    def _getNewColumnHeader(self, obj, **args):
        result = []
        # Check to see if this spread sheet cell has either a dynamic
        # row heading associated with it.
        #
        table = self._script.getTable(obj)
        parent = obj.parent
        try:
            parentTable = parent.queryTable()
        except NotImplementedError:
            parentTable = None
        index = self._script.getCellIndex(obj)
        if "lastColumn" in self._script.pointOfReference and \
           self._script.pointOfReference["lastColumn"] != \
           parentTable.getColumnAtIndex(index):
            if table in self._script.dynamicColumnHeaders:
                row = self._script.dynamicColumnHeaders[table]
                header = self._script.getDynamicRowHeaderCell(obj, row)
                try:
                    headerText = header.queryText()
                except:
                    headerText = None
                if header.childCount > 0:
                    for child in header:
                        text = self._script.getText(child, 0, -1)
                        if text:
                            result.append(text)
                elif headerText:
                    text = self._script.getText(header, 0, -1)
                    if text:
                        result.append(text)
        return result

    def _getSpreadSheetCell(self, obj, **args):
        result = []
        if self._script.inputLineForCell == None:
            self._script.inputLineForCell = \
                self._script.locateInputLine(obj)
        try:
            if obj.queryText():
                objectText = self._script.getText(obj, 0, -1)
                if not script_settings.speakCellCoordinates \
                   and len(objectText) == 0:
                    # Translators: this indicates an empty (blank) spread
                    # sheet cell.
                    #
                    objectText = _("blank")
                result.append(objectText)
        except NotImplementedError:
            pass

        if script_settings.speakCellCoordinates:
            nameList = obj.name.split()
            # We were assuming that the word for "cell" would always
            # precede the coordinates. This is not the case for all
            # languages (e.g. Hungarian). See bug #562532. Therefore
            # examine each item and choose the one which contains a
            # digit.
            #
            for name in nameList:
                for char in name.decode("UTF-8"):
                    if char.isdigit():
                        result.append(name)
        return result

    def _getRealTableCell(self, obj, **args):
        """Get the speech for a table cell. If this isn't inside a
        spread sheet, just return the utterances returned by the default
        table cell speech handler.

        Arguments:
        - obj: the table cell
        - already_focused: False if object just received focus

        Returns a list of utterances to be spoken for the object.
        """
        result = []
        if self._script.isSpreadSheetCell(obj):
            result.extend(self._getSpreadSheetCell(obj, **args))
        else:
            # Check to see how many children this table cell has. If it's
            # just one (or none), then pass it on to the superclass to be
            # processed.
            #
            # If it's more than one, then get the speech for each child,
            # and call this method again.
            #
            if obj.childCount <= 1:
                result.extend(speech_generator.SpeechGenerator.\
                              _getRealTableCell(self, obj, **args))
            else:
                for child in obj:
                    result.extend(self._getRealTableCell(child, **args))
        return result

    def _getTableCellRow(self, obj, **args):
        """Get the speech for a table cell row or a single table cell
        if settings.readTableCellRow is False. If this isn't inside a
        spread sheet, just return the utterances returned by the default
        table cell speech handler.

        Arguments:
        - obj: the table cell
        - already_focused: False if object just received focus

        Returns a list of utterances to be spoken for the object.
        """
        result = []
        if self._script.isSpreadSheetCell(obj):
            if settings.readTableCellRow:
                parent = obj.parent
                parentTable = parent.queryTable()
                index = self._script.getCellIndex(obj)
                row = parentTable.getRowAtIndex(index)
                column = parentTable.getColumnAtIndex(index)
                # This is an indication of whether we should speak all the
                # table cells (the user has moved focus up or down a row),
                # or just the current one (focus has moved left or right in
                # the same row).
                #
                speakAll = True
                if "lastRow" in self._script.pointOfReference and \
                    "lastColumn" in self._script.pointOfReference:
                    pointOfReference = self._script.pointOfReference
                    speakAll = (pointOfReference["lastRow"] != row) or \
                           ((row == 0 or row == parentTable.nRows-1) and \
                            pointOfReference["lastColumn"] == column)
                if speakAll:
                    [startIndex, endIndex] = \
                        self._script.getSpreadSheetRowRange(obj)
                    for i in range(startIndex, endIndex+1):
                        cell = parentTable.getAccessibleAt(row, i)
                        showing = cell.getState().contains( \
                                      pyatspi.STATE_SHOWING)
                        if showing:
                            result.extend(self._getRealTableCell(cell, **args))
                else:
                    result.extend(self._getRealTableCell(obj, **args))
            else:
                result.extend(self._getRealTableCell(obj, **args))
        else:
            result.extend(speech_generator.SpeechGenerator._getTableCellRow(
                          self, obj, **args))
        return result
<|endoftext|>