<commit_before># Django settings for spiff project.
import os

relpath = lambda *x: os.path.join(os.path.abspath(os.path.dirname(__file__)), *x)

DEBUG = True
TEMPLATE_DEBUG = DEBUG

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

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': relpath('spiff.sqlite3'),                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

# 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 = 'America/New_York'

# 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 = ''

# 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 = ''

# 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 = ''

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

# Additional locations of static files
STATICFILES_DIRS = (
    relpath("static/"),
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

# 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',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

# Make this unique, and don't share it with anybody.
SECRET_KEY = 's)v()z^q-&p*#b%e9w05)r+vodsx35@1q*@hhqpexa^y97#r^z'

# 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',
#     'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'spiff.urls'

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

TEMPLATE_DIRS = (
    relpath("templates/"),
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'django.contrib.admindocs',
    'south',
    'gravatar',
    #'webfinger',
    'django.contrib.markup',
    'django_openid_auth',
    'openid_provider',
    'wellknown',
    'spiff.membership',
    'spiff.inventory',
    'spiff.local',
    'spiff.events',
    'spiff.sensors',
    'spiff.payment',
)

WEBFINGER_HANDLER = 'spiff.local.webfinger.handle'

OPENID_PROVIDER_STORE = 'django_openid_auth.store.DjangoOpenIDStore'

OPENID_USE_EMAIL_FOR_USERNAME = True

AUTHENTICATION_BACKENDS = (
    'django_openid_auth.auth.OpenIDBackend',
    'django.contrib.auth.backends.ModelBackend',
)

OPENID_CREATE_USERS = True

OPENID_UPDATE_DETAILS_FROM_SREG = True

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.contrib.messages.context_processors.messages",
  'spiff.local.context.space_info',
  'spiff.local.context.search_form',
)

# 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,
        },
    }
}

STRIPE_KEY = ''

try:
  from local_settings import *
except ImportError:
  pass

<commit_msg>Add management app to settings.py<commit_after># Django settings for spiff project.
import os

relpath = lambda *x: os.path.join(os.path.abspath(os.path.dirname(__file__)), *x)

DEBUG = True
TEMPLATE_DEBUG = DEBUG

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

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': relpath('spiff.sqlite3'),                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

# 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 = 'America/New_York'

# 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 = ''

# 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 = ''

# 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 = ''

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

# Additional locations of static files
STATICFILES_DIRS = (
    relpath("static/"),
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

# 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',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

# Make this unique, and don't share it with anybody.
SECRET_KEY = 's)v()z^q-&p*#b%e9w05)r+vodsx35@1q*@hhqpexa^y97#r^z'

# 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',
#     'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'spiff.urls'

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

TEMPLATE_DIRS = (
    relpath("templates/"),
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'django.contrib.admindocs',
    'south',
    'gravatar',
    #'webfinger',
    'django.contrib.markup',
    'django_openid_auth',
    'openid_provider',
    'wellknown',
    'spiff.membership',
    'spiff.inventory',
    'spiff.local',
    'spiff.events',
    'spiff.sensors',
    'spiff.payment',
    'spiff.management',
)

WEBFINGER_HANDLER = 'spiff.local.webfinger.handle'

OPENID_PROVIDER_STORE = 'django_openid_auth.store.DjangoOpenIDStore'

OPENID_USE_EMAIL_FOR_USERNAME = True

AUTHENTICATION_BACKENDS = (
    'django_openid_auth.auth.OpenIDBackend',
    'django.contrib.auth.backends.ModelBackend',
)

OPENID_CREATE_USERS = True

OPENID_UPDATE_DETAILS_FROM_SREG = True

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.contrib.messages.context_processors.messages",
  'spiff.local.context.space_info',
  'spiff.local.context.search_form',
)

# 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,
        },
    }
}

STRIPE_KEY = ''

try:
  from local_settings import *
except ImportError:
  pass

<|endoftext|>


<commit_before>import copy
import logging

import spreads.vendor.confit as confit
from spreads.vendor.pathlib import Path

class OptionTemplate(object):
    """ A configuration option.

    :attr value:      The default value for the option or a list of available
                      options if :attr selectable: is True
    :type value:      object (or list/tuple when :attr selectable: is True)
    :attr docstring:  A string explaining the configuration option
    :type docstring:  unicode
    :attr selectable: Make the OptionTemplate a selectable, i.e. value contains
                      a list or tuple of acceptable values for this option,
                      with the first member being the default selection.
    :type selectable: bool
    """

    def __init__(self, value, docstring=None, selectable=False):
        self.value = value
        self.docstring = docstring
        self.selectable = selectable

    def __repr__(self):
        return ("OptionTemplate(value={0}, docstring={1}, selectable={2})"
                .format(repr(self.value), repr(self.docstring),
                        repr(self.selectable)))

CORE_OPTIONS = {
    'verbose': OptionTemplate(value=False,
                              docstring="Enable verbose output"),
    'logfile': OptionTemplate(value="~/.config/spreads/spreads.log",
                              docstring="Path to logfile"),
    'loglevel': OptionTemplate(value=['info', 'critical', 'error',
                                      'warning', 'debug'],
                               docstring="Logging level for logfile",
                               selectable=True),
    'capture_keys': OptionTemplate(value=[" ", "b"],
                                   docstring="Keys to trigger capture",
                                   selectable=False),
}

class Configuration(object):
    def __init__(self, appname='spreads'):
        self._config = confit.LazyConfig(appname, __name__)
        self._config.read()
        if 'plugins' not in self._config.keys():
            self['plugins'] = []
        self.load_defaults(overwrite=False)

    # ----------------------------------------- #
    # Proxied methods from confit.Configuration #
    def __getitem__(self, key):
        return self._config[key]

    def __setitem__(self, key, value):
        self._config[key] = value

    def keys(self):
        return self._config.keys()

    def dump(self, filename=None, full=True):
        return self._config.dump(unicode(filename), full)

    def flatten(self):
        return self._config.flatten()
    # ----------------------------------------- #

    @property
    def templates(self):
        """ Get all available configuration templates.

        :rtype: dict

        """
        import spreads.plugin
        templates = {'core': CORE_OPTIONS}
        if 'driver' in self.keys():
            driver_name = self["driver"].get()
            templates['device'] = (spreads.plugin.get_driver(driver_name)
                                   .configuration_template())
            plugins = spreads.plugin.get_plugins(*self["plugins"].get())
            for name, plugin in plugins.iteritems():
                tmpl = plugin.configuration_template()
                if tmpl:
                    templates[name] = tmpl
        return templates

    @property
    def cfg_path(self):
        return Path(self._config.config_dir()) / confit.CONFIG_FILENAME

    def with_overlay(self, overlay):
        """ Get a new configuration that overlays the provided configuration
        over the present configuration.

        :param overlay:   The configuration to be overlaid
        :type overlay:    confit.ConfigSource or dict
        :return:          A new, merged configuration
        :rtype:           confit.Configuration

        """
        new_config = copy.deepcopy(self._config)
        new_config.set(overlay)
        return new_config

    def as_view(self):
        return self._config

    def load_defaults(self, overwrite=True):
        """ Load default settings from option templates.

        :param overwrite:   Whether to overwrite already existing values
        """
        for section, template in self.templates.iteritems():
            self.set_from_template(section, template, overwrite)

    def set_from_template(self, section, template, overwrite=True):
        """ Set default options from templates.

        :param section:   Target section for settings
        :type section:    unicode
        :type template:   OptionTemplate
        :param overwrite: Whether to overwrite already existing values

        """
        for key, option in template.iteritems():
            logging.info("Adding setting {0} from {1}"
                         .format(key, section))
            if not overwrite and key in self[section].keys():
                continue
            if option.selectable:
                self[section][key] = option.value[0]
            else:
                self[section][key] = option.value

    def set_from_args(self, args):
        """ Apply settings from parsed arguments.

        :type args:   argparse.Namespace

        """
        for argkey, value in args.__dict__.iteritems():
            skip = (value is None
                    or argkey == 'subcommand'
                    or argkey.startswith('_'))
            if skip:
                continue
            if '.' in argkey:
                section, key = argkey.split('.')
                self[section][key] = value
            else:
                self[argkey] = value
<commit_msg>Fix bug where plugin templates would not be returned when no driver was activated<commit_after>import copy
import logging

import spreads.vendor.confit as confit
from spreads.vendor.pathlib import Path

class OptionTemplate(object):
    """ A configuration option.

    :attr value:      The default value for the option or a list of available
                      options if :attr selectable: is True
    :type value:      object (or list/tuple when :attr selectable: is True)
    :attr docstring:  A string explaining the configuration option
    :type docstring:  unicode
    :attr selectable: Make the OptionTemplate a selectable, i.e. value contains
                      a list or tuple of acceptable values for this option,
                      with the first member being the default selection.
    :type selectable: bool
    """

    def __init__(self, value, docstring=None, selectable=False):
        self.value = value
        self.docstring = docstring
        self.selectable = selectable

    def __repr__(self):
        return ("OptionTemplate(value={0}, docstring={1}, selectable={2})"
                .format(repr(self.value), repr(self.docstring),
                        repr(self.selectable)))

CORE_OPTIONS = {
    'verbose': OptionTemplate(value=False,
                              docstring="Enable verbose output"),
    'logfile': OptionTemplate(value="~/.config/spreads/spreads.log",
                              docstring="Path to logfile"),
    'loglevel': OptionTemplate(value=['info', 'critical', 'error',
                                      'warning', 'debug'],
                               docstring="Logging level for logfile",
                               selectable=True),
    'capture_keys': OptionTemplate(value=[" ", "b"],
                                   docstring="Keys to trigger capture",
                                   selectable=False),
}

