<commit_before>#
# Copyright (c) 2008 rPath, Inc.
#
# This program is distributed under the terms of the Common Public License,
# version 1.0. A copy of this license should have been distributed with this
# source file in a file called LICENSE. If it is not present, the license
# is always available at http://www.rpath.com/permanent/licenses/CPL-1.0.
#
# 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 Common Public License for
# full details.
#

"""
Builder object implementation.
"""

import time
import logging

from conary import conarycfg, conaryclient

from rmake import plugins
from rmake.build import buildcfg
from rmake.cmdline import helper, monitor, commit

from updatebot import util
from updatebot.errors import JobFailedError, CommitFailedError

log = logging.getLogger('updateBot.build')

class Builder(object):
    """
    Class for wrapping the rMake api until we can switch to using rBuild.

    @param cfg: updateBot configuration object
    @type cfg: config.UpdateBotConfig
    """

    # R0903 - Too few public methods
    # pylint: disable-msg=R0903

    def __init__(self, cfg):
        self._cfg = cfg

        self._ccfg = conarycfg.ConaryConfiguration(readConfigFiles=False)
        self._ccfg.read(util.join(self._cfg.configPath, 'conaryrc'))
        self._ccfg.dbPath = ':memory:'
        self._ccfg.initializeFlavors()

        self._client = conaryclient.ConaryClient(self._ccfg)

        # Get default pluginDirs from the rmake cfg object, setup the plugin
        # manager, then create a new rmake config object so that rmakeUser
        # will be parsed correctly.
        rmakeCfg = buildcfg.BuildConfiguration(readConfigFiles=False)
        pluginMgr = plugins.PluginManager(rmakeCfg.pluginDirs)
        pluginMgr.loadPlugins()
        pluginMgr.callClientHook('client_preInit', self, [])

        self._rmakeCfg = buildcfg.BuildConfiguration(readConfigFiles=False)
        self._rmakeCfg.read(util.join(self._cfg.configPath, 'rmakerc'))
        self._rmakeCfg.useConaryConfig(self._ccfg)

        self._helper = helper.rMakeHelper(buildConfig=self._rmakeCfg)

    def build(self, troveSpecs):
        """
        Build a list of troves.
        @param troveSpecs: list of trove specs
        @type troveSpecs: [(name, versionObj, flavorObj), ...]
        @return troveMap: dictionary of troveSpecs to built troves
        """

        # Build all troves in defined contexts.
        troves = []
        for name, version, flavor in troveSpecs:
            # Don't set context for groups, they will already have the
            # correct flavors.
            if name.startswith('group-'):
                troves.append((name, version, flavor))
            else:
                # Build all packages as x86 and x86_64.
                for context in self._cfg.archContexts:
                    troves.append((name, version, flavor, context))

        jobId = self._startJob(troves)
        self._monitorJob(jobId)
        self._sanityCheckJob(jobId)
        trvMap = self._commitJob(jobId)

        # Format trvMap into something more usefull.
        # {(name, version, None): set([(name, version, flavor), ...])}
        ret = {}
        for sn, sv, sf, c in trvMap.iterkeys():
            n = sn.split(':')[0]
            if (n, sv, None) not in ret:
                ret[(n, sv, None)] = set()
            ret[(n, sv, None)].update(set(trvMap[(sn, sv, sf, c)]))

        return ret

    def _startJob(self, troveSpecs):
        """
        Create and start a rMake build.
        @param troveSpecs: list of trove specs
        @type troveSpecs: [(name, versionObj, flavorObj), ...]
        @return integer jobId
        """

        # Create rMake job
        log.info('Creating build job: %s' % (troveSpecs, ))
        job = self._helper.createBuildJob(troveSpecs)
        jobId = self._helper.buildJob(job)
        log.info('Started jobId: %s' % jobId)

        return jobId

    def _monitorJob(self, jobId):
        """
        Monitor job status, block until complete.
        @param jobId: rMake job ID
        @type jobId: integer
        """

        # Watch build, wait for completion
        monitor.monitorJob(self._helper.client, jobId,
            exitOnFinish=True, displayClass=_StatusOnlyDisplay)

    def _sanityCheckJob(self, jobId):
        """
        Verify the status of a job.
        @param jobId: rMake job ID
        @type jobId: integer
        """

        # Check for errors
        job = self._helper.getJob(jobId)
        if job.isFailed():
            log.error('Job %d failed', jobId)
            raise JobFailedError(jobId=jobId, why='Job failed')
        elif not job.isFinished():
            log.error('Job %d is not done, yet watch returned early!', jobId)
            raise JobFailedError(jobId=jobId, why='Job not done')
        elif not list(job.iterBuiltTroves()):
            log.error('Job %d has no built troves', jobId)
            raise JobFailedError(jobId=jobId, why='Job built no troves')

    def _commitJob(self, jobId):
        """
        Commit completed job.
        @param jobId: rMake job ID
        @type jobId: integer
        @return troveMap: dictionary of troveSpecs to built troves
        """

        # Do the commit
        startTime = time.time()
        job = self._helper.getJob(jobId)
        log.info('Starting commit of job %d', jobId)

        self._helper.client.startCommit([jobId, ])
        succeeded, data = commit.commitJobs(self._client,
                                            [job, ],
                                            self._rmakeCfg.reposName,
                                            self._cfg.commitMessage)

        if not succeeded:
            self._helper.client.commitFailed([jobId, ], data)
            raise CommitFailedError(jobId=job.jobId, why=data)

        log.info('Commit of job %d completed in %.02f seconds',
                 jobId, time.time() - startTime)

        troveMap = {}
        for troveTupleDict in data.itervalues():
            for buildTroveTuple, committedList in troveTupleDict.iteritems():
                troveMap[buildTroveTuple] = committedList

        self._helper.client.commitSucceeded(data)

        return troveMap

    def _registerCommand(self, *args, **kwargs):
        'Fake rMake hook'

class _StatusOnlyDisplay(monitor.JobLogDisplay):
    """
    Display only job and trove status. No log output.

    Copied from bob3
    """

    # R0901 - Too many ancestors
    # pylint: disable-msg=R0901

    def _troveLogUpdated(self, (jobId, troveTuple), state, status):
        """
        Don't care about trove logs
        """

    def _trovePreparingChroot(self, (jobId, troveTuple), host, path):
        """
        Don't care about resolving/installing chroot
        """
<commit_msg>make module more useful to other applications and for importing<commit_after>#
# Copyright (c) 2008 rPath, Inc.
#
# This program is distributed under the terms of the Common Public License,
# version 1.0. A copy of this license should have been distributed with this
# source file in a file called LICENSE. If it is not present, the license
# is always available at http://www.rpath.com/permanent/licenses/CPL-1.0.
#
# 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 Common Public License for
# full details.
#

"""
Builder object implementation.
"""

import time
import logging

from conary import conarycfg, conaryclient

from rmake import plugins
from rmake.build import buildcfg
from rmake.cmdline import helper, monitor, commit

from updatebot import util
from updatebot.errors import JobFailedError, CommitFailedError

log = logging.getLogger('updateBot.build')