class Configuration(object):
    def __init__(self, appname='spreads'):
        self._config = confit.LazyConfig(appname, __name__)
        self._config.read()
        if 'plugins' not in self._config.keys():
            self['plugins'] = []
        self.load_defaults(overwrite=False)

    # ----------------------------------------- #
    # Proxied methods from confit.Configuration #
    def __getitem__(self, key):
        return self._config[key]

    def __setitem__(self, key, value):
        self._config[key] = value

    def keys(self):
        return self._config.keys()

    def dump(self, filename=None, full=True):
        return self._config.dump(unicode(filename), full)

    def flatten(self):
        return self._config.flatten()
    # ----------------------------------------- #

    @property
    def templates(self):
        """ Get all available configuration templates.

        :rtype: dict

        """
        import spreads.plugin
        templates = {'core': CORE_OPTIONS}
        if 'driver' in self.keys():
            driver_name = self["driver"].get()
            templates['device'] = (spreads.plugin.get_driver(driver_name)
                                   .configuration_template())
        plugins = spreads.plugin.get_plugins(*self["plugins"].get())
        for name, plugin in plugins.iteritems():
            tmpl = plugin.configuration_template()
            if tmpl:
                templates[name] = tmpl
        return templates

    @property
    def cfg_path(self):
        return Path(self._config.config_dir()) / confit.CONFIG_FILENAME

    def with_overlay(self, overlay):
        """ Get a new configuration that overlays the provided configuration
        over the present configuration.

        :param overlay:   The configuration to be overlaid
        :type overlay:    confit.ConfigSource or dict
        :return:          A new, merged configuration
        :rtype:           confit.Configuration

        """
        new_config = copy.deepcopy(self._config)
        new_config.set(overlay)
        return new_config

    def as_view(self):
        return self._config

    def load_defaults(self, overwrite=True):
        """ Load default settings from option templates.

        :param overwrite:   Whether to overwrite already existing values
        """
        for section, template in self.templates.iteritems():
            self.set_from_template(section, template, overwrite)

    def set_from_template(self, section, template, overwrite=True):
        """ Set default options from templates.

        :param section:   Target section for settings
        :type section:    unicode
        :type template:   OptionTemplate
        :param overwrite: Whether to overwrite already existing values

        """
        for key, option in template.iteritems():
            logging.info("Adding setting {0} from {1}"
                         .format(key, section))
            if not overwrite and key in self[section].keys():
                continue
            if option.selectable:
                self[section][key] = option.value[0]
            else:
                self[section][key] = option.value

    def set_from_args(self, args):
        """ Apply settings from parsed arguments.

        :type args:   argparse.Namespace

        """
        for argkey, value in args.__dict__.iteritems():
            skip = (value is None
                    or argkey == 'subcommand'
                    or argkey.startswith('_'))
            if skip:
                continue
            if '.' in argkey:
                section, key = argkey.split('.')
                self[section][key] = value
            else:
                self[argkey] = value
<|endoftext|>


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

# Copyright (c) 2013 Johannes Baiter. All rights reserved.
# 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.

from __future__ import division, unicode_literals

import abc
import itertools
import logging

import usb
import stevedore
from stevedore.driver import DriverManager
from stevedore.named import NamedExtensionManager

from spreads.util import abstractclassmethod, DeviceException

logger = logging.getLogger("spreads.plugin")

class PluginOption(object):
    """ A configuration option.

    :attr value:      The default value for the option or a list of available
                      options if :attr selectable: is True
    :type value:      object (or list/tuple when :attr selectable: is True)
    :attr docstring:  A string explaining the configuration option
    :type docstring:  unicode
    :attr selectable: Make the PluginOption a selectable, i.e. value contains
                      a list or tuple of acceptable values for this option,
                      with the first member being the default selection.
    :type selectable: bool
    """

    def __init__(self, value, docstring=None, selectable=False):
        self.value = value
        self.docstring = docstring
        self.selectable = selectable

class SpreadsNamedExtensionManager(NamedExtensionManager):
    """ Custom extension manager for spreads.

    stevedore's NamedExtensionmanger does not give us the Exception that caused
    a plugin to fail at initialization. This derived class throws the original
    exception instead of logging it.
    """
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = (super(SpreadsNamedExtensionManager, cls)
                             .__new__(cls, *args, **kwargs))
        return cls._instance

    def _load_plugins(self, invoke_on_load, invoke_args, invoke_kwds):
        extensions = []
        for ep in self._find_entry_points(self.namespace):
            stevedore.LOG.debug('found extension %r', ep)
            ext = self._load_one_plugin(ep,
                                        invoke_on_load,
                                        invoke_args,
                                        invoke_kwds,
                                        )
            if ext:
                extensions.append(ext)
        return extensions

class SpreadsPlugin(object):
    """ Plugin base class.

    """
    @classmethod
    def configuration_template(cls):
        """ Allows a plugin to define its configuration keys.

        The returned dictionary has to be flat (i.e. no nested dicts)
        and contain a PluginOption object for each key.

        Example:
          {
           'a_setting': PluginOption(value='default_value'),
           'another_setting': PluginOption(value=[1, 2, 3],
                                           docstring="A list of things"),
           # In this case, 'full-fat' would be the default value
           'milk': PluginOption(value=('full-fat', 'skim'),
                                docstring="Type of milk",
                                selectable=True),
          }

        :return: dict with unicode: PluginOption(value, docstring, selection)
        """
        pass

    def __init__(self, config):
        """ Initialize the plugin.

        :param config: The global configuration object
        :type config: confit.ConfigView

        """
        self.config = config

class DevicePlugin(SpreadsPlugin):
    """ Base class for devices.

        Subclass to implement support for different devices.

    """
    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def features(self):
        """ Return device features. """
        return { 'preview': False, }

    @abstractclassmethod
    def match(cls, usbdevice):
        """ Match device against USB device information.

        :param device:      The USB device to match against
        :type vendor_id:    `usb.core.Device <http://github.com/walac/pyusb>`_
        :return:            True if the :param usbdevice: matches the
                            implemented category

        """
        raise NotImplementedError

    def __init__(self, config, device):
        """ Set connection information and other properties.

        :param config:  spreads configuration
        :type config:   spreads.confit.ConfigView
        :param device:  USB device to use for the object
        :type device:   `usb.core.Device <http://github.com/walac/pyusb>`_

        """
        super(DevicePlugin, self).__init__(config['device'])
        self._device = device

    def set_orientation(self, orientation):
        """ Set the device orientation, if applicable.

        :param orientation: The orientation name
        :type orientation:  unicode in (u"left", u"right")

        """
        raise NotImplementedError

    @abc.abstractmethod
    def prepare_capture(self, path):
        """ Prepare device for scanning.

            What this means exactly is up to the implementation and the type,
            of device, usually it involves things like switching into record
            mode, path and applying all relevant settings.

        """
        raise NotImplementedError

    @abc.abstractmethod
    def capture(self, path):
        """ Capture a single image with the device.

        """
        raise NotImplementedError

class HookPlugin(SpreadsPlugin):
    """ Add functionality to any of spreads' commands by implementing one or
        more of the available hooks.

    """
    @classmethod
    def add_command_parser(cls, rootparser):
        """ Allows a plugin to register a new command with the command-line
            parser. The subparser that is added to :param rootparser: should
            set the class' ``__call__`` method as the ``func`` (via
            ``set_defaults``) that is executed when the subcommand is specified
            on the CLI.

        :param rootparser: The root parser that this plugin should add a
                           subparser to.
        :type rootparser:  argparse.ArgumentParser

        """
        pass

    def prepare_capture(self, devices, path):
        """ Perform some action before capturing begins.

        :param devices: The devices used for capturing
        :type devices: list(DevicePlugin)
        :param path: The project path
        :type path: unicode

        """
        pass

    def capture(self, devices, path):
        """ Perform some action after each successful capture.

        :param devices: The devices used for capturing
        :type devices: list(DevicePlugin)
        :param path: The project path
        :type path: unicode

        """
        pass

    def finish_capture(self, devices, path):
        """ Perform some action after capturing has finished.

        :param devices: The devices used for capturing
        :type devices: list(DevicePlugin)
        :param path: The project path
        :type path: unicode

        """
        pass

    def process(self, path):
        """ Perform one or more actions that either modify the captured images
            or generate a different output.

        .. note:
            This method is intended to operate on the *done* subdfolder of
            the project directory. At the beginning of postprocessing, it
            will contain copies of the images in *raw*. This is to ensure that
            a copy of the original, scanned images will always be available
            for archival purposes.

        :param path: The project path
        :type path: unicode

        """
        pass

    def output(self, path):
        """ Assemble an output file from the postprocessed images.

        .. note:
            This method is intended to take its input files from the *done*
            subfolder of the project path and store its output in the
            *out* subfolder.

        :param path: The project path
        :type path: unicode
        """
        pass

def get_pluginmanager(config):
    logger.debug("Creating plugin manager")
    pluginmanager = SpreadsNamedExtensionManager(
        namespace='spreadsplug.hooks',
        names=config['plugins'].as_str_seq(),
        invoke_on_load=True,
        invoke_args=[config],
        name_order=True)
    return pluginmanager

def get_driver(config):
    driver_name = config["driver"].get(unicode)
    return DriverManager(namespace="spreadsplug.devices",
                         name=driver_name)

def get_devices(config):
    """ Initialize configured devices.
    """
    driver = get_driver(config)
    driver_class = driver.driver
    logger.debug("Finding devices for driver \"{0}\"".format(driver))
    usb_devices = filter(lambda dev: driver_class.match(dev),
                         usb.core.find(find_all=True))
    devices = [driver_class(config, dev) for dev in usb_devices]
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    return devices

def setup_plugin_config(config):
    pluginmanager = get_pluginmanager(config)
    driver_name = config["driver"].get(unicode)
    driver = DriverManager(namespace="spreadsplug.devices",
                           name=driver_name)
    for ext in itertools.chain(pluginmanager, driver):
        logger.debug("Obtaining configuration template for plugin \"{0}\""
                     .format(ext.name))
        tmpl = ext.plugin.configuration_template()
        if ext in driver.extensions:
            section = 'device'
        else:
            section = ext.name
        if not tmpl:
            continue
        # Add default values
        for key, option in tmpl.items():
            # Check if we already have a configuration entry for this setting
            if key in config[section].keys():
                continue
            logging.info("Adding setting {0} from  plugin {1}"
                         .format(key, ext.name))
            if option.selectable:
                config[section][key] = option.value[0]
            else:
                config[section][key] = option.value

def get_relevant_extensions(plugin_manager, hooks):
    """ Find all extensions that implement certain hooks.

    :param hooks:   A list of hook method names
    :type hooks:    list(unicode)
    :return:        A generator that yields relevant extensions
    :rtype:         generator(Extension)

    """
    # NOTE: This one is wicked... The goal is to find all extensions that
    #       implement one of the specified hooks.
    #       To do so, we compare the code objects for the appropriate
    #       hook method with the same method in the HookPlugin base class.
    #       If the two are not the same, we can (somewhat) safely assume
    #       that the extension implements this hook and is thus relevant
    #       to us.
    #       Yes, this is not ideal and is due to our somewhat sloppy
    #       plugin interface. That's why...
    # TODO: Refactor plugin interface to make this less painful
    for ext in plugin_manager:
        relevant = any(
            getattr(ext.plugin, hook).func_code is not
            getattr(HookPlugin, hook).func_code
            for hook in hooks
        )
        if relevant:
            yield ext
<commit_msg>Only pass subviews of config to devices and plugins<commit_after># -*- coding: utf-8 -*-

# Copyright (c) 2013 Johannes Baiter. All rights reserved.
# 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.

from __future__ import division, unicode_literals

import abc
import itertools
import logging

import usb
import stevedore
from stevedore.driver import DriverManager
from stevedore.named import NamedExtensionManager

from spreads.util import abstractclassmethod, DeviceException

logger = logging.getLogger("spreads.plugin")

class PluginOption(object):
    """ A configuration option.

    :attr value:      The default value for the option or a list of available
                      options if :attr selectable: is True
    :type value:      object (or list/tuple when :attr selectable: is True)
    :attr docstring:  A string explaining the configuration option
    :type docstring:  unicode
    :attr selectable: Make the PluginOption a selectable, i.e. value contains
                      a list or tuple of acceptable values for this option,
                      with the first member being the default selection.
    :type selectable: bool
    """

    def __init__(self, value, docstring=None, selectable=False):
        self.value = value
        self.docstring = docstring
        self.selectable = selectable

class SpreadsNamedExtensionManager(NamedExtensionManager):
    """ Custom extension manager for spreads.

    stevedore's NamedExtensionmanger does not give us the Exception that caused
    a plugin to fail at initialization. This derived class throws the original
    exception instead of logging it.
    """
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = (super(SpreadsNamedExtensionManager, cls)
                             .__new__(cls, *args, **kwargs))
        return cls._instance

    def _load_plugins(self, invoke_on_load, invoke_args, invoke_kwds):
        extensions = []
        for ep in self._find_entry_points(self.namespace):
            stevedore.LOG.debug('found extension %r', ep)
            ext = self._load_one_plugin(ep,
                                        invoke_on_load,
                                        invoke_args,
                                        invoke_kwds,
                                        )
            if ext:
                extensions.append(ext)
        return extensions

class SpreadsPlugin(object):
    """ Plugin base class.

    """
    @classmethod
    def configuration_template(cls):
        """ Allows a plugin to define its configuration keys.

        The returned dictionary has to be flat (i.e. no nested dicts)
        and contain a PluginOption object for each key.

        Example:
          {
           'a_setting': PluginOption(value='default_value'),
           'another_setting': PluginOption(value=[1, 2, 3],
                                           docstring="A list of things"),
           # In this case, 'full-fat' would be the default value
           'milk': PluginOption(value=('full-fat', 'skim'),
                                docstring="Type of milk",
                                selectable=True),
          }

        :return: dict with unicode: PluginOption(value, docstring, selection)
        """
        pass

    def __init__(self, config):
        """ Initialize the plugin.

        :param config: The global configuration object, by default only the
                       section with plugin-specific values gets stored in
                       the `config` attribute, if the plugin has a `__name__`
                       attribute.
        :type config: confit.ConfigView

        """
        if hasattr(self, '__name__'):
            self.config = config[self.__name__]
        else:
            self.config = config

class DevicePlugin(SpreadsPlugin):
    """ Base class for devices.

        Subclass to implement support for different devices.

    """
    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def features(self):
        """ Return device features. """
        return {'preview': False}

    @abstractclassmethod
    def match(cls, usbdevice):
        """ Match device against USB device information.

        :param device:      The USB device to match against
        :type vendor_id:    `usb.core.Device <http://github.com/walac/pyusb>`_
        :return:            True if the :param usbdevice: matches the
                            implemented category

        """
        raise NotImplementedError

    def __init__(self, config, device):
        """ Set connection information and other properties.

        :param config:  spreads configuration
        :type config:   spreads.confit.ConfigView
        :param device:  USB device to use for the object
        :type device:   `usb.core.Device <http://github.com/walac/pyusb>`_

        """
        super(DevicePlugin, self).__init__(config['device'])
        self._device = device

    def set_orientation(self, orientation):
        """ Set the device orientation, if applicable.

        :param orientation: The orientation name
        :type orientation:  unicode in (u"left", u"right")

        """
        raise NotImplementedError

    @abc.abstractmethod
    def prepare_capture(self, path):
        """ Prepare device for scanning.

            What this means exactly is up to the implementation and the type,
            of device, usually it involves things like switching into record
            mode, path and applying all relevant settings.

        """
        raise NotImplementedError

    @abc.abstractmethod
    def capture(self, path):
        """ Capture a single image with the device.

        """
        raise NotImplementedError

class HookPlugin(SpreadsPlugin):
    """ Add functionality to any of spreads' commands by implementing one or
        more of the available hooks.

    """
    @classmethod
    def add_command_parser(cls, rootparser):
        """ Allows a plugin to register a new command with the command-line
            parser. The subparser that is added to :param rootparser: should
            set the class' ``__call__`` method as the ``func`` (via
            ``set_defaults``) that is executed when the subcommand is specified
            on the CLI.

        :param rootparser: The root parser that this plugin should add a
                           subparser to.
        :type rootparser:  argparse.ArgumentParser

        """
        pass

    def prepare_capture(self, devices, path):
        """ Perform some action before capturing begins.

        :param devices: The devices used for capturing
        :type devices: list(DevicePlugin)
        :param path: The project path
        :type path: unicode

        """
        pass

    def capture(self, devices, path):
        """ Perform some action after each successful capture.

        :param devices: The devices used for capturing
        :type devices: list(DevicePlugin)
        :param path: The project path
        :type path: unicode

        """
        pass

    def finish_capture(self, devices, path):
        """ Perform some action after capturing has finished.

        :param devices: The devices used for capturing
        :type devices: list(DevicePlugin)
        :param path: The project path
        :type path: unicode

        """
        pass

    def process(self, path):
        """ Perform one or more actions that either modify the captured images
            or generate a different output.

        .. note:
            This method is intended to operate on the *done* subdfolder of
            the project directory. At the beginning of postprocessing, it
            will contain copies of the images in *raw*. This is to ensure that
            a copy of the original, scanned images will always be available
            for archival purposes.

        :param path: The project path
        :type path: unicode

        """
        pass

    def output(self, path):
        """ Assemble an output file from the postprocessed images.

        .. note:
            This method is intended to take its input files from the *done*
            subfolder of the project path and store its output in the
            *out* subfolder.

        :param path: The project path
        :type path: unicode
        """
        pass

def get_pluginmanager(config):
    logger.debug("Creating plugin manager")
    pluginmanager = SpreadsNamedExtensionManager(
        namespace='spreadsplug.hooks',
        names=config['plugins'].as_str_seq(),
        invoke_on_load=True,
        invoke_args=[config],
        name_order=True)
    return pluginmanager

def get_driver(config):
    driver_name = config["driver"].get(unicode)
    return DriverManager(namespace="spreadsplug.devices",
                         name=driver_name)

def get_devices(config):
    """ Initialize configured devices.
    """
    driver = get_driver(config)
    driver_class = driver.driver
    logger.debug("Finding devices for driver \"{0}\"".format(driver))
    usb_devices = filter(lambda dev: driver_class.match(dev),
                         usb.core.find(find_all=True))
    devices = [driver_class(config['device'], dev) for dev in usb_devices]
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    return devices

def setup_plugin_config(config):
    pluginmanager = get_pluginmanager(config)
    driver_name = config["driver"].get(unicode)
    driver = DriverManager(namespace="spreadsplug.devices",
                           name=driver_name)
    for ext in itertools.chain(pluginmanager, driver):
        logger.debug("Obtaining configuration template for plugin \"{0}\""
                     .format(ext.name))
        tmpl = ext.plugin.configuration_template()
        if ext in driver.extensions:
            section = 'device'
        else:
            section = ext.name
        if not tmpl:
            continue
        # Add default values
        for key, option in tmpl.items():
            # Check if we already have a configuration entry for this setting
            if key in config[section].keys():
                continue
            logging.info("Adding setting {0} from  plugin {1}"
                         .format(key, ext.name))
            if option.selectable:
                config[section][key] = option.value[0]
            else:
                config[section][key] = option.value