class Builder(object):
    """
    Class for wrapping the rMake api until we can switch to using rBuild.

    @param cfg: updateBot configuration object
    @type cfg: config.UpdateBotConfig
    """

    def __init__(self, cfg):
        self._cfg = cfg

        self._ccfg = conarycfg.ConaryConfiguration(readConfigFiles=False)
        self._ccfg.read(util.join(self._cfg.configPath, 'conaryrc'))
        self._ccfg.dbPath = ':memory:'
        self._ccfg.initializeFlavors()

        self._client = conaryclient.ConaryClient(self._ccfg)

        # Get default pluginDirs from the rmake cfg object, setup the plugin
        # manager, then create a new rmake config object so that rmakeUser
        # will be parsed correctly.
        rmakeCfg = buildcfg.BuildConfiguration(readConfigFiles=False)
        pluginMgr = plugins.PluginManager(rmakeCfg.pluginDirs)
        pluginMgr.loadPlugins()
        pluginMgr.callClientHook('client_preInit', self, [])

        self._rmakeCfg = buildcfg.BuildConfiguration(readConfigFiles=False)
        self._rmakeCfg.read(util.join(self._cfg.configPath, 'rmakerc'))
        self._rmakeCfg.useConaryConfig(self._ccfg)

        self._helper = helper.rMakeHelper(buildConfig=self._rmakeCfg)

    def build(self, troveSpecs):
        """
        Build a list of troves.
        @param troveSpecs: list of trove specs
        @type troveSpecs: [(name, versionObj, flavorObj), ...]
        @return troveMap: dictionary of troveSpecs to built troves
        """

        troves = self._formatInput(troveSpecs)
        jobId = self._startJob(troves)
        self._monitorJob(jobId)
        self._sanityCheckJob(jobId)
        trvMap = self._commitJob(jobId)
        ret = self._formatOutput(trvMap)
        return ret

    def buildmany(self, troveSpecs):
        """
        Build all packages in troveSpecs, 10 at a time, one per job.
        @param troveSpecs: list of trove specs
        @type troveSpecs: [(name, versionObj, flavorObj), ...]
        @return troveMap: dictionary of troveSpecs to built troves
        """

        id = 0
        jobs = {}
        for i, trv in enumerate(troveSpecs):
            if id not in jobs:
                jobs[id] = []

            jobs[id].append(trv)

            if i % 10 == 0:
                id += 1

        failed = set()
        results = {}
        for job in jobs.itervalues():
            res, fail = self._buildmany(job)
            failed.update(fail)
            results.update(res)

        return results, failed

    def _buildmany(self, troveSpecs):
        """
        Build a list of packages, one per job.
        @param troveSpecs: list of trove specs
        @type troveSpecs: [(name, versionObj, flavorObj), ...]
        @return troveMap: dictionary of troveSpecs to built troves
        """

        jobs = {}
        for trv in troveSpecs:
            jobs[trv] = self.start([trv, ])

        for trv, jobId in jobs.iteritems():
            job = self._helper.getJob(jobId)
            if not job.isFinished() and not job.isFailed():
                self.watch(jobId)

        failed = set()
        results = {}
        for trv, jobId in jobs.iteritems():
            job = self._helper.getJob(jobId)
            if job.isFailed():
                failed.add(trv)
            elif job.isFinished():
                try:
                    res = self.commit(jobId)
                    results.update(res)
                except JobFailedError:
                    failed.add(trv)

        return results, failed

    def start(self, troveSpecs):
        """
        Public version of start job that starts a job without monitoring.
        @param troveSpecs: set of name, version, flavor tuples
        @type troveSpecs: set([(name, version, flavor), ..])
        @return jobId: integer
        """

        troves = self._formatInput(troveSpecs)
        jobId = self._startJob(troves)
        return jobId

    def watch(self, jobId):
        """
        Watch a build.
        @param jobId: rMake job ID
        @type jobId: integer
        """

        self._monitorJob(jobId)

    def commit(self, jobId):
        """
        Public commit from jobId with sanity checking.
        @param jobId: id of the build job to commit
        @type jobId: integer
        @return dict((name, version, flavor)=
                     set([(name, version, flavor), ...])
        """

        self._sanityCheckJob(jobId)
        trvMap = self._commitJob(jobId)
        ret = self._formatOutput(trvMap)
        return ret

    def _formatInput(self, troveSpecs):
        """
        Formats the list of troves provided into a job list for rMake.
        @param troveSpecs: set of name, version, flavor tuples
        @type troveSpecs: set([(name, version, flavor), ..])
        @return list((name, version, flavor, context), ...)
        """

        # Build all troves in defined contexts.
        troves = []
        for name, version, flavor in troveSpecs:
            # Don't set context for groups, they will already have the
            # correct flavors.
            if name.startswith('group-'):
                troves.append((name, version, flavor))
            else:
                # Build all packages as x86 and x86_64.
                for context in self._cfg.archContexts:
                    troves.append((name, version, flavor, context))

        return troves

    def _startJob(self, troveSpecs):
        """
        Create and start a rMake build.
        @param troveSpecs: list of trove specs
        @type troveSpecs: [(name, versionObj, flavorObj), ...]
        @return integer jobId
        """

        # Create rMake job
        log.info('Creating build job: %s' % (troveSpecs, ))
        job = self._helper.createBuildJob(troveSpecs)
        jobId = self._helper.buildJob(job)
        log.info('Started jobId: %s' % jobId)

        return jobId

    def _monitorJob(self, jobId):
        """
        Monitor job status, block until complete.
        @param jobId: rMake job ID
        @type jobId: integer
        """

        # Watch build, wait for completion
        monitor.monitorJob(self._helper.client, jobId,
            exitOnFinish=True, displayClass=_StatusOnlyDisplay)

    def _sanityCheckJob(self, jobId):
        """
        Verify the status of a job.
        @param jobId: rMake job ID
        @type jobId: integer
        """

        # Check for errors
        job = self._helper.getJob(jobId)
        if job.isFailed():
            log.error('Job %d failed', jobId)
            raise JobFailedError(jobId=jobId, why=job.status)
        elif not job.isFinished():
            log.error('Job %d is not done, yet watch returned early!', jobId)
            raise JobFailedError(jobId=jobId, why=job.status)
        elif not list(job.iterBuiltTroves()):
            log.error('Job %d has no built troves', jobId)
            raise JobFailedError(jobId=jobId, why='No troves found in job')

    def _commitJob(self, jobId):
        """
        Commit completed job.
        @param jobId: rMake job ID
        @type jobId: integer
        @return troveMap: dictionary of troveSpecs to built troves
        """

        # Do the commit
        startTime = time.time()
        job = self._helper.getJob(jobId)
        log.info('Starting commit of job %d', jobId)

        self._helper.client.startCommit([jobId, ])
        succeeded, data = commit.commitJobs(self._helper.getConaryClient(),  #self._client,
                                            [job, ],
                                            self._rmakeCfg.reposName,
                                            self._cfg.commitMessage)

        if not succeeded:
            self._helper.client.commitFailed([jobId, ], data)
            raise CommitFailedError(jobId=job.jobId, why=data)

        log.info('Commit of job %d completed in %.02f seconds',
                 jobId, time.time() - startTime)

        troveMap = {}
        for troveTupleDict in data.itervalues():
            for buildTroveTuple, committedList in troveTupleDict.iteritems():
                troveMap[buildTroveTuple] = committedList

        self._helper.client.commitSucceeded(data)

        return troveMap

    @staticmethod
    def _formatOutput(trvMap):
        """
        Format the output from rMake into something keyd off of the original
        input.
        @param trvMap: dictionary mapping of source to binary
        @type trvMap: dict((name, version, flavor, context)=
                            set([(name, version, flavor), ...]))
        @return dict((name, version, flavor)=
                     set([(name, version, flavor), ...])
        """

        # {(name, version, None): set([(name, version, flavor), ...])}
        ret = {}
        for sn, sv, sf, c in trvMap.iterkeys():
            n = sn.split(':')[0]
            if (n, sv, None) not in ret:
                ret[(n, sv, None)] = set()
            ret[(n, sv, None)].update(set(trvMap[(sn, sv, sf, c)]))

        return ret

    def _registerCommand(self, *args, **kwargs):
        'Fake rMake hook'

class _StatusOnlyDisplay(monitor.JobLogDisplay):
    """
    Display only job and trove status. No log output.

    Copied from bob3
    """

    # R0901 - Too many ancestors
    # pylint: disable-msg=R0901

    def _troveLogUpdated(self, (jobId, troveTuple), state, status):
        """
        Don't care about trove logs
        """

    def _trovePreparingChroot(self, (jobId, troveTuple), host, path):
        """
        Don't care about resolving/installing chroot
        """
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Django settings for asylum project.

For more information on this file, see
https://docs.djangoproject.com/en/dev/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/dev/ref/settings/
"""
from __future__ import absolute_import, unicode_literals

import os.path
import environ

ROOT_DIR = environ.Path(__file__) - 3  # (/a/b/myfile.py - 3 = /)
APPS_DIR = ROOT_DIR.path('asylum')

env = environ.Env()
# If the project root contains a .env file, read it
if os.path.isfile(str(ROOT_DIR + '.env')):
    environ.Env.read_env(str(ROOT_DIR + '.env'))

# APP CONFIGURATION
# ------------------------------------------------------------------------------
DJANGO_APPS = (
    # Default Django apps:
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Useful template tags:
    # 'django.contrib.humanize',

    # Admin
    'django.contrib.admin',
)
THIRD_PARTY_APPS = (
    'crispy_forms',  # Form layouts
    'bootstrap3',
    'reversion',
)

# Apps specific for this project go here.
LOCAL_APPS = (
    # Your stuff: custom apps go here
    'members',
    'access',
    'creditor',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

# MIDDLEWARE CONFIGURATION
# ------------------------------------------------------------------------------
MIDDLEWARE_CLASSES = (
    # Make sure djangosecure.middleware.SecurityMiddleware is listed first
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

# MIGRATIONS CONFIGURATION
# ------------------------------------------------------------------------------
MIGRATION_MODULES = {
    'sites': 'asylum.contrib.sites.migrations'
}

# DEBUG
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = env.bool("DJANGO_DEBUG", False)

# FIXTURE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS
FIXTURE_DIRS = (
    str(APPS_DIR.path('fixtures')),
)

# EMAIL CONFIGURATION
# ------------------------------------------------------------------------------
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend')

# MANAGER CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (
    ("""Anders Innovations""", 'support@anders.fi'),
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS

# DATABASE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
    # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
    'default': env.db("DATABASE_URL", default="postgres:///asylum"),
}
DATABASES['default']['ATOMIC_REQUESTS'] = True

# GENERAL CONFIGURATION
# ------------------------------------------------------------------------------
# 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.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'Europe/Helsinki'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = 'fi-FI'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True

# TEMPLATE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#templates
_TEMPLATE_CONTEXT_PROCESSORS = [
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.template.context_processors.i18n',
    'django.template.context_processors.media',
    'django.template.context_processors.static',
    'django.template.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    # Your stuff: custom template context processors go here
]

TEMPLATES = [
    {
        'BACKEND': "django_jinja.backend.Jinja2",
        'APP_DIRS': False,
        'DIRS': [
            str(APPS_DIR.path('templates')),
        ],
        'OPTIONS': {
            'match_extension': '.jinja',
            'context_processors': _TEMPLATE_CONTEXT_PROCESSORS,
            'newstyle_gettext': True
        }
    },
    {
        # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
        'APP_DIRS': False,
        'DIRS': [
            str(APPS_DIR.path('templates')),
        ],
        'OPTIONS': {
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
            'debug': DEBUG,
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
            # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
            'loaders': [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
            ],
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
            'context_processors': _TEMPLATE_CONTEXT_PROCESSORS,
       },
    },
]

# See: http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs
CRISPY_TEMPLATE_PACK = 'bootstrap3'

# STATIC FILE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = str(ROOT_DIR('staticfiles'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = '/static/'

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
STATICFILES_DIRS = (
    str(APPS_DIR.path('static')),
)

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

# MEDIA CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
MEDIA_ROOT = str(APPS_DIR('media'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
MEDIA_URL = '/media/'

# URL Configuration
# ------------------------------------------------------------------------------
ROOT_URLCONF = 'config.urls'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
WSGI_APPLICATION = 'config.wsgi.application'

# AUTHENTICATION CONFIGURATION
# ------------------------------------------------------------------------------
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',

)

# SLUGLIFIER
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'

# Location of root django.contrib.admin URL, use {% url 'admin:index' %}
ADMIN_URL = r'^admin/'

# Your common stuff: Below this line define 3rd party library settings
APPLICATION_RULES_URL = env('APPLICATION_RULES_URL', default='http://hacklab.fi/')

# Give path to a class implementing the api outlined in member.handers baseclasses
MEMBERAPPLICATION_CALLBACKS_HANDLER=env('MEMBERAPPLICATION_CALLBACKS_HANDLER', default=None)
MEMBER_CALLBACKS_HANDLER=env('MEMBER_CALLBACKS_HANDLER', default=None)
<commit_msg>use hacklab.fi brand<commit_after># -*- coding: utf-8 -*-
"""
Django settings for asylum project.