def get_relevant_extensions(plugin_manager, hooks):
    """ Find all extensions that implement certain hooks.

    :param hooks:   A list of hook method names
    :type hooks:    list(unicode)
    :return:        A generator that yields relevant extensions
    :rtype:         generator(Extension)

    """
    # NOTE: This one is wicked... The goal is to find all extensions that
    #       implement one of the specified hooks.
    #       To do so, we compare the code objects for the appropriate
    #       hook method with the same method in the HookPlugin base class.
    #       If the two are not the same, we can (somewhat) safely assume
    #       that the extension implements this hook and is thus relevant
    #       to us.
    #       Yes, this is not ideal and is due to our somewhat sloppy
    #       plugin interface. That's why...
    # TODO: Refactor plugin interface to make this less painful
    for ext in plugin_manager:
        relevant = any(
            getattr(ext.plugin, hook).func_code is not
            getattr(HookPlugin, hook).func_code
            for hook in hooks
        )
        if relevant:
            yield ext
<|endoftext|>


<commit_before>import os
import sys
import json
import docker
import argparse
import jsonschema

class DckrMgr(object):
    def __init__(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('-c', dest='commands', action='append_const', const='c', help='Create container')
        parser.add_argument('-s', dest='commands', action='append_const', const='s', help='Start container')
        parser.add_argument('-t', dest='commands', action='append_const', const='t', help='Stop container')
        parser.add_argument('-r', dest='commands', action='append_const', const='r', help='Remove container')
        parser.add_argument('-p', dest='commands', action='append_const', const='p', help='Pull container')
        parser.add_argument('-b', dest='commands', action='append_const', const='b', help='Backup volumes')
        args = parser.parse_args()

        self.cli = docker.Client('unix://var/run/docker.sock')

        self.p_src = os.path.dirname(os.path.abspath(__file__))

        self.p_cwd = os.getcwd()
        self.p_cnf = os.path.join(self.p_cwd, 'dckrcnf.json')
        self.p_cch = os.path.join(self.p_cwd, 'dckrcch.json')

        try:
            f_cnf = open(self.p_cnf, 'r')
        except OSError:
            print('Couldn\'t open dckrcnf.json')
            exit(1)

        try:
            f_sch = open(os.path.join(self.p_src, 'dckrcnf.schema.json'), 'r')
        except OSError:
            print('Couldn\'t open dckrcnf.schema.json')
            exit(1)

        try:
            self.j_cnf = json.load(f_cnf)
        except ValueError:
            print('dckrcnf.json is invalid json')
            exit(1)

        try:
            j_sch = json.load(f_sch)
        except ValueError:
            print('dckrcnf.schema.json is invalid json')
            exit(1)

        try:
            jsonschema.validate(self.j_cnf, j_sch)
        except jsonschema.exceptions.ValidationError as detail:
            print(detail.message)
            exit(1)

        try:
            f_cch = open(self.p_cch, 'x')
        except OSError:
            pass
        else:
            json.dump({}, f_cch, indent = 4, sort_keys = True)

        try:
            f_cch = open(self.p_cch, 'r')
        except OSError:
            exit(1)

        self.j_cch = json.load(f_cch)

        i_sts = 0

        for command in args.commands:
            if getattr(self, command)() != 0:
                i_sts = 1
                break

        try:
            f_cch = open(self.p_cch, 'w')
        except OSError:
            exit(1)

        json.dump(self.j_cch, f_cch, indent = 4, sort_keys = True)

        exit(i_sts)

    def c(self):
        if 'id' in self.j_cch:
            print(self.j_cnf['name'] + ' already created')
            return 1

        environment = {}

        for variable in self.j_cnf.get('environment', {}):
            environment[variable['name']] = variable['value']

        volumes = []
        binds = {}

        for volume in self.j_cnf.get('volumes', {}):
            volumes.append(volume['container_path'])

            binds[os.path.join(self.p_cwd, volume['host_path'])] = {
                'bind': volume['container_path'],
                'mode': volume['mode']
            }

        ports = []
        port_bindings = {}

        for port in self.j_cnf.get('ports', {}):
            if 'protocol' in port and port['protocol'] == 'udp':
                p = (port['container_port'], 'udp')
                p_hc = str(port['container_port']) + '/udp'
            else:
                p = port['container_port']
                p_hc = port['container_port']

            if 'address' in port:
                h = (port['address'], port['host_port'])
            else:
                h = port['host_port']

            ports.append(p)
            port_bindings[p_hc] = h

        links = {}

        for link in self.j_cnf.get('links', {}):
            links[link['name']] = link['alias']

        host_config = docker.utils.create_host_config(
            binds = binds,
            port_bindings = port_bindings,
            links = links
        )

        try:
            res = self.cli.create_container(
                name = self.j_cnf['name'],
                image = self.j_cnf['image']['name'] + ':' + self.j_cnf['image']['version'],
                hostname = self.j_cnf.get('hostname'),
                environment = environment,
                volumes = volumes,
                ports = ports,
                host_config = host_config
            )
        except docker.errors.APIError as detail:
            print('Couldn\'t create ' + self.j_cnf['name'] + ':')
            print(detail)
            return 1

        self.j_cch['id'] = res['Id']

        print('Created ' + self.j_cnf['name'])

        if res['Warnings'] != None:
            print('Warnings generated:')
            print(res['Warnings'])

        return 0

    def s(self):
        if not 'id' in self.j_cch:
            print(self.j_cnf['name'] + ' not created')
            return 1

        self.cli.start(self.j_cch['id'])
        print('Started ' + self.j_cnf['name'])
        return 0

    def t(self):
        if not 'id' in self.j_cch:
            print(self.j_cnf['name'] + ' not created')
            return 1

        self.cli.stop(self.j_cch['id'])
        print('Stopped ' + self.j_cnf['name'])
        return 0

    def r(self):
        if not 'id' in self.j_cch:
            print(self.j_cnf['name'] + ' not created')
            return 1

        self.cli.remove_container(container = self.j_cch['id'])
        self.j_cch.pop('id')
        print('Removed ' + self.j_cnf['name'])

        return 0

    def p(self):
        print('P')
        return 0

    def b(self):
        print('B')
        return 0
<commit_msg>make dckrmgr stateless<commit_after>import os
import sys
import json
import docker
import argparse
import jsonschema

class DckrMgr(object):
    def __init__(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('-c', dest='commands', action='append_const', const='c', help='Create container')
        parser.add_argument('-s', dest='commands', action='append_const', const='s', help='Start container')
        parser.add_argument('-t', dest='commands', action='append_const', const='t', help='Stop container')
        parser.add_argument('-r', dest='commands', action='append_const', const='r', help='Remove container')
        parser.add_argument('-p', dest='commands', action='append_const', const='p', help='Pull container')
        parser.add_argument('-b', dest='commands', action='append_const', const='b', help='Backup volumes')
        args = parser.parse_args()

        self.cli = docker.Client('unix://var/run/docker.sock')

        self.p_src = os.path.dirname(os.path.abspath(__file__))

        self.p_cwd = os.getcwd()
        self.p_cnf = os.path.join(self.p_cwd, 'dckrcnf.json')

        try:
            f_cnf = open(self.p_cnf, 'r')
        except OSError:
            print('Couldn\'t open dckrcnf.json')
            exit(1)

        try:
            f_sch = open(os.path.join(self.p_src, 'dckrcnf.schema.json'), 'r')
        except OSError:
            print('Couldn\'t open dckrcnf.schema.json')
            exit(1)

        try:
            self.j_cnf = json.load(f_cnf)
        except ValueError:
            print('dckrcnf.json is invalid json')
            exit(1)

        try:
            j_sch = json.load(f_sch)
        except ValueError:
            print('dckrcnf.schema.json is invalid json')
            exit(1)

        try:
            jsonschema.validate(self.j_cnf, j_sch)
        except jsonschema.exceptions.ValidationError as detail:
            print(detail.message)
            exit(1)

        i_sts = 0

        for command in args.commands:
            if getattr(self, command)() != 0:
                i_sts = 1
                break

        exit(i_sts)

    def c(self):
        environment = {}

        for variable in self.j_cnf.get('environment', {}):
            environment[variable['name']] = variable['value']

        volumes = []
        binds = {}

        for volume in self.j_cnf.get('volumes', {}):
            volumes.append(volume['container_path'])

            binds[os.path.join(self.p_cwd, volume['host_path'])] = {
                'bind': volume['container_path'],
                'mode': volume['mode']
            }

        ports = []
        port_bindings = {}

        for port in self.j_cnf.get('ports', {}):
            if 'protocol' in port and port['protocol'] == 'udp':
                p = (port['container_port'], 'udp')
                p_hc = str(port['container_port']) + '/udp'
            else:
                p = port['container_port']
                p_hc = port['container_port']

            if 'address' in port:
                h = (port['address'], port['host_port'])
            else:
                h = port['host_port']

            ports.append(p)
            port_bindings[p_hc] = h

        links = {}

        for link in self.j_cnf.get('links', {}):
            links[link['name']] = link['alias']

        host_config = docker.utils.create_host_config(
            binds = binds,
            port_bindings = port_bindings,
            links = links
        )

        try:
            res = self.cli.create_container(
                name = self.j_cnf['name'],
                image = self.j_cnf['image']['name'] + ':' + self.j_cnf['image']['version'],
                hostname = self.j_cnf.get('hostname'),
                environment = environment,
                volumes = volumes,
                ports = ports,
                host_config = host_config
            )
        except docker.errors.APIError as detail:
            print('Couldn\'t create ' + self.j_cnf['name'] + ':')
            print(detail)
            return 1

        print('Created ' + self.j_cnf['name'])

        if res['Warnings'] != None:
            print('Warnings generated:')
            print(res['Warnings'])

        return 0

    def s(self):
        self.cli.start(self.j_cnf['name'])
        print('Started ' + self.j_cnf['name'])
        return 0

    def t(self):
        self.cli.stop(self.j_cnf['name'])
        print('Stopped ' + self.j_cnf['name'])
        return 0

    def r(self):
        self.cli.remove_container(container = self.j_cnf['name'])
        print('Removed ' + self.j_cnf['name'])
        return 0

    def p(self):
        print('P')
        return 0

    def b(self):
        print('B')
        return 0
<|endoftext|>


<commit_before>from __future__ import print_function, division

def log(string):
    print(" << %s" % string)

#http://0x10c.com/doc/dcpu-16.txt
spec = '1.1'

w = 16
wmask = 2**w - 1

literals = [l for l in xrange(0, 0x20)]

_opcode_map = {}
_valcode_map = {}

class opcode(object):
    def __init__(self, *opcode):
        self.opcode = opcode

    def __call__(self, f):
        _opcode_f = f
        _opcode_f.opcode = self.opcode
        if len(self.opcode) == 1:
            _opcode_map[self.opcode[0]] = _opcode_f
        else:
            if not self.opcode[0] in _opcode_map.keys():
                _opcode_map[self.opcode[0]] = {}
            _opcode_map[self.opcode[0]][self.opcode[1]] = _opcode_f
        return _opcode_f

class valcode(object):
    def __init__(self, valcode):
        self.valcode = valcode

    def __call__(self, f):
        _valcode_f = f
        _valcode_f.valcode = self.valcode
        try:
            for code in self.valcode:
                # currify with (bound) code
                _valcode_map[code] = lambda c, code=code: _valcode_f(c, code)
                _valcode_map[code].__name__ = '%s(code=0x%02X)' % (_valcode_f.__name__, code)
        except TypeError:
            _valcode_map[self.valcode] = _valcode_f
        return _valcode_f

class Register(object):
    def __init__(self, regcode):
        self.regcode = regcode
    def __get__(self, c, type=None):
        return c.r[self.regcode]
    def __set__(self, c, value):
        c.r[self.regcode] = value & wmask

@opcode(0x0, 0x01)
def JSR(c, a):
    """pushes the address of the next instruction to the stack, then sets PC to a"""
    c.sp = (c.sp - 1) & wmask
    c.m[c.sp] = c.pc
    c.pc = a()

@opcode(0x1)
def SET(c, a, b):
    """sets a to b"""
    a.set(b())

@opcode(0x2)
def ADD(c, a, b):
    """sets a to a+b, sets O to 0x0001 if there's an overflow"""
    res = (a() + b())
    if res > wmask:
        c.o = 0x0001
    res = res & wmask
    a.set(res)

@opcode(0x3)
def SUB(c, a, b):
    """sets a to a-b, sets O to 0xFFFF if there's an underflow"""
    res = (a() - b())
    if res & (wmask+1):
        c.o = 0xFFFF
    res = res & wmask
    a.set(res)

@opcode(0x4)
def MUL(c, a, b):
    """sets a to a*b, sets O to ((a*b)>>16)&0xFFFF"""
    res = (a() * b())
    c.o = ((a() * b()) >> w) & wmask
    res = res & wmask
    a.set(res)

@opcode(0x5)
def DIV(c, a, b):
    """sets a to a/b, sets O to ((a<<16)/b)&0xFFFF"""
    res = a() // b()
    c.o = ((a() << w) // b()) & wmask
    a.set(res)

@opcode(0x6)
def MOD(c, a, b):
    """sets a to a%b. if b==0, sets a to 0 instead"""
    if b()==0:
        res = 0
    else:
        res = a() % b()
    a.set(res)

@opcode(0x7)
def SHL(c, a, b):
    """sets a to a<<b. sets O to ((a<<b)>>16)&0xFFFF"""
    res = (a() << b())
    c.o = ((a() << b()) >> w) & wmask
    res = res & wmask
    a.set(res)

@opcode(0x8)
def SHR(c, a, b):
    """sets a to a>>b. sets O to ((a>>16)>>b)&0xFFFF"""
    res = (a() >> b())
    c.o = ((a() >> w) >> b()) & wmask
    res = res & wmask
    a.set(res)

@opcode(0x9)
def AND(c, a, b):
    """sets a to a&b"""
    res = a() & b()
    a.set(res)

@opcode(0xA)
def BOR(c, a, b):
    """sets a to a|b"""
    res = a() | b()
    a.set(res)

@opcode(0xB)
def XOR(c, a, b):
    """sets a to a^b"""
    res = a() ^ b()
    a.set(res)

@opcode(0xC)
def IFE(c, a, b):
    """performs next instruction only if a==b"""
    if a() == b():
        c.skip = False
    else:
        c.skip = True

@opcode(0xD)
def IFN(c, a, b):
    """performs next instruction only if a!=b"""
    if a() != b():
        c.skip = False
    else:
        c.skip = True

@opcode(0xE)
def IFG(c, a, b):
    """performs next instruction only if a>b"""
    if a() > b():
        c.skip = False
    else:
        c.skip = True

@opcode(0xF)
def IFB(c, a, b):
    """performs next instruction only if (a&b)!=0"""
    if (a() & b()) != 0:
        c.skip = False
    else:
        c.skip = True

def make_pointer(c, codestr):
    """creates a pointer func that evaluates codestr"""
    def getter(c=c):
        return eval("%s" % codestr)
    def setter(data, c=c):
        exec("%s = %r" % (codestr, data)) in {}, {'c': c, 'data': data}
    pointer     = getter
    pointer.codestr = codestr
    pointer.set = setter
    return pointer

def pointerize(f):
    """wraps a function that generates a codestr to create a pointer"""
    if f.func_code.co_argcount == 1:
        ptrz = lambda c: make_pointer(c, f(c))
    elif f.func_code.co_argcount == 2:
        ptrz = lambda c, code: make_pointer(c, f(c, code))
    else:
        raise Exception('%s has too many arguments' % f.__name__)
    ptrz.__name__ = 'ptr_to_%s' % f.__name__
    ptrz.__doc__ = f.__doc__
    return ptrz

@valcode(range(0x00, 0x08))
@pointerize
def register(c, code):
    """register"""
    v = "c.r[0x%01X]" % code
    return v

@valcode(range(0x08, 0x10))
@pointerize
def register_value(c, code):
    """[register]"""
    v = "c.m[c.r[0x%01X]]" % (code-0x07)
    return v

@valcode(range(0x10, 0x18))
@pointerize
def next_word_plus_register_value(c, code):
    """[next word + register]"""
    v = "c.m[0x%04X + c.r[0x%01X]]" % (c.m[c.pc], code-0x0F)
    c.pc = (c.pc + 1) & wmask
    return v

@valcode(0x18)
@pointerize
def pop(c):
    """POP / [SP++]"""
    v = "c.m[0x%04X]" % c.sp
    c.sp = (c.sp + 1) & wmask
    return v

@valcode(0x19)
@pointerize
def peek(c):
    """PEEK / [SP]"""
    v = "c.m[0x%04X]" % c.sp
    return v

@valcode(0x1A)
@pointerize
def push(c):
    """PUSH / [--SP]"""
    c.sp = (c.sp - 1) & wmask
    v = "c.m[0x%04X]" % c.sp
    return v

@valcode(0x1B)
@pointerize
def stack_pointer(c):
    """stack pointer"""
    v = "c.sp"
    return v

@valcode(0x1C)
@pointerize
def program_counter(c):
    """program counter"""
    v = "c.pc"
    return v

@valcode(0x1D)
@pointerize
def overflow(c):
    """overflow"""
    v = "c.o"
    return v

@valcode(0x1E)
@pointerize
def next_word_value(c):
    """[next_word]"""
    v = "c.m[0x%04X]" % c.m[c.pc]
    c.pc = (c.pc + 1) & wmask
    return v

@valcode(0x1F)
@pointerize
def next_word(c):
    """next_word (literal)"""
    v = "c.m[0x%04X]" % c.pc
    c.pc = (c.pc + 1) & wmask
    return v

@valcode(range(0x20, 0x40))
@pointerize
def literal(c, code):
    """literal value 0x00-0x1F (literal)"""
    v = "0x%04X" % (code - 0x20)
    return v

class CPU(object):
    def __init__(c, debug=False):
        c.clear()
        c.reset()
        c.debug = debug

    def reset(c):
        """reset CPU"""
        c.r = [0 for _ in xrange(0, 8)]
        c.pc = 0x0000
        c.sp = 0x0000
        c.o  = 0x0000
        c.skip = False

    def clear(c):
        """clear memory"""
        c.m = [0 for _ in xrange(0, 2**w)]

    a = Register(0x0)
    b = Register(0x1)
    c = Register(0x2)
    x = Register(0x3)
    y = Register(0x4)
    z = Register(0x5)
    i = Register(0x6)
    j = Register(0x7)

    def _op(c, word):
        """dispatch word to op and args"""
        opcode = word & 0xF
        a_code = word >>  4 & 0x3F
        b_code = word >> 10 & 0x3F
        try:
            op = _opcode_map[opcode]
            try:
                op = op[a_code]
            except TypeError:
                args = (c._pointer(a_code),
                        c._pointer(b_code))
            else:
                args = (c._pointer(b_code),)
            finally:
                if c.debug:
                    log(' '.join([op.__name__] + [arg.codestr for arg in args]))
        except KeyError:
            raise Exception('Invalid opcode %s at PC=%04X' % (["%02X"%x for x in opcode], c.pc))
        return op, args

    def _pointer(c, code):
        """get pointer to valcode"""
        try:
            return _valcode_map[code](c)
        except KeyError:
            raise Exception("Invalid valcode")

    def __getitem__(c, code):
        """get value of valcode"""
        return c._pointer(code)()

    def __setitem__(c, code, value):
        """set value at valcode"""
        c._pointer(code).set(value)

    def step(c):
        """start handling [PC]"""
        word = c.m[c.pc]
        c.pc = (c.pc + 1) & wmask
        op, args = c._op(word)
        if c.skip:
            c.skip = False
            if c.debug: log("Skipped")
        else:
            op(c, *args)
        if c.debug: log(c.dump_r())

    def run(c):
        """step until PC is constant"""
        last_pc = 0xFFFF
        while c.pc != last_pc:
            last_pc = c.pc
            c.step()
        log("Infinite loop")

    def dump_r(c):
        """human-readable register status"""
        return " ".join( "%s=%04X" %
                (["A", "B", "C",
                  "X", "Y", "Z",
                  "I", "J",
                  "PC", "SP", "O",
                  ][i],
                  (c.r + [c.pc, c.sp, c.o])[i])
                for i in range(11))

    def load_m(c, data=None, io=None):
        """load data in memory"""
        # TODO: load from io object
        for i in xrange(len(data)):
            c.m[i] = data[i]

    def dump_m(c, io):
        """dump memory data"""
        # TODO: save to io object
        pass

spec_demo = [
    0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d,
    0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
    0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a,
    0x9037, 0x61c1, 0x7dc1, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000,
]
<commit_msg>all registers wrapped as 16 bits<commit_after>from __future__ import print_function, division

def log(string):
    print(" << %s" % string)

#http://0x10c.com/doc/dcpu-16.txt
spec = '1.1'

w = 16
wmask = 2**w - 1

literals = [l for l in xrange(0, 0x20)]

_opcode_map = {}
_valcode_map = {}

class opcode(object):
    def __init__(self, *opcode):
        self.opcode = opcode

    def __call__(self, f):
        _opcode_f = f
        _opcode_f.opcode = self.opcode
        if len(self.opcode) == 1:
            _opcode_map[self.opcode[0]] = _opcode_f
        else:
            if not self.opcode[0] in _opcode_map.keys():
                _opcode_map[self.opcode[0]] = {}
            _opcode_map[self.opcode[0]][self.opcode[1]] = _opcode_f
        return _opcode_f

class valcode(object):
    def __init__(self, valcode):
        self.valcode = valcode

    def __call__(self, f):
        _valcode_f = f
        _valcode_f.valcode = self.valcode
        try:
            for code in self.valcode:
                # currify with (bound) code
                _valcode_map[code] = lambda c, code=code: _valcode_f(c, code)
                _valcode_map[code].__name__ = '%s(code=0x%02X)' % (_valcode_f.__name__, code)
        except TypeError:
            _valcode_map[self.valcode] = _valcode_f
        return _valcode_f

class Register(object):
    def __init__(self, regcode=None):
        self.regcode = regcode
    def __get__(self, c, type=None):
        if self.regcode is not None:
            return c.r[self.regcode]
        else:
            return self.value
    def __set__(self, c, value):
        if self.regcode is not None:
            c.r[self.regcode] = value & wmask
        else:
            self.value = value & wmask

@opcode(0x0, 0x01)
def JSR(c, a):
    """pushes the address of the next instruction to the stack, then sets PC to a"""
    c.sp -= 1
    c.m[c.sp] = c.pc
    c.pc = a()

@opcode(0x1)
def SET(c, a, b):
    """sets a to b"""
    a.set(b())

@opcode(0x2)
def ADD(c, a, b):
    """sets a to a+b, sets O to 0x0001 if there's an overflow"""
    res = (a() + b())
    if res > wmask:
        c.o = 0x0001
    res = res & wmask
    a.set(res)

@opcode(0x3)
def SUB(c, a, b):
    """sets a to a-b, sets O to 0xFFFF if there's an underflow"""
    res = (a() - b())
    if res & (wmask+1):
        c.o = 0xFFFF
    res = res & wmask
    a.set(res)

@opcode(0x4)
def MUL(c, a, b):
    """sets a to a*b, sets O to ((a*b)>>16)&0xFFFF"""
    res = (a() * b())
    c.o = ((a() * b()) >> w) & wmask
    res = res & wmask
    a.set(res)

@opcode(0x5)
def DIV(c, a, b):
    """sets a to a/b, sets O to ((a<<16)/b)&0xFFFF"""
    res = a() // b()
    c.o = ((a() << w) // b()) & wmask
    a.set(res)

@opcode(0x6)
def MOD(c, a, b):
    """sets a to a%b. if b==0, sets a to 0 instead"""
    if b()==0:
        res = 0
    else:
        res = a() % b()
    a.set(res)

@opcode(0x7)
def SHL(c, a, b):
    """sets a to a<<b. sets O to ((a<<b)>>16)&0xFFFF"""
    res = (a() << b())
    c.o = ((a() << b()) >> w) & wmask
    res = res & wmask
    a.set(res)

@opcode(0x8)
def SHR(c, a, b):
    """sets a to a>>b. sets O to ((a>>16)>>b)&0xFFFF"""
    res = (a() >> b())
    c.o = ((a() >> w) >> b()) & wmask
    res = res & wmask
    a.set(res)

@opcode(0x9)
def AND(c, a, b):
    """sets a to a&b"""
    res = a() & b()
    a.set(res)

@opcode(0xA)
def BOR(c, a, b):
    """sets a to a|b"""
    res = a() | b()
    a.set(res)

@opcode(0xB)
def XOR(c, a, b):
    """sets a to a^b"""
    res = a() ^ b()
    a.set(res)

@opcode(0xC)
def IFE(c, a, b):
    """performs next instruction only if a==b"""
    if a() == b():
        c.skip = False
    else:
        c.skip = True

@opcode(0xD)
def IFN(c, a, b):
    """performs next instruction only if a!=b"""
    if a() != b():
        c.skip = False
    else:
        c.skip = True

@opcode(0xE)
def IFG(c, a, b):
    """performs next instruction only if a>b"""
    if a() > b():
        c.skip = False
    else:
        c.skip = True

@opcode(0xF)
def IFB(c, a, b):
    """performs next instruction only if (a&b)!=0"""
    if (a() & b()) != 0:
        c.skip = False
    else:
        c.skip = True

def make_pointer(c, codestr):
    """creates a pointer func that evaluates codestr"""
    def getter(c=c):
        return eval("%s" % codestr)
    def setter(data, c=c):
        exec("%s = %r" % (codestr, data)) in {}, {'c': c, 'data': data}
    pointer     = getter
    pointer.codestr = codestr
    pointer.set = setter
    return pointer

def pointerize(f):
    """wraps a function that generates a codestr to create a pointer"""
    if f.func_code.co_argcount == 1:
        ptrz = lambda c: make_pointer(c, f(c))
    elif f.func_code.co_argcount == 2:
        ptrz = lambda c, code: make_pointer(c, f(c, code))
    else:
        raise Exception('%s has too many arguments' % f.__name__)
    ptrz.__name__ = 'ptr_to_%s' % f.__name__
    ptrz.__doc__ = f.__doc__
    return ptrz

@valcode(range(0x00, 0x08))
@pointerize
def register(c, code):
    """register"""
    v = "c.r[0x%01X]" % code
    return v

@valcode(range(0x08, 0x10))
@pointerize
def register_value(c, code):
    """[register]"""
    v = "c.m[c.r[0x%01X]]" % (code-0x07)
    return v

@valcode(range(0x10, 0x18))
@pointerize
def next_word_plus_register_value(c, code):
    """[next word + register]"""
    v = "c.m[0x%04X + c.r[0x%01X]]" % (c.m[c.pc], code-0x0F)
    c.pc += 1
    return v

@valcode(0x18)
@pointerize
def pop(c):
    """POP / [SP++]"""
    v = "c.m[0x%04X]" % c.sp
    c.sp += 1
    return v

@valcode(0x19)
@pointerize
def peek(c):
    """PEEK / [SP]"""
    v = "c.m[0x%04X]" % c.sp
    return v

@valcode(0x1A)
@pointerize
def push(c):
    """PUSH / [--SP]"""
    c.sp -= 1
    v = "c.m[0x%04X]" % c.sp
    return v

@valcode(0x1B)
@pointerize
def stack_pointer(c):
    """stack pointer"""
    v = "c.sp"
    return v

@valcode(0x1C)
@pointerize
def program_counter(c):
    """program counter"""
    v = "c.pc"
    return v

@valcode(0x1D)
@pointerize
def overflow(c):
    """overflow"""
    v = "c.o"
    return v

@valcode(0x1E)
@pointerize
def next_word_value(c):
    """[next_word]"""
    v = "c.m[0x%04X]" % c.m[c.pc]
    c.pc += 1
    return v

@valcode(0x1F)
@pointerize
def next_word(c):
    """next_word (literal)"""
    v = "c.m[0x%04X]" % c.pc
    c.pc += 1
    return v

@valcode(range(0x20, 0x40))
@pointerize
def literal(c, code):
    """literal value 0x00-0x1F (literal)"""
    v = "0x%04X" % (code - 0x20)
    return v

class CPU(object):
    def __init__(c, debug=False):
        c.clear()
        c.reset()
        c.debug = debug

    def reset(c):
        """reset CPU"""
        c.r = [0 for _ in xrange(0, 8)]
        c.pc = 0x0000
        c.sp = 0x0000
        c.o  = 0x0000
        c.skip = False

    def clear(c):
        """clear memory"""
        c.m = [0 for _ in xrange(0, 2**w)]

    a = Register(0x0)
    b = Register(0x1)
    c = Register(0x2)
    x = Register(0x3)
    y = Register(0x4)
    z = Register(0x5)
    i = Register(0x6)
    j = Register(0x7)
    pc = Register()
    sp = Register()
    o = Register()

    def _op(c, word):
        """dispatch word to op and args"""
        opcode = word & 0xF
        a_code = word >>  4 & 0x3F
        b_code = word >> 10 & 0x3F
        try:
            op = _opcode_map[opcode]
            try:
                op = op[a_code]
            except TypeError:
                args = (c._pointer(a_code),
                        c._pointer(b_code))
            else:
                args = (c._pointer(b_code),)
            finally:
                if c.debug:
                    log(' '.join([op.__name__] + [arg.codestr for arg in args]))
        except KeyError:
            raise Exception('Invalid opcode %s at PC=%04X' % (["%02X"%x for x in opcode], c.pc))
        return op, args

    def _pointer(c, code):
        """get pointer to valcode"""
        try:
            return _valcode_map[code](c)
        except KeyError:
            raise Exception("Invalid valcode")

    def __getitem__(c, code):
        """get value of valcode"""
        return c._pointer(code)()

    def __setitem__(c, code, value):
        """set value at valcode"""
        c._pointer(code).set(value)

    def step(c):
        """start handling [PC]"""
        word = c.m[c.pc]
        c.pc += 1
        op, args = c._op(word)
        if c.skip:
            c.skip = False
            if c.debug: log("Skipped")
        else:
            op(c, *args)
        if c.debug: log(c.dump_r())

    def run(c):
        """step until PC is constant"""
        last_pc = 0xFFFF
        while c.pc != last_pc:
            last_pc = c.pc
            c.step()
        log("Infinite loop")

    def dump_r(c):
        """human-readable register status"""
        return " ".join( "%s=%04X" %
                (["A", "B", "C",
                  "X", "Y", "Z",
                  "I", "J",
                  "PC", "SP", "O",
                  ][i],
                  (c.r + [c.pc, c.sp, c.o])[i])
                for i in range(11))

    def load_m(c, data=None, io=None):
        """load data in memory"""
        # TODO: load from io object
        for i in xrange(len(data)):
            c.m[i] = data[i]

    def dump_m(c, io):
        """dump memory data"""
        # TODO: save to io object
        pass

spec_demo = [
    0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d,
    0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
    0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a,
    0x9037, 0x61c1, 0x7dc1, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000,
]
<|endoftext|>


<commit_before># coding: utf-8
#!/usr/bin/env python

# OZ TV
# Author:  Birkir Gudjonsson (birkir.gudjonsson@gmail.com)
# Port of the popular OZ app for android and ios devices.
#
# TODO: Add genres for vod
#       Add following
#       Add context menu
#       Content type for series, episodes or movies with fanart

import urllib, urllib2, re, xbmcaddon, xbmcplugin, xbmcgui, xbmc
from oz import *

# Plugin constants
__addonid__   = "plugin.video.oztv"
__addon__     = xbmcaddon.Addon(id=__addonid__)
__language__  = __addon__.getLocalizedString

action_key = None
action_value = None
name = None

def showMenu():
	items = []
	items.append([0, 'Now', 'schedule', ''])
	items.append([1, 'Channels', 'channels', ''])
	items.append([2, 'Movies', 'vod', 'movies'])
	items.append([3, 'TV Shows', 'vod', 'series'])

	for item in items:
		addMenuItem(item[1], item[2], item[3])

def showSchedule():
	channels = getChannels()
	items = getNowAndNext(channels)
	for item in items:
		if item[0] == None or 'content' not in item[0]:
			continue
		content = item[0]['content']
		channel = extractChannel(channels, item[0]['channel'])
		name = channel['name'] + ': ' + parseName(content)
		still = 'http://image.l3.cdn.oz.com/still/'+item[0]['channel']+'/tn'
		name = name.encode('utf-8').strip()
		offering = channel['offerings'][0]
		addMenuItem(name, 'play_offering', offering['organization']+','+offering['key'], still)

def showChannels():
	channels = getChannels()
	for channel in channels:
		name = channel['name'].encode('utf-8').strip()
		offering = channel['offerings'][0]
		logo = channel['media']['icon']
		addMenuItem(name, 'play_offering', offering['organization']+','+offering['key'], logo)

def showVod(type):
	page = 0
	items = getVodWithType(type, page)
	for item in items:
		if 'series' in item:
			series = item['series']
			name = series['title']
			still = parseStill(series)
			addMenuItem(name.encode('utf-8').strip(), 'vod_series', series['id'], still)
		else:
			content = item['content']
			offering = item['offerings'][0]
			name = parseName(content)
			still = parseStill(content)
			addMenuItem(name.encode('utf-8').strip(), 'play_offering', offering['organization']+','+offering['key'], still)

def showVodSeries(series):
	episodes = getVodSeriesEpisodes(series)
	for episode in episodes:
		content = episode['content']
		name = parseName(content)
		offering = episode['offerings'][0]
		still = parseStill(content)
		addMenuItem(name.encode('utf-8').strip(), 'play_offering', offering['organization']+','+offering['key'], still)

def playOffering(param):
	data = param.split(',')
	offering = getOffering(data[0], data[1])
	if 'message' in offering:
		showDialog(offering['message'])
	else:
		#xbmc.PlayerCDVDInputStreamFFmpeg
		xbmc.Player().play(offering['url'])

def parseName(content):
	name = content['title'] + ' '
	if 'season_number' in content:
		season_number = content['season_number']
		episode_number = content['episode_number']
		if season_number < 10:
			season_number = str('0') + str(season_number)
		if episode_number < 10:
			episode_number = str('0') + str(episode_number)
		name += 'S' + str(season_number) + 'E' + str(episode_number)
	elif 'number_of_episodes' in content:
		name += str(content['episode_number']) + '/' + str(content['number_of_episodes'])
	elif 'year' in content:
		name += '(' + str(content['year']) + ')'
	return name

def parseStill(item):
	if 'stills' in item:
		for still in item['stills']:
			return 'https://oz-img.global.ssl.fastly.net' + still
	return ''

def extractChannel(channels, channel):
	for chan in channels:
		if chan['key'] == channel:
			return chan

def addMenuItem(foo, bar, baz, abba):
	print(foo+': ' + bar)

def showDialog(msg):
	print 'error: ' + str(msg)

def get_params():
	param=[]
	paramstring=sys.argv[2]
	if len(paramstring)>=2:
		params=sys.argv[2]
		cleanedparams=params.replace('?','')
		if (params[len(params)-1]=='/'):
			params=params[0:len(params)-2]
		pairsofparams=cleanedparams.split('&')
		param={}
		for i in range(len(pairsofparams)):
			splitparams={}
			splitparams=pairsofparams[i].split('=')
			if (len(splitparams))==2:
				param[splitparams[0]]=splitparams[1]

	return param

def addMenuItem(name, action_key, action_value, iconimage='DefaultFolder.png'):
	is_folder = True
	if action_key == 'play_offering':
		is_folder = False
	u=sys.argv[0]+"?action_key="+urllib.quote_plus(action_key)+"&action_value="+str(action_value)+"&name="+urllib.quote_plus(name)
	liz=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage='')
	liz.setInfo(type="Video", infoLabels={ "Title": name } )
	return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=is_folder)

def showDialog(message):
	dialog = xbmcgui.Dialog()
	dialog.ok('OZ TV', message)

params=get_params()
try:
	action_key = urllib.unquote_plus(params["action_key"])
	action_value = urllib.unquote_plus(params["action_value"])
	name = urllib.unquote_plus(params["name"])
except:
	pass

if action_key is None:
	showMenu()
elif action_key == 'schedule':
	showSchedule()
elif action_key == 'channels':
	showChannels()
elif action_key == 'vod':
	showVod(action_value)
elif action_key == 'vod_series':
	showVodSeries(action_value)
elif action_key == 'play_offering':
	playOffering(action_value)

xbmcplugin.endOfDirectory(int(sys.argv[1]))<commit_msg>Added paging to vod list<commit_after># coding: utf-8
#!/usr/bin/env python

# OZ TV
# Author:  Birkir Gudjonsson (birkir.gudjonsson@gmail.com)
# Port of the popular OZ app for android and ios devices.
#
# TODO: Add genres for vod
#       Add following
#       Add context menu
#       Content type for series, episodes or movies with fanart

import urllib, urllib2, re, xbmcaddon, xbmcplugin, xbmcgui, xbmc
from oz import *

# Plugin constants
__addonid__   = "plugin.video.oztv"
__addon__     = xbmcaddon.Addon(id=__addonid__)
__language__  = __addon__.getLocalizedString

action_key = None
action_value = None
name = None

def showMenu():
	items = []
	items.append([0, 'Now', 'schedule', ''])
	items.append([1, 'Channels', 'channels', ''])
	items.append([2, 'Movies', 'vod', 'movies'])
	items.append([3, 'TV Shows', 'vod', 'series'])

	for item in items:
		addMenuItem(item[1], item[2], item[3])

def showSchedule():
	channels = getChannels()
	items = getNowAndNext(channels)
	for item in items:
		if item[0] == None or 'content' not in item[0]:
			continue
		content = item[0]['content']
		channel = extractChannel(channels, item[0]['channel'])
		name = channel['name'] + ': ' + parseName(content)
		still = 'http://image.l3.cdn.oz.com/still/'+item[0]['channel']+'/tn'
		name = name.encode('utf-8').strip()
		offering = channel['offerings'][0]
		addMenuItem(name, 'play_offering', offering['organization']+','+offering['key'], still)

def showChannels():
	channels = getChannels()
	for channel in channels:
		name = channel['name'].encode('utf-8').strip()
		offering = channel['offerings'][0]
		logo = channel['media']['icon']
		addMenuItem(name, 'play_offering', offering['organization']+','+offering['key'], logo)

def showVod(params):
	params = params.split(',')
	type = params[0]
	page = 0
	if len(params) > 1:
		page = int(params[1])

	addMenuItem(' # Home', '', '')

	if page > 0:
		addMenuItem(' < Previous page'.encode('utf-8'), 'vod', type+','+str(page - 1))

	addMenuItem(' > Next page'.encode('utf-8'), 'vod', type+','+str(page + 1))

	items = getVodWithType(type, page)
	for item in items:
		if 'series' in item:
			series = item['series']
			name = series['title']
			still = parseStill(series)
			addMenuItem(name.encode('utf-8').strip(), 'vod_series', series['id'], still)
		else:
			content = item['content']
			offering = item['offerings'][0]
			name = parseName(content)
			still = parseStill(content)
			addMenuItem(name.encode('utf-8').strip(), 'play_offering', offering['organization']+','+offering['key'], still)

def showVodSeries(series):
	episodes = getVodSeriesEpisodes(series)
	for episode in episodes:
		content = episode['content']
		name = parseName(content)
		offering = episode['offerings'][0]
		still = parseStill(content)
		addMenuItem(name.encode('utf-8').strip(), 'play_offering', offering['organization']+','+offering['key'], still)

def playOffering(param):
	data = param.split(',')
	offering = getOffering(data[0], data[1])
	if 'message' in offering:
		showDialog(offering['message'])
	else:
		xbmc.Player().play(offering['url'])

def parseName(content):
	name = content['title'] + ' '
	if 'season_number' in content:
		season_number = content['season_number']
		episode_number = content['episode_number']
		if season_number < 10:
			season_number = str('0') + str(season_number)
		if episode_number < 10:
			episode_number = str('0') + str(episode_number)
		name += 'S' + str(season_number) + 'E' + str(episode_number)
	elif 'number_of_episodes' in content:
		name += str(content['episode_number']) + '/' + str(content['number_of_episodes'])
	elif 'year' in content:
		name += '(' + str(content['year']) + ')'
	return name

def parseStill(item):
	if 'stills' in item:
		for still in item['stills']:
			return 'https://oz-img.global.ssl.fastly.net' + still + '?width=340'
	return ''

def extractChannel(channels, channel):
	for chan in channels:
		if chan['key'] == channel:
			return chan

def get_params():
	param=[]
	paramstring=sys.argv[2]
	if len(paramstring)>=2:
		params=sys.argv[2]
		cleanedparams=params.replace('?','')
		if (params[len(params)-1]=='/'):
			params=params[0:len(params)-2]
		pairsofparams=cleanedparams.split('&')
		param={}
		for i in range(len(pairsofparams)):
			splitparams={}
			splitparams=pairsofparams[i].split('=')
			if (len(splitparams))==2:
				param[splitparams[0]]=splitparams[1]

	return param

def addMenuItem(name, action_key, action_value, iconimage='DefaultFolder.png'):
	is_folder = True
	if action_key == 'play_offering':
		is_folder = False
	u=sys.argv[0]+"?action_key="+urllib.quote_plus(action_key)+"&action_value="+str(action_value)+"&name="+urllib.quote_plus(name)
	liz=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage='')
	liz.setInfo(type="Video", infoLabels={ "Title": name } )
	return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=is_folder)

def showDialog(message):
	dialog = xbmcgui.Dialog()
	dialog.ok('OZ TV', message)

params=get_params()
try:
	action_key = urllib.unquote_plus(params["action_key"])
	action_value = urllib.unquote_plus(params["action_value"])
	name = urllib.unquote_plus(params["name"])
except:
	pass

if action_key is None:
	showMenu()
elif action_key == 'schedule':
	showSchedule()
elif action_key == 'channels':
	showChannels()
elif action_key == 'vod':
	showVod(action_value)
elif action_key == 'vod_series':
	showVodSeries(action_value)
elif action_key == 'play_offering':
	playOffering(action_value)

xbmcplugin.endOfDirectory(int(sys.argv[1]))<|endoftext|>


<commit_before># Copyright 2015 Isotoma Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from touchdown.core.resource import Resource
from touchdown.core.target import Target, Present
from touchdown.core import argument, serializers

from ..account import Account
from ..iam import ServerCertificate
from ..common import SimpleDescribe, SimpleApply, SimpleDestroy
from ..vpc import Subnet, SecurityGroup

class Listener(Resource):

    resource_name = "listener"

    protocol = argument.String(filed="Protocol")
    port = argument.Integer(field="LoadBalancerPort")
    instance_protocol = argument.String(field="InstanceProtocol")
    instance_port = argument.Integer(field="InstancePort")
    ssl_certificate = argument.Resource(
        ServerCertificate,
        field="SSLCertificiateId",
        serializer=serializers.Property("Arn"),
    )