For more information on this file, see
https://docs.djangoproject.com/en/dev/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/dev/ref/settings/
"""
from __future__ import absolute_import, unicode_literals

import os.path
import environ

ROOT_DIR = environ.Path(__file__) - 3  # (/a/b/myfile.py - 3 = /)
APPS_DIR = ROOT_DIR.path('asylum')

env = environ.Env()
# If the project root contains a .env file, read it
if os.path.isfile(str(ROOT_DIR + '.env')):
    environ.Env.read_env(str(ROOT_DIR + '.env'))

# APP CONFIGURATION
# ------------------------------------------------------------------------------
DJANGO_APPS = (
    # Default Django apps:
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Useful template tags:
    # 'django.contrib.humanize',

    # Admin
    'django.contrib.admin',
)
THIRD_PARTY_APPS = (
    'crispy_forms',  # Form layouts
    'bootstrap3',
    'reversion',
)

# Apps specific for this project go here.
LOCAL_APPS = (
    # Your stuff: custom apps go here
    'members',
    'access',
    'creditor',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

# MIDDLEWARE CONFIGURATION
# ------------------------------------------------------------------------------
MIDDLEWARE_CLASSES = (
    # Make sure djangosecure.middleware.SecurityMiddleware is listed first
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

# MIGRATIONS CONFIGURATION
# ------------------------------------------------------------------------------
MIGRATION_MODULES = {
    'sites': 'asylum.contrib.sites.migrations'
}

# DEBUG
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = env.bool("DJANGO_DEBUG", False)

# FIXTURE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS
FIXTURE_DIRS = (
    str(APPS_DIR.path('fixtures')),
)

# EMAIL CONFIGURATION
# ------------------------------------------------------------------------------
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend')

# MANAGER CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (
    ("""Hacklab.fi""", 'info@hacklab.fi'),
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS

# DATABASE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
    # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
    'default': env.db("DATABASE_URL", default="postgres:///asylum"),
}
DATABASES['default']['ATOMIC_REQUESTS'] = True

# GENERAL CONFIGURATION
# ------------------------------------------------------------------------------
# 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.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'Europe/Helsinki'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = 'fi-FI'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True

# TEMPLATE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#templates
_TEMPLATE_CONTEXT_PROCESSORS = [
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.template.context_processors.i18n',
    'django.template.context_processors.media',
    'django.template.context_processors.static',
    'django.template.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    # Your stuff: custom template context processors go here
]

TEMPLATES = [
    {
        'BACKEND': "django_jinja.backend.Jinja2",
        'APP_DIRS': False,
        'DIRS': [
            str(APPS_DIR.path('templates')),
        ],
        'OPTIONS': {
            'match_extension': '.jinja',
            'context_processors': _TEMPLATE_CONTEXT_PROCESSORS,
            'newstyle_gettext': True
        }
    },
    {
        # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
        'APP_DIRS': False,
        'DIRS': [
            str(APPS_DIR.path('templates')),
        ],
        'OPTIONS': {
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
            'debug': DEBUG,
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
            # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
            'loaders': [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
            ],
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
            'context_processors': _TEMPLATE_CONTEXT_PROCESSORS,
       },
    },
]

# See: http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs
CRISPY_TEMPLATE_PACK = 'bootstrap3'

# STATIC FILE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = str(ROOT_DIR('staticfiles'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = '/static/'

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
STATICFILES_DIRS = (
    str(APPS_DIR.path('static')),
)

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

# MEDIA CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
MEDIA_ROOT = str(APPS_DIR('media'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
MEDIA_URL = '/media/'

# URL Configuration
# ------------------------------------------------------------------------------
ROOT_URLCONF = 'config.urls'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
WSGI_APPLICATION = 'config.wsgi.application'

# AUTHENTICATION CONFIGURATION
# ------------------------------------------------------------------------------
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',

)

# SLUGLIFIER
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'

# Location of root django.contrib.admin URL, use {% url 'admin:index' %}
ADMIN_URL = r'^admin/'

# Your common stuff: Below this line define 3rd party library settings
APPLICATION_RULES_URL = env('APPLICATION_RULES_URL', default='http://hacklab.fi/')

# Give path to a class implementing the api outlined in member.handers baseclasses
MEMBERAPPLICATION_CALLBACKS_HANDLER=env('MEMBERAPPLICATION_CALLBACKS_HANDLER', default=None)
MEMBER_CALLBACKS_HANDLER=env('MEMBER_CALLBACKS_HANDLER', default=None)
<|endoftext|>


<commit_before>from django.db import models
import lxml.etree
import datetime
import time
import urllib2

URL_CARTO = 'http://www.bicikelj.si/service/carto'
URL_STATION = 'http://www.bicikelj.si/service/stationdetails/%s'

class BicikeljData(models.Model):
	timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
	json_data = models.TextField()

def _parse_main_xml(data):
	json = {}
	carto = lxml.etree.fromstring(data)

	count = 0
	for marker in carto.xpath('//carto/markers/marker'):
		assert len(marker.getchildren()) == 0, 'Marker has children!? ' + repr(marker.getchildren())
		station_id = unicode(marker.attrib['number'])
		json[station_id] = dict(marker.attrib)

		count += 1
	assert count > 0, 'No markers found in main XML!?'

	return json

def _parse_station_xml(data):
	sta_xml = lxml.etree.fromstring(data)
	sta_dict = {}
	for elem in sta_xml.xpath('//station/*'):
		sta_dict[elem.tag] = elem.text
	assert list(sorted(sta_dict.keys())) == ['available', 'free', 'ticket', 'total'], 'Missing or added keys in station XML!?'
	return sta_dict

def fetch_xmls():
	main_xml = urllib2.urlopen(URL_CARTO, timeout=10).read()
	json = _parse_main_xml(main_xml)

	for k, v in json.iteritems():
		sta_xml_data = urllib2.urlopen(URL_STATION % k, timeout=10).read()
		sta_dict = _parse_station_xml(sta_xml_data)
		v['station'] = sta_dict
		v['station_valid'] = not int(sta_dict['total']) == 0

	now = datetime.datetime.now()
	resp = {
		'markers': json,
		'updated': time.mktime(now.timetuple())
		}
	return now, resp

<commit_msg>Fix for changed url.<commit_after>from django.db import models
import lxml.etree
import datetime
import time
import urllib2

URL_CARTO = 'http://www.bicikelj.si/service/carto'
URL_STATION = 'http://www.bicikelj.si/service/stationdetails/ljubljana/%s'

class BicikeljData(models.Model):
	timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
	json_data = models.TextField()

def _parse_main_xml(data):
	json = {}
	carto = lxml.etree.fromstring(data)

	count = 0
	for marker in carto.xpath('//carto/markers/marker'):
		assert len(marker.getchildren()) == 0, 'Marker has children!? ' + repr(marker.getchildren())
		station_id = unicode(marker.attrib['number'])
		json[station_id] = dict(marker.attrib)

		count += 1
	assert count > 0, 'No markers found in main XML!?'

	return json

def _parse_station_xml(data):
	sta_xml = lxml.etree.fromstring(data)
	sta_dict = {}
	for elem in sta_xml.xpath('//station/*'):
		sta_dict[elem.tag] = elem.text
	assert list(sorted(sta_dict.keys())) == ['available', 'free', 'ticket', 'total'], 'Missing or added keys in station XML!?'
	return sta_dict

def fetch_xmls():
	main_xml = urllib2.urlopen(URL_CARTO, timeout=10).read()
	json = _parse_main_xml(main_xml)

	for k, v in json.iteritems():
		sta_xml_data = urllib2.urlopen(URL_STATION % k, timeout=10).read()
		sta_dict = _parse_station_xml(sta_xml_data)
		v['station'] = sta_dict
		v['station_valid'] = not int(sta_dict['total']) == 0

	now = datetime.datetime.now()
	resp = {
		'markers': json,
		'updated': time.mktime(now.timetuple())
		}
	return now, resp

<|endoftext|>


<commit_before>"""
A reflector backend module for the satosa proxy
"""
from datetime import datetime

from satosa.internal import AuthenticationInformation
from satosa.internal import InternalData
from satosa.metadata_creation.description import MetadataDescription
from satosa.backends.base import BackendModule

class ReflectorBackend(BackendModule):
    """
    A reflector backend module
    """

    def __init__(self, outgoing, internal_attributes, config, base_url, name):
        """
        :type outgoing:
        (satosa.context.Context, satosa.internal.InternalData) -> satosa.response.Response
        :type internal_attributes: dict[str, dict[str, list[str] | str]]
        :type config: dict[str, Any]
        :type base_url: str
        :type name: str

        :param outgoing: Callback should be called by the module after
                                   the authorization in the backend is done.
        :param internal_attributes: Internal attribute map
        :param config: The module config
        :param base_url: base url of the service
        :param name: name of the plugin
        """
        super().__init__(outgoing, internal_attributes, base_url, name)

    def start_auth(self, context, internal_req):
        """
        See super class method satosa.backends.base.BackendModule#start_auth

        :type context: satosa.context.Context
        :type internal_req: satosa.internal.InternalData
        :rtype: satosa.response.Response
        """

        timestamp = datetime.utcnow().timestamp()
        auth_info = AuthenticationInformation(
            'reflector', timestamp, 'reflector',
        )

        internal_resp = InternalData(
            auth_info=auth_info,
            attributes={},
            subject_type=None,
            subject_id='reflector',
        )

        return self.auth_callback_func(context, internal_resp)

    def register_endpoints(self):
        """
        See super class method satosa.backends.base.BackendModule#register_endpoints
        :rtype list[(str, ((satosa.context.Context, Any) -> Any, Any))]
        """
        url_map = []
        return url_map

    def get_metadata_desc(self):
        """
        See super class satosa.backends.backend_base.BackendModule#get_metadata_desc
        :rtype: satosa.metadata_creation.description.MetadataDescription
        """
        entity_descriptions = []
        description = MetadataDescription(urlsafe_b64encode('reflector'.encode("utf-8")).decode("utf-8"))
        description.organization = 'reflector'

        entity_descriptions.append(description)
        return entity_descriptions
<commit_msg>Format code and use constants<commit_after>"""
A reflector backend module for the satosa proxy
"""
from datetime import datetime

from satosa.internal import AuthenticationInformation
from satosa.internal import InternalData
from satosa.metadata_creation.description import MetadataDescription
from satosa.backends.base import BackendModule

class ReflectorBackend(BackendModule):
    """
    A reflector backend module
    """

    ENTITY_ID = ORG_NAME = AUTH_CLASS_REF = SUBJECT_ID = "reflector"

    def __init__(self, outgoing, internal_attributes, config, base_url, name):
        """
        :type outgoing:
        (satosa.context.Context, satosa.internal.InternalData) -> satosa.response.Response
        :type internal_attributes: dict[str, dict[str, list[str] | str]]
        :type config: dict[str, Any]
        :type base_url: str
        :type name: str

        :param outgoing: Callback should be called by the module after
                                   the authorization in the backend is done.
        :param internal_attributes: Internal attribute map
        :param config: The module config
        :param base_url: base url of the service
        :param name: name of the plugin
        """
        super().__init__(outgoing, internal_attributes, base_url, name)

    def start_auth(self, context, internal_req):
        """
        See super class method satosa.backends.base.BackendModule#start_auth

        :type context: satosa.context.Context
        :type internal_req: satosa.internal.InternalData
        :rtype: satosa.response.Response
        """

        timestamp = datetime.utcnow().timestamp()
        auth_info = AuthenticationInformation(
            auth_class_ref=ReflectorBackend.AUTH_CLASS_REF,
            timestamp=timestamp,
            issuer=ReflectorBackend.ENTITY_ID,
        )

        internal_resp = InternalData(
            auth_info=auth_info,
            attributes={},
            subject_type=None,
            subject_id=ReflectorBackend.SUBJECT_ID,
        )

        return self.auth_callback_func(context, internal_resp)

    def register_endpoints(self):
        """
        See super class method satosa.backends.base.BackendModule#register_endpoints
        :rtype list[(str, ((satosa.context.Context, Any) -> Any, Any))]
        """
        url_map = []
        return url_map

    def get_metadata_desc(self):
        """
        See super class satosa.backends.backend_base.BackendModule#get_metadata_desc
        :rtype: satosa.metadata_creation.description.MetadataDescription
        """
        entity_descriptions = []
        description = MetadataDescription(
            urlsafe_b64encode(ReflectorBackend.ENTITY_ID.encode("utf-8")).decode(
                "utf-8"
            )
        )
        description.organization = ReflectorBackend.ORG_NAME

        entity_descriptions.append(description)
        return entity_descriptions
<|endoftext|>


<commit_before># encoding: utf-8
from decimal import Decimal as D
import logging

from django.conf import settings
from django.apps import apps
from django.views import generic
from django.contrib import messages
from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponseBadRequest
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _

from oscar.core.loading import get_class, get_classes

from .models import SystemPayTransaction
from .facade import Facade
from .gateway import Gateway
from .exceptions import *

logger = logging.getLogger('systempay')

Basket = apps.get_model('basket', 'Basket')
Order = apps.get_model('order', 'Order')
Source = apps.get_model('payment', 'Source')
SourceType = apps.get_model('payment', 'SourceType')

PaymentDetailsView, OrderPlacementMixin, CheckoutSessionMixin = get_classes(
    'checkout.views',
    ['PaymentDetailsView', 'OrderPlacementMixin', 'CheckoutSessionMixin'])
PaymentError, UnableToTakePayment = get_classes(
    'payment.exceptions',
    ['PaymentError', 'UnableToTakePayment'])

EventHandler = get_class('order.processing', 'EventHandler')

class SecureRedirectView(CheckoutSessionMixin, generic.DetailView):
    """
    Simple Redirect Page initiating the transaction throughout
    a fulfilled form of the payment order send to the SystemPay
    checkout.
    """
    template_name = 'systempay/secure_redirect.html'
    context_object_name = 'order'

    _order = None
    _form = None

    def get_object(self):
        if self._order is not None:
            return self._order

        order = None
        if self.request.user.is_superuser:
            if 'order_number' in self.request.GET:
                order = Order.objects.get(
                    number=self.request.GET['order_number'])
            elif 'order_id' in self.request.GET:
                order = Order.objects.get(
                    id=self.request.GET['order_id'])

        if not order:
            if 'checkout_order_id' in self.request.session:
                order = Order.objects.get(
                    pk=self.request.session['checkout_order_id'])
            else:
                raise Http404(_("No order found"))

        self._order = order
        return order

    def get_form(self):
        if self._form is not None:
            return self._form
        order = self.get_object()
        self._form = Facade().get_submit_form_populated_with_order(order)
        return self._form

    def get(self, *args, **kwargs):
        order = self.get_object()
        form = self.get_form()
        Facade().save_submit_txn(order.number, order.total_incl_tax, form)
        response = super(SecureRedirectView, self).get(*args, **kwargs)

        # Flush of all session data
        self.checkout_session.flush()

        return response

    def get_context_data(self, **kwargs):
        ctx = super(SecureRedirectView, self).get_context_data(**kwargs)
        ctx['submit_form'] = self.get_form()
        ctx['SYSTEMPAY_GATEWAY_URL'] = Gateway.URL
        return ctx

class PlaceOrderView(PaymentDetailsView):
    # template_name = 'systempay/preview.html'
    template_name = 'checkout/payment_details.html'
    template_name_preview = 'systempay/preview.html'
    # template_name_preview = 'checkout/preview.html'
    preview = True

    def post(self, request, *args, **kwargs):

        if self.preview:
            if request.POST.get('action', '') == 'place_order':
                return self.submit(**self.build_submission())
            return self.render_preview(request)

        return self.get(request, *args, **kwargs)

    def handle_payment(self, order_number, total_incl_tax, **kwargs):
        """
        Skip this step when placing the order, it'll be handle by the ipn
        received from server to server.
        Only record the allocated amount.
        """
        # Record payment source
        payment_method = self.checkout_session.payment_method()
        if payment_method is None:
            messages.error(self.request, _("Please choose a payment method."))
            return HttpResponseRedirect(reverse('checkout:payment-method'))

        source_type, is_created = SourceType.objects.get_or_create(
            code=payment_method)
        source = Source(source_type=source_type,
                        currency=kwargs.get('currency'),
                        amount_allocated=total_incl_tax,
                        amount_debited=D(0))
        self.add_payment_source(source)

    def handle_successful_order(self, order, send_confirmation_message=True):
        """
        Handle the various steps required after an order has been successfully
        placed.

        Override this view if you want to perform custom actions when an
        order is submitted.
        """
        # Send confirmation message (normally an email)
        # if send_confirmation_message:
        #     self.send_confirmation_message(order)

        # Delay the flush of all session data
        # self.checkout_session.flush()

        # Save order id in session so secure redirect page can load it
        self.request.session['checkout_order_id'] = order.id

        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse('systempay:secure-redirect')

class ResponseView(generic.RedirectView):
    def get_order(self):
        # We allow superusers to force an order thank-you page for testing
        # http://localhost:8001/systempay/handle-ipn?vads_amount=330425&vads_auth_mode=FULL&vads_auth_number=3fea71&vads_auth_result=00&vads_capture_delay=0&vads_card_brand=CB&vads_card_number=497010XXXXXX0000&vads_payment_certificate=febb57ed6bb93cc6b3f14a1ccbfb3cee143c4c75&vads_ctx_mode=TEST&vads_currency=978&vads_effective_amount=330425&vads_site_id=21908992&vads_trans_date=20170117115209&vads_trans_id=427300&vads_trans_uuid=c4b5b52c439d44428aba6c489cd87a6c&vads_validation_mode=0&vads_version=V2&vads_warranty_result=YES&vads_payment_src=EC&vads_order_id=100024&vads_order_info=&vads_order_info2=&vads_order_info3=&vads_cust_email=bastien.roques1%40gmail.com&vads_cust_id=1&vads_cust_name=Bastien+Roques&vads_cust_country=&vads_contrib=&vads_user_info=&vads_cust_state=&vads_ship_to_name=jean-s%C3%A9bastien+r%C3%B4ques&vads_ship_to_street=34+rue+roucher&vads_ship_to_street2=34+rue+roucher&vads_ship_to_city=Montpellier&vads_ship_to_zip=34000&vads_ship_to_country=FR&vads_sequence_number=1&vads_contract_used=5591192&vads_trans_status=AUTHORISED&vads_expiry_month=6&vads_expiry_year=2018&vads_bank_product=F&vads_pays_ip=FR&vads_presentation_date=20170117115216&vads_effective_creation_date=20170117115216&vads_operation_type=DEBIT&vads_threeds_enrolled=Y&vads_threeds_cavv=Q2F2dkNhdnZDYXZ2Q2F2dkNhdnY%3D&vads_threeds_eci=05&vads_threeds_xid=UEZPM01tcFVxOUVpSnh0NzB4MTc%3D&vads_threeds_cavvAlgorithm=2&vads_threeds_status=Y&vads_threeds_sign_valid=1&vads_threeds_error_code=&vads_threeds_exit_status=10&vads_risk_control=&vads_result=00&vads_extra_result=&vads_card_country=FR&vads_language=&vads_action_mode=INTERACTIVE&vads_cust_address=&vads_cust_cell_phone=&vads_cust_city=&vads_payment_config=SINGLE&vads_page_action=PAYMENT&vads_cust_phone=&vads_cust_title=&vads_cust_zip=&signature=2a7786d4e622bec989278852910268bd0aabf11f

        order = None
        if self.request.user.is_superuser:
            if 'order_number' in self.request.GET:
                order = Order._default_manager.get(
                    number=self.request.GET['order_number'])
            elif 'order_id' in self.request.GET:
                order = Order._default_manager.get(
                    id=self.request.GET['orderid'])

        if not order:
            order_number = None
            if 'vads_order_id' in self.request.POST:
                order_number = self.request.POST['vads_order_id']
            elif 'vads_order_id' in self.request.GET:
                order_number = self.request.GET['vads_order_id']

            if not order_number:
                raise Http404(_("No order found"))

            try:
                order = Order._default_manager.get(number=order_number)
            except Order.DoesNotExist:
                raise Http404(_("The page requested seems outdated"))

        return order

class ReturnResponseView(ResponseView):
    def get_redirect_url(self, **kwargs):
        order = self.get_order()

        # check if the transaction exists
        txns = SystemPayTransaction.objects.filter(
            mode=SystemPayTransaction.MODE_RETURN,
            order_number=order.number
        ).order_by('-date_created')[:1]

        if not txns:
            messages.error(
                self.request,
                _("No response received from your bank for the moment. "
                  "Be patient, we'll get back to you as soon as we receive it.")
            )
        else:
            txn = txns[0]
            if txn.is_complete():  # check if the transaction has been complete
                messages.success(
                    self.request,
                    _("Your payment has been successfully validated.")
                )
            else:
                messages.error(
                    self.request,
                    _("Your payment has been rejected for the reason. You will "
                      "not be charged. Contact the support for more details.")
                )

        self.request.session['checkout_order_id'] = order.id
        return reverse('checkout:thank-you')

class CancelResponseView(ResponseView):
    def get_redirect_url(self, **kwargs):
        order = self.get_order()

        # cancel the order (to deallocate the products)
        handler = EventHandler()
        handler.handle_order_status_change(
            order, getattr(settings, 'OSCAR_STATUS_CANCELLED', None))

        # delete the order
        order.delete()

        # unfreeze the basket
        basket = Basket.objects.get(pk=order.basket_id)
        basket.thaw()

        messages.error(self.request, _("The transaction has be canceled"))
        return reverse('basket:summary')

class HandleIPN(OrderPlacementMixin, generic.View):
    def get(self, request, *args, **kwargs):
        if request.user and request.user.is_superuser:
            # Authorize admins for test purpose to copy the GET params
            #  to the POST dict
            request.POST = request.GET
            # from .test_vars import NOTIFICATION
            # request.POST = NOTIFICATION
            return self.post(request, *args, **kwargs)
        return HttpResponse()

    def post(self, request, *args, **kwargs):
        try:
            self.handle_ipn(request)
        except PaymentError as inst:
            return HttpResponseBadRequest(inst.message)
        return HttpResponse()

    def handle_ipn(self, request, **kwargs):
        """
        Complete payment.
        """
        # for k, v in request.POST.items():
        #     if k.startswith('vads'):
        #         print('{0:10} ==> {1:10}'.format(k, v))

        try:
            txn = Facade().handle_request(request)
            order = Order.objects.get(number=txn.order_number)

            source_type, is_created = SourceType.objects.get_or_create(
                code='systempay', name='SystemPay',
            )

            if txn.operation_type == SystemPayTransaction.OPERATION_TYPE_DEBIT:
                source = Source(source_type=source_type,
                                currency=txn.currency,
                                amount_allocated=D(0),
                                amount_debited=txn.amount,
                                reference=txn.reference)
                self.add_payment_source(source)

            elif txn.operation_type == SystemPayTransaction.OPERATION_TYPE_CREDIT:
                source = Source(source_type=source_type,
                                currency=txn.currency,
                                amount_allocated=D(0),
                                amount_refunded=txn.amount,
                                reference=txn.reference)
                self.add_payment_source(source)

            else:

                raise PaymentError(
                    _("Unknown operation type '%(operation_type)s'")
                    % {'operation_type': txn.operation_type})

            self.save_payment_details(order)

        except SystemPayError:
            raise
        except Order.DoesNotExist:
            logger.error(_("Unable to retrieve Order #%(order_number)s")
                         % {'order_number': txn.order_number})
<commit_msg>Remove wrong code from handle_payment in PlaceORder<commit_after># encoding: utf-8
from decimal import Decimal as D
import logging

from django.conf import settings
from django.apps import apps
from django.views import generic
from django.contrib import messages
from django.http import HttpResponse, Http404, HttpResponseRedirect, \
    HttpResponseBadRequest
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _

from oscar.core.loading import get_class, get_classes

from .models import SystemPayTransaction
from .facade import Facade
from .gateway import Gateway
from .exceptions import *

logger = logging.getLogger('systempay')

Basket = apps.get_model('basket', 'Basket')
Order = apps.get_model('order', 'Order')
Source = apps.get_model('payment', 'Source')
SourceType = apps.get_model('payment', 'SourceType')

PaymentDetailsView, OrderPlacementMixin, CheckoutSessionMixin = get_classes(
    'checkout.views',
    ['PaymentDetailsView', 'OrderPlacementMixin', 'CheckoutSessionMixin'])
PaymentError, UnableToTakePayment = get_classes(
    'payment.exceptions',
    ['PaymentError', 'UnableToTakePayment'])

EventHandler = get_class('order.processing', 'EventHandler')

class SecureRedirectView(CheckoutSessionMixin, generic.DetailView):
    """
    Simple Redirect Page initiating the transaction throughout
    a fulfilled form of the payment order send to the SystemPay
    checkout.
    """
    template_name = 'systempay/secure_redirect.html'
    context_object_name = 'order'

    _order = None
    _form = None

    def get_object(self):
        if self._order is not None:
            return self._order

        order = None
        if self.request.user.is_superuser:
            if 'order_number' in self.request.GET:
                order = Order.objects.get(
                    number=self.request.GET['order_number'])
            elif 'order_id' in self.request.GET:
                order = Order.objects.get(
                    id=self.request.GET['order_id'])

        if not order:
            if 'checkout_order_id' in self.request.session:
                order = Order.objects.get(
                    pk=self.request.session['checkout_order_id'])
            else:
                raise Http404(_("No order found"))

        self._order = order
        return order

    def get_form(self):
        if self._form is not None:
            return self._form
        order = self.get_object()
        self._form = Facade().get_submit_form_populated_with_order(order)
        return self._form

    def get(self, *args, **kwargs):
        order = self.get_object()
        form = self.get_form()
        Facade().save_submit_txn(order.number, order.total_incl_tax, form)
        response = super(SecureRedirectView, self).get(*args, **kwargs)

        # Flush of all session data
        self.checkout_session.flush()

        return response

    def get_context_data(self, **kwargs):
        ctx = super(SecureRedirectView, self).get_context_data(**kwargs)
        ctx['submit_form'] = self.get_form()
        ctx['SYSTEMPAY_GATEWAY_URL'] = Gateway.URL
        return ctx

class PlaceOrderView(PaymentDetailsView):
    template_name = 'checkout/payment_details.html'
    template_name_preview = 'systempay/preview.html'
    preview = True

    def post(self, request, *args, **kwargs):

        if self.preview:
            if request.POST.get('action', '') == 'place_order':
                return self.submit(**self.build_submission())
            return self.render_preview(request)

        return self.get(request, *args, **kwargs)

    def handle_payment(self, order_number, total_incl_tax, **kwargs):
        """
        Skip this step when placing the order, it'll be handle by the ipn
        received from server to server.
        Only record the allocated amount.
        """
        pass

    def handle_successful_order(self, order, send_confirmation_message=True):
        """
        Handle the various steps required after an order has been successfully
        placed.

        Override this view if you want to perform custom actions when an
        order is submitted.
        """
        # Send confirmation message (normally an email)
        # if send_confirmation_message:
        #     self.send_confirmation_message(order)

        # Delay the flush of all session data
        # self.checkout_session.flush()

        # Save order id in session so secure redirect page can load it
        self.request.session['checkout_order_id'] = order.id

        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse('systempay:secure-redirect')

class ResponseView(generic.RedirectView):
    def get_order(self):
        # We allow superusers to force an order thank-you page for testing

        order = None
        if self.request.user.is_superuser:
            if 'order_number' in self.request.GET:
                order = Order.objects.get(
                    number=self.request.GET['order_number'])
            elif 'order_id' in self.request.GET:
                order = Order.objects.get(
                    id=self.request.GET['order_id'])

        if not order:
            order_number = None
            if 'vads_order_id' in self.request.POST:
                order_number = self.request.POST['vads_order_id']
            elif 'vads_order_id' in self.request.GET:
                order_number = self.request.GET['vads_order_id']

            if not order_number:
                raise Http404(_("No order found"))

            try:
                order = Order.objects.get(number=order_number)
            except Order.DoesNotExist:
                raise Http404(_("The page requested seems outdated"))

        return order

class ReturnResponseView(ResponseView):
    def get_redirect_url(self, **kwargs):
        order = self.get_order()

        # check if the transaction exists
        txns = SystemPayTransaction.objects.filter(
            mode=SystemPayTransaction.MODE_RETURN,
            order_number=order.number
        ).order_by('-date_created')[:1]

        if not txns:
            messages.error(
                self.request,
                _("No response received from your bank for the moment. "
                  "Be patient, we'll get back to you as soon as we receive it.")
            )
        else:
            txn = txns[0]
            if txn.is_complete():  # check if the transaction has been complete
                messages.success(
                    self.request,
                    _("Your payment has been successfully validated.")
                )
            else:
                messages.error(
                    self.request,
                    _("Your payment has been rejected for the reason. You will "
                      "not be charged. Contact the support for more details.")
                )

        self.request.session['checkout_order_id'] = order.id
        return reverse('checkout:thank-you')

class CancelResponseView(ResponseView):
    def get_redirect_url(self, **kwargs):
        order = self.get_order()

        # cancel the order (to deallocate the products)
        handler = EventHandler()
        handler.handle_order_status_change(
            order, getattr(settings, 'OSCAR_STATUS_CANCELLED', None))

        # delete the order
        order.delete()

        # unfreeze the basket
        basket = Basket.objects.get(pk=order.basket_id)
        basket.thaw()

        messages.error(self.request, _("The transaction has be canceled"))
        return reverse('basket:summary')

class HandleIPN(OrderPlacementMixin, generic.View):
    def get(self, request, *args, **kwargs):
        if request.user and request.user.is_superuser:
            # Authorize admins for test purpose to copy the GET params
            #  to the POST dict
            request.POST = request.GET
            # from .test_vars import NOTIFICATION
            # request.POST = NOTIFICATION
            return self.post(request, *args, **kwargs)
        return HttpResponse()

    def post(self, request, *args, **kwargs):
        try:
            self.handle_ipn(request)
        except PaymentError as inst:
            return HttpResponseBadRequest(inst.message)
        return HttpResponse()

    def handle_ipn(self, request, **kwargs):
        """
        Complete payment.
        """
        # for k, v in request.POST.items():
        #     if k.startswith('vads'):
        #         print('{0:10} ==> {1:10}'.format(k, v))

        try:
            txn = Facade().handle_request(request)
            order = Order.objects.get(number=txn.order_number)

            source_type, is_created = SourceType.objects.get_or_create(
                code='systempay', name='SystemPay',
            )

            if txn.operation_type == SystemPayTransaction.OPERATION_TYPE_DEBIT:
                source = Source(source_type=source_type,
                                currency=txn.currency,
                                amount_allocated=D(0),
                                amount_debited=txn.amount,
                                reference=txn.reference)
                self.add_payment_source(source)

            elif txn.operation_type == SystemPayTransaction.OPERATION_TYPE_CREDIT:
                source = Source(source_type=source_type,
                                currency=txn.currency,
                                amount_allocated=D(0),
                                amount_refunded=txn.amount,
                                reference=txn.reference)
                self.add_payment_source(source)

            else:

                raise PaymentError(
                    _("Unknown operation type '%(operation_type)s'")
                    % {'operation_type': txn.operation_type})

            self.save_payment_details(order)

        except SystemPayError:
            raise
        except Order.DoesNotExist:
            logger.error(_("Unable to retrieve Order #%(order_number)s")
                         % {'order_number': txn.order_number})
<|endoftext|>


<commit_before>#!/usr/bin/python

from __future__ import unicode_literals

from collections import defaultdict
import glob
import json
import os

from .metrics_core import Metric
from .mmap_dict import MmapedDict
from .samples import Sample
from .utils import floatToGoString

class MultiProcessCollector(object):
    """Collector for files for multi-process mode."""

    def __init__(self, registry, path=None):
        if path is None:
            path = os.environ.get('prometheus_multiproc_dir')
        if not path or not os.path.isdir(path):
            raise ValueError('env prometheus_multiproc_dir is not set or not a directory')
        self._path = path
        if registry:
            registry.register(self)

    @staticmethod
    def merge(files, accumulate=True):
        """Merge metrics from given mmap files.

        By default, histograms are accumulated, as per prometheus wire format.
        But if writing the merged data back to mmap files, use
        accumulate=False to avoid compound accumulation.
        """
        metrics = {}
        for f in files:
            parts = os.path.basename(f).split('_')
            typ = parts[0]
            d = MmapedDict(f, read_mode=True)
            for key, value in d.read_all_values():
                metric_name, name, labels = json.loads(key)
                labels_key = tuple(sorted(labels.items()))

                metric = metrics.get(metric_name)
                if metric is None:
                    metric = Metric(metric_name, 'Multiprocess metric', typ)
                    metrics[metric_name] = metric

                if typ == 'gauge':
                    pid = parts[2][:-3]
                    metric._multiprocess_mode = parts[1]
                    metric.add_sample(name, labels_key + (('pid', pid),), value)
                else:
                    # The duplicates and labels are fixed in the next for.
                    metric.add_sample(name, labels_key, value)
            d.close()

        for metric in metrics.values():
            samples = defaultdict(float)
            buckets = {}
            for s in metric.samples:
                name, labels, value = s.name, s.labels, s.value
                if metric.type == 'gauge':
                    without_pid = tuple(l for l in labels if l[0] != 'pid')
                    if metric._multiprocess_mode == 'min':
                        current = samples.setdefault((name, without_pid), value)
                        if value < current:
                            samples[(s.name, without_pid)] = value
                    elif metric._multiprocess_mode == 'max':
                        current = samples.setdefault((name, without_pid), value)
                        if value > current:
                            samples[(s.name, without_pid)] = value
                    elif metric._multiprocess_mode == 'livesum':
                        samples[(name, without_pid)] += value
                    else:  # all/liveall
                        samples[(name, labels)] = value

                elif metric.type == 'histogram':
                    bucket = tuple(float(l[1]) for l in labels if l[0] == 'le')
                    if bucket:
                        # _bucket
                        without_le = tuple(l for l in labels if l[0] != 'le')
                        buckets.setdefault(without_le, {})
                        buckets[without_le].setdefault(bucket[0], 0.0)
                        buckets[without_le][bucket[0]] += value
                    else:
                        # _sum/_count
                        samples[(s.name, labels)] += value

                else:
                    # Counter and Summary.
                    samples[(s.name, labels)] += value

            # Accumulate bucket values.
            if metric.type == 'histogram':
                for labels, values in buckets.items():
                    acc = 0.0
                    for bucket, value in sorted(values.items()):
                        sample_key = (
                            metric.name + '_bucket',
                            labels + (('le', floatToGoString(bucket)),),
                        )
                        if accumulate:
                            acc += value
                            samples[sample_key] = acc
                        else:
                            samples[sample_key] = value
                    if accumulate:
                        samples[(metric.name + '_count', labels)] = acc

            # Convert to correct sample format.
            metric.samples = [Sample(name_, dict(labels), value) for (name_, labels), value in samples.items()]
        return metrics.values()

    def collect(self):
        files = glob.glob(os.path.join(self._path, '*.db'))
        return self.merge(files, accumulate=True)

def mark_process_dead(pid, path=None):
    """Do bookkeeping for when one process dies in a multi-process setup."""
    if path is None:
        path = os.environ.get('prometheus_multiproc_dir')
    for f in glob.glob(os.path.join(path, 'gauge_livesum_{0}.db'.format(pid))):
        os.remove(f)
    for f in glob.glob(os.path.join(path, 'gauge_liveall_{0}.db'.format(pid))):
        os.remove(f)
<commit_msg>Split MultiProcessCollector.__init__ for better profiling<commit_after>#!/usr/bin/python

from __future__ import unicode_literals

from collections import defaultdict
import glob
import json
import os

from .metrics_core import Metric
from .mmap_dict import MmapedDict
from .samples import Sample
from .utils import floatToGoString

class MultiProcessCollector(object):
    """Collector for files for multi-process mode."""

    def __init__(self, registry, path=None):
        if path is None:
            path = os.environ.get('prometheus_multiproc_dir')
        if not path or not os.path.isdir(path):
            raise ValueError('env prometheus_multiproc_dir is not set or not a directory')
        self._path = path
        if registry:
            registry.register(self)

    @staticmethod
    def merge(files, accumulate=True):
        """Merge metrics from given mmap files.

        By default, histograms are accumulated, as per prometheus wire format.
        But if writing the merged data back to mmap files, use
        accumulate=False to avoid compound accumulation.
        """
        metrics = MultiProcessCollector._read_metrics(files)
        return MultiProcessCollector._accumulate_metrics(metrics, accumulate)

    @staticmethod
    def _read_metrics(files):
        metrics = {}
        for f in files:
            parts = os.path.basename(f).split('_')
            typ = parts[0]
            d = MmapedDict(f, read_mode=True)
            for key, value in d.read_all_values():
                metric_name, name, labels = json.loads(key)
                labels_key = tuple(sorted(labels.items()))

                metric = metrics.get(metric_name)
                if metric is None:
                    metric = Metric(metric_name, 'Multiprocess metric', typ)
                    metrics[metric_name] = metric

                if typ == 'gauge':
                    pid = parts[2][:-3]
                    metric._multiprocess_mode = parts[1]
                    metric.add_sample(name, labels_key + (('pid', pid),), value)
                else:
                    # The duplicates and labels are fixed in the next for.
                    metric.add_sample(name, labels_key, value)
            d.close()
        return metrics

    @staticmethod
    def _accumulate_metrics(metrics, accumulate):
        for metric in metrics.values():
            samples = defaultdict(float)
            buckets = {}
            for s in metric.samples:
                name, labels, value = s.name, s.labels, s.value
                if metric.type == 'gauge':
                    without_pid = tuple(l for l in labels if l[0] != 'pid')
                    if metric._multiprocess_mode == 'min':
                        current = samples.setdefault((name, without_pid), value)
                        if value < current:
                            samples[(s.name, without_pid)] = value
                    elif metric._multiprocess_mode == 'max':
                        current = samples.setdefault((name, without_pid), value)
                        if value > current:
                            samples[(s.name, without_pid)] = value
                    elif metric._multiprocess_mode == 'livesum':
                        samples[(name, without_pid)] += value
                    else:  # all/liveall
                        samples[(name, labels)] = value

                elif metric.type == 'histogram':
                    bucket = tuple(float(l[1]) for l in labels if l[0] == 'le')
                    if bucket:
                        # _bucket
                        without_le = tuple(l for l in labels if l[0] != 'le')
                        buckets.setdefault(without_le, {})
                        buckets[without_le].setdefault(bucket[0], 0.0)
                        buckets[without_le][bucket[0]] += value
                    else:
                        # _sum/_count
                        samples[(s.name, labels)] += value

                else:
                    # Counter and Summary.
                    samples[(s.name, labels)] += value

            # Accumulate bucket values.
            if metric.type == 'histogram':
                for labels, values in buckets.items():
                    acc = 0.0
                    for bucket, value in sorted(values.items()):
                        sample_key = (
                            metric.name + '_bucket',
                            labels + (('le', floatToGoString(bucket)),),
                        )
                        if accumulate:
                            acc += value
                            samples[sample_key] = acc
                        else:
                            samples[sample_key] = value
                    if accumulate:
                        samples[(metric.name + '_count', labels)] = acc

            # Convert to correct sample format.
            metric.samples = [Sample(name_, dict(labels), value) for (name_, labels), value in samples.items()]
        return metrics.values()

    def collect(self):
        files = glob.glob(os.path.join(self._path, '*.db'))
        return self.merge(files, accumulate=True)

def mark_process_dead(pid, path=None):
    """Do bookkeeping for when one process dies in a multi-process setup."""
    if path is None:
        path = os.environ.get('prometheus_multiproc_dir')
    for f in glob.glob(os.path.join(path, 'gauge_livesum_{0}.db'.format(pid))):
        os.remove(f)
    for f in glob.glob(os.path.join(path, 'gauge_liveall_{0}.db'.format(pid))):
        os.remove(f)
<|endoftext|>


<commit_before>from ctypes import pointer, windll
from ctypes.wintypes import BOOL, DWORD, HANDLE
from typing import List, Optional

from prompt_toolkit.win32_types import SECURITY_ATTRIBUTES

__all__ = ["wait_for_handles", "create_win32_event"]

WAIT_TIMEOUT = 0x00000102
INFINITE = -1

def wait_for_handles(
    handles: List[HANDLE], timeout: int = INFINITE
) -> Optional[HANDLE]:
    """
    Waits for multiple handles. (Similar to 'select') Returns the handle which is ready.
    Returns `None` on timeout.
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx

    Note that handles should be a list of `HANDLE` objects, not integers. See
    this comment in the patch by @quark-zju for the reason why:

        ''' Make sure HANDLE on Windows has a correct size

        Previously, the type of various HANDLEs are native Python integer
        types. The ctypes library will treat them as 4-byte integer when used
        in function arguments. On 64-bit Windows, HANDLE is 8-byte and usually
        a small integer. Depending on whether the extra 4 bytes are zero-ed out
        or not, things can happen to work, or break. '''
    """
    arrtype = HANDLE * len(handles)
    handle_array = arrtype(*handles)

    ret = windll.kernel32.WaitForMultipleObjects(
        len(handle_array), handle_array, BOOL(False), DWORD(timeout)
    )

    if ret == WAIT_TIMEOUT:
        return None
    else:
        h = handle_array[ret]
        return HANDLE(h)

def create_win32_event() -> HANDLE:
    """
    Creates a Win32 unnamed Event .
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
    """
    return HANDLE(
        windll.kernel32.CreateEventA(
            pointer(SECURITY_ATTRIBUTES()),
            BOOL(True),  # Manual reset event.
            BOOL(False),  # Initial state.
            None,  # Unnamed event object.
        )
    )
<commit_msg>Fix `win32.wait_for_handles`. Return one of the given `HANDLE` objects instead of creating a new one. This is important, because we want to test the outcome with the `is` operator.<commit_after>from ctypes import pointer, windll
from ctypes.wintypes import BOOL, DWORD, HANDLE
from typing import List, Optional

from prompt_toolkit.win32_types import SECURITY_ATTRIBUTES

__all__ = ["wait_for_handles", "create_win32_event"]

WAIT_TIMEOUT = 0x00000102
INFINITE = -1

def wait_for_handles(
    handles: List[HANDLE], timeout: int = INFINITE
) -> Optional[HANDLE]:
    """
    Waits for multiple handles. (Similar to 'select') Returns the handle which is ready.
    Returns `None` on timeout.
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx

    Note that handles should be a list of `HANDLE` objects, not integers. See
    this comment in the patch by @quark-zju for the reason why:

        ''' Make sure HANDLE on Windows has a correct size

        Previously, the type of various HANDLEs are native Python integer
        types. The ctypes library will treat them as 4-byte integer when used
        in function arguments. On 64-bit Windows, HANDLE is 8-byte and usually
        a small integer. Depending on whether the extra 4 bytes are zero-ed out
        or not, things can happen to work, or break. '''

    This function returns either `None` or one of the given `HANDLE` objects.
    (The return value can be tested with the `is` operator.)
    """
    arrtype = HANDLE * len(handles)
    handle_array = arrtype(*handles)

    ret = windll.kernel32.WaitForMultipleObjects(
        len(handle_array), handle_array, BOOL(False), DWORD(timeout)
    )

    if ret == WAIT_TIMEOUT:
        return None
    else:
        return handles[ret]

def create_win32_event() -> HANDLE:
    """
    Creates a Win32 unnamed Event .
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
    """
    return HANDLE(
        windll.kernel32.CreateEventA(
            pointer(SECURITY_ATTRIBUTES()),
            BOOL(True),  # Manual reset event.
            BOOL(False),  # Initial state.
            None,  # Unnamed event object.
        )
    )
<|endoftext|>


<commit_before>#    Copyright 2012, SIL International
#    All rights reserved.
#
#    This library is free software; you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published
#    by the Free Software Foundation; either version 2.1 of 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
#    Lesser General Public License for more details.
#
#    You should also have received a copy of the GNU Lesser General Public
#    License along with this library in the file named "LICENSE".
#    If not, write to the Free Software Foundation, 51 Franklin Street,
#    suite 500, Boston, MA 02110-1335, USA or visit their web page on the
#    internet at http://www.fsf.org/licenses/lgpl.html.

from graide.attribview import Attribute, AttribModel
from graide.utils import copyobj, DataObj
import traceback

class Slot(DataObj) :

    def __init__(self, info = {}) :
        self.highlighted = False
        self.highlightType = ""
        self.px = None          # set in self.pixmap()
        for k, v in info.items() :
            setattr(self, k, v)

    def copy(self) :
        res = Slot()
        copyobj(self, res)
        self.px = None
        #self.highlighted = False
        #self.highlightType = ""
        return res

    def clearHighlight(self) :
        self.highlighted = False
        self.highlightType = ""

    def attribModel(self) :

        res = []
        for k in ('index', 'id', 'gid', 'break', 'insert', 'justification') :
            if hasattr(self, k) :
                res.append(Attribute(k, self.__getattribute__, None, False, None, k))
        for k in ('origin', 'advance', "shift") :
            if hasattr(self, k) :
                res.append(Attribute(k, self.getPos, None, False, None, k))
        for k in ('before', 'after') :
            res.append(Attribute(k, self.getCharInfo, None, False, None, k))

        if hasattr(self, 'collision') :
            cres = []
            cres.append(Attribute('flags', self.getColFlags, None, False))
            cres.append(Attribute('margin', self.getColMargin, None, False))
            cres.append(Attribute('min', self.getColLimitMin, None, False))
            cres.append(Attribute('max', self.getColLimitMax, None, False))
            cres.append(Attribute('shift', self.getColShift, None, False))

        if hasattr(self, 'parent') :
            res.append(Attribute('parent', self.getParent, None, False, None, 'parent'))
            res.append(Attribute('parent offset', self.getOffset, None, False))

        resAttrib = AttribModel(res)

        ures = []
        for i in range(len(self.user)) :
            ures.append(Attribute(str(i+1), self.getUser, None, False, None, i))

        if hasattr(self, 'collision') :
            cAttrib = AttribModel(cres, resAttrib)
            resAttrib.add(Attribute('collision', None, None, True, None, cAttrib))

        uAttrib = AttribModel(ures, resAttrib)
        resAttrib.add(Attribute('user attributes', None, None, True, None, uAttrib))
        return resAttrib

    def getPos(self, name) :
        res = self.__getattribute__(name)
        return "(%d, %d)" % (res[0], res[1])

    def getCharInfo(self, name) :
        return self.charinfo[name]

    def getUser(self, index) :
        return self.user[index]

    def getParent(self, name) :
        try :
            return self.parent['id']
        except :
            return None

    def getOffset(self) :
        try :
            res = self.parent['offset']
            return "(%d, %d)" % (res[0], res[1])
        except :
            return None

    def getColFlags(self) :
        try :
            return self.collision['flags']
        except :
            return None

    def getColMargin(self) :
        try :
            return self.collision['margin']
        except :
            return None

    def getColLimitMin(self) :
        try :
            res = self.collision['limit']
            return "(%d, %d)" % (res[0], res[1])
        except :
            return None

    def getColLimitMax(self) :
        try :
            res = self.collision['limit']
            return "(%d, %d)" % (res[2], res[3])
        except :
            return None

    def getColShift(self) :
        try :
            res = self.collision['shift']
            return "(%d, %d)" % (res[0], res[1])
        except :
            return None

    def highlight(self, type = "default") :
        self.highlighted = True
        self.highlightType = type
        if (self.px) :
            self.px.highlight(type)

    def pixmap(self, px) :
        self.px = px
        if self.highlighted :
            px.highlight(self.highlightType)

    # Return line-and-file info corresponding to this row and column.
    def lineAndFile(self, row, col) :
        #print "Slot::doubleClick",event
        return None
<commit_msg>Small changes to to Slot tab labels.<commit_after>#    Copyright 2012, SIL International
#    All rights reserved.
#
#    This library is free software; you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published
#    by the Free Software Foundation; either version 2.1 of 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
#    Lesser General Public License for more details.
#
#    You should also have received a copy of the GNU Lesser General Public
#    License along with this library in the file named "LICENSE".
#    If not, write to the Free Software Foundation, 51 Franklin Street,
#    suite 500, Boston, MA 02110-1335, USA or visit their web page on the
#    internet at http://www.fsf.org/licenses/lgpl.html.

from graide.attribview import Attribute, AttribModel
from graide.utils import copyobj, DataObj
import traceback

class Slot(DataObj) :

    def __init__(self, info = {}) :
        self.highlighted = False
        self.highlightType = ""
        self.px = None          # set in self.pixmap()
        for k, v in info.items() :
            setattr(self, k, v)

    def copy(self) :
        res = Slot()
        copyobj(self, res)
        self.px = None
        #self.highlighted = False
        #self.highlightType = ""
        return res

    def clearHighlight(self) :
        self.highlighted = False
        self.highlightType = ""

    def attribModel(self) :
        res = []
        for pair in (('index', 'index'), ('glyph number','gid'), ('slot ID', 'id'),
                ('breakweight', 'break'), ('insert', 'insert'), ('justification', 'justification')) :
            label,attr = pair
            if hasattr(self, attr) :
                res.append(Attribute(label, self.__getattribute__, None, False, None, attr))
        for k in ('origin', 'advance', 'shift') :
            if hasattr(self, k) :
                res.append(Attribute(k, self.getPos, None, False, None, k))
        for k in ('before', 'after') :
            res.append(Attribute(k, self.getCharInfo, None, False, None, k))

        if hasattr(self, 'collision') :
            cres = []
            cres.append(Attribute('flags', self.getColFlags, None, False))
            cres.append(Attribute('margin', self.getColMargin, None, False))
            cres.append(Attribute('min', self.getColLimitMin, None, False))
            cres.append(Attribute('max', self.getColLimitMax, None, False))
            cres.append(Attribute('shift', self.getColShift, None, False))

        if hasattr(self, 'parent') :
            res.append(Attribute('parent slot', self.getParent, None, False, None, 'parent'))
            res.append(Attribute('parent offset', self.getOffset, None, False))

        resAttrib = AttribModel(res)

        ures = []
        for i in range(len(self.user)) :
            ures.append(Attribute(str(i+1), self.getUser, None, False, None, i))

        if hasattr(self, 'collision') :
            cAttrib = AttribModel(cres, resAttrib)
            resAttrib.add(Attribute('collision', None, None, True, None, cAttrib))

        uAttrib = AttribModel(ures, resAttrib)
        resAttrib.add(Attribute('user attributes', None, None, True, None, uAttrib))
        return resAttrib

    def getPos(self, name) :
        res = self.__getattribute__(name)
        return "(%d, %d)" % (res[0], res[1])

    def getCharInfo(self, name) :
        return self.charinfo[name]

    def getUser(self, index) :
        return self.user[index]

    def getParent(self, name) :
        try :
            return self.parent['id']
        except :
            return None

    def getOffset(self) :
        try :
            res = self.parent['offset']
            return "(%d, %d)" % (res[0], res[1])
        except :
            return None

    def getColFlags(self) :
        try :
            return self.collision['flags']
        except :
            return None

    def getColMargin(self) :
        try :
            return self.collision['margin']
        except :
            return None

    def getColLimitMin(self) :
        try :
            res = self.collision['limit']
            return "(%d, %d)" % (res[0], res[1])
        except :
            return None

    def getColLimitMax(self) :
        try :
            res = self.collision['limit']
            return "(%d, %d)" % (res[2], res[3])
        except :
            return None

    def getColShift(self) :
        try :
            res = self.collision['shift']
            return "(%d, %d)" % (res[0], res[1])
        except :
            return None

    def highlight(self, type = "default") :
        self.highlighted = True
        self.highlightType = type
        if (self.px) :
            self.px.highlight(type)

    def pixmap(self, px) :
        self.px = px
        if self.highlighted :
            px.highlight(self.highlightType)

    # Return line-and-file info corresponding to this row and column.
    def lineAndFile(self, row, col) :
        #print "Slot::doubleClick",event
        return None
<|endoftext|>