class HealthCheck(Resource):

    resource_name = "health_check"
    dot_ignore = True

    interval = argument.Integer(field="Interval")
    target = argument.String(field="Target")
    healthy_threshold = argument.Integer(field="HealthyThreshold")
    unhealthy_threshold = argument.Integer(field="UnhealthyThreshold")
    timeout = argument.Integer(field="Timeout")

class LoadBalancer(Resource):

    resource_name = "load_balancer"

    name = argument.String(field="LoadBalancerName")
    listeners = argument.ResourceList(
        Listener,
        field="Listeners",
        serializers=serializers.List(serializers.Resource()),
    )
    availability_zones = argument.List(field="AvailabilityZones")
    scheme = argument.String(choices=["internet-facing", "private"], field="Scheme")
    subnets = argument.ResourceList(Subnet, field="Subnets")
    security_groups = argument.ResourceList(SecurityGroup, field="SecurityGroups")
    # tags = argument.Dict()

    health_check = argument.Resource(HealthCheck)

    account = argument.Resource(Account)

class Describe(SimpleDescribe, Target):

    resource = LoadBalancer
    service_name = 'elb'
    describe_action = "describe_load_balancers"
    describe_list_key = "LoadBalancerDescriptions"
    key = 'LoadBalancerName'

    def get_describe_filters(self):
        return {"LoadBalancerNames": [self.resource.name]}

class Apply(SimpleApply, Describe):

    create_action = "create_load_balancer"

    signature = [
        Present('name'),
        Present('listeners'),
    ]

    def update_object(self):
        if not self.object and self.health_check:
            yield self.generic_action(
                "Configure health check",
                self.client.configure_health_check,
                LoadBalancerName=self.resource.name,
                HealthCheck=serializers.Context(
                    serializers.Const(self.health_check),
                    serializers.Resource(),
                ),
            )

class Destroy(SimpleDestroy, Describe):

    destroy_action = "delete_load_balancer"
<commit_msg>Don't forget to yield from super<commit_after># Copyright 2015 Isotoma Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from touchdown.core.resource import Resource
from touchdown.core.target import Target, Present
from touchdown.core import argument, serializers

from ..account import Account
from ..iam import ServerCertificate
from ..common import SimpleDescribe, SimpleApply, SimpleDestroy
from ..vpc import Subnet, SecurityGroup

class Listener(Resource):

    resource_name = "listener"

    protocol = argument.String(filed="Protocol")
    port = argument.Integer(field="LoadBalancerPort")
    instance_protocol = argument.String(field="InstanceProtocol")
    instance_port = argument.Integer(field="InstancePort")
    ssl_certificate = argument.Resource(
        ServerCertificate,
        field="SSLCertificiateId",
        serializer=serializers.Property("Arn"),
    )

class HealthCheck(Resource):

    resource_name = "health_check"
    dot_ignore = True

    interval = argument.Integer(field="Interval")
    target = argument.String(field="Target")
    healthy_threshold = argument.Integer(field="HealthyThreshold")
    unhealthy_threshold = argument.Integer(field="UnhealthyThreshold")
    timeout = argument.Integer(field="Timeout")

class LoadBalancer(Resource):

    resource_name = "load_balancer"

    name = argument.String(field="LoadBalancerName")
    listeners = argument.ResourceList(
        Listener,
        field="Listeners",
        serializers=serializers.List(serializers.Resource()),
    )
    availability_zones = argument.List(field="AvailabilityZones")
    scheme = argument.String(choices=["internet-facing", "private"], field="Scheme")
    subnets = argument.ResourceList(Subnet, field="Subnets")
    security_groups = argument.ResourceList(SecurityGroup, field="SecurityGroups")
    # tags = argument.Dict()

    health_check = argument.Resource(HealthCheck)

    account = argument.Resource(Account)

class Describe(SimpleDescribe, Target):

    resource = LoadBalancer
    service_name = 'elb'
    describe_action = "describe_load_balancers"
    describe_list_key = "LoadBalancerDescriptions"
    key = 'LoadBalancerName'

    def get_describe_filters(self):
        return {"LoadBalancerNames": [self.resource.name]}

class Apply(SimpleApply, Describe):

    create_action = "create_load_balancer"

    signature = [
        Present('name'),
        Present('listeners'),
    ]

    def update_object(self):
        for action in super(Apply, self).update_object():
            yield action

        if not self.object and self.health_check:
            yield self.generic_action(
                "Configure health check",
                self.client.configure_health_check,
                LoadBalancerName=self.resource.name,
                HealthCheck=serializers.Context(
                    serializers.Const(self.health_check),
                    serializers.Resource(),
                ),
            )

class Destroy(SimpleDestroy, Describe):

    destroy_action = "delete_load_balancer"
<|endoftext|>