<commit_before># -*- coding: utf-8 -*-
import logging
import os
import tempfile
import hashlib

from jpegtran import JPEGImage

from spreads.config import OptionTemplate
from spreads.plugin import DevicePlugin, DeviceFeatures

import piggyphoto as pp

class GPhoto2CameraDevice(DevicePlugin):
    """ Plugin for digital cameras communicating via raw PTP.

    """
    features = (DeviceFeatures.PREVIEW, DeviceFeatures.IS_CAMERA)

    target_page = None

    @classmethod
    def configuration_template(cls):
        conf = super(GPhoto2CameraDevice, cls).configuration_template()
        conf.update(
            {'iso': OptionTemplate(u"Auto", "The ISO value"),
             'shutter_speed': OptionTemplate(
                 u"1/25", "The shutter speed as a fraction"),
             'aperture': OptionTemplate(
                 u"5.6", "The shutter speed as an f-stop"),
             'shoot_raw': OptionTemplate(False, "Shoot in RAW format (DNG)")
             })
        return conf

    @classmethod
    def yield_devices(cls, config):
        """ Search for usable devices, yield one at a time

        :param config:  spreads configuration
        :type config:   spreads.config.ConfigView

        """
        pil = pp.portInfoList()
        for name, path in pp.cameraList(autodetect=True).toList():
            pi = pil.get_info(pil.lookup_path(path))
            logger = logging.getLogger('GPhoto2Camera')
            logger.debug("Connecting to camera {} at {}".format(name, path))
            cam = pp.camera(autoInit=False)
            cam.port_info = pi
            cam.init()
            yield cls(config, cam)

    def __init__(self, config, camera):
        """ Set connection information and try to obtain target page.

        :param config:  spreads configuration
        :type config:   spreads.confit.ConfigView
        :param camera:  camera device
        :type camera:   `camera <http://github.com/piggyphoto>`

        """
        self.logger = logging.getLogger('GPhoto2Camera')
        self._camera = camera
        self.config = config

        try:
            serialnumber = self._camera.config['status']['serialnumber'].value
            self.target_page = config['target_page'][serialnumber].get()
        except:
            self.target_page = None

        self.logger = logging.getLogger('GPhoto2Camera[{0}]'
                                        .format(self.target_page))

    def connected(self):
        try:
            # check if we're connected by accessing the config, which is backed
            # by a getter function that attempts to retrieve the config from the
            # camera (and throws libgphoto2error if unable to communicate with it).
            self._camera.config
            return True
        except pp.libgphoto2error:
            return False

    def set_target_page(self, target_page):
        """ Set the device target page.

        :param target_page: The target page name
        :type target_page:  unicode in (u"odd", u"even")

        """
        # Map this in the spreads config keyed by the camera serial number.
        # We can't use the approach taken by CHDKCameraDevice, because most PTP cameras don't support writing
        # files via PTP.
        self.config['target_page'][self._camera.config['status']['serialnumber'].value].set(target_page)

    def prepare_capture(self, path):
        iso = str(self.config['iso'].get())
        shoot_raw = self.config['shoot_raw'].get(bool)
        shutter_speed = str(self.config["shutter_speed"].get())
        aperture = str(self.config['aperture'].get())

        cfg = self._camera.config
        mode = cfg['capturesettings']['autoexposuremode']

        self.logger.debug("Camera mode: {}".format(mode))
        self.logger.debug("Setting iso={}, shutter_speed={}, aperture={}, raw={}".format(iso, shutter_speed, aperture, shoot_raw))

        cfg['imgsettings']['iso'].value = iso

        if shoot_raw:
            format = 'RAW'
        else:
            format = 'Large Fine JPEG'
        cfg['imgsettings']['imageformat'].value = format
        cfg['imgsettings']['imageformatsd'].value = format

        if cfg['capturesettings']['shutterspeed']:
            cfg['capturesettings']['shutterspeed'].value = shutter_speed
        else:
            self.logger.debug("Skipping shutter_speed config due to camera mode ({})".format(mode))

        if cfg['capturesettings']['aperture']:
            cfg['capturesettings']['aperture'].value = aperture
        else:
            self.logger.debug("Skipping aperture config due to camera mode ({})".format(mode))

        self._camera.config = cfg

    def finish_capture(self):
        pass

    def get_preview_image(self):
        fpath = tempfile.mkstemp()[1]
        self._camera.capture_preview(fpath)
        with open(fpath, 'rb') as fp:
            data = fp.read()
        os.remove(fpath)
        return data

    def capture(self, path):
        shoot_raw = self.config['shoot_raw'].get(bool)

        # TODO: support choosing jpg size
        # TODO: support choosing sraw vs raw
        # TODO: support capturing raw + jpeg

        extension = 'cr2' if shoot_raw else 'jpg' # TODO: choose raw extension based on camera vendor
        local_path = "{0}.{1}".format(path, extension)

        self._camera.capture_image(local_path)

        # Set EXIF orientation
        self.logger.debug("Setting EXIF orientation on captured image")
        img = JPEGImage(local_path)
        if self.target_page == 'odd':
            img.exif_orientation = 6  # -90°
        else:
            img.exif_orientation = 8  # 90°
        img.save(local_path)

    def _acquire_focus(self):
        raise NotImplementedError
<commit_msg>flake8 style cleanup<commit_after># -*- coding: utf-8 -*-
import logging
import os
import tempfile

from jpegtran import JPEGImage

from spreads.config import OptionTemplate
from spreads.plugin import DevicePlugin, DeviceFeatures

import piggyphoto as pp

class GPhoto2CameraDevice(DevicePlugin):
    """ Plugin for digital cameras communicating via raw PTP.

    """
    features = (DeviceFeatures.PREVIEW, DeviceFeatures.IS_CAMERA)

    target_page = None

    @classmethod
    def configuration_template(cls):
        conf = super(GPhoto2CameraDevice, cls).configuration_template()
        conf.update(
            {'iso': OptionTemplate(u"Auto", "The ISO value"),
             'shutter_speed': OptionTemplate(
                 u"1/25", "The shutter speed as a fraction"),
             'aperture': OptionTemplate(
                 u"5.6", "The shutter speed as an f-stop"),
             'shoot_raw': OptionTemplate(False, "Shoot in RAW format (DNG)")
             })
        return conf

    @classmethod
    def yield_devices(cls, config):
        """ Search for usable devices, yield one at a time

        :param config:  spreads configuration
        :type config:   spreads.config.ConfigView

        """
        pil = pp.portInfoList()
        for name, path in pp.cameraList(autodetect=True).toList():
            pi = pil.get_info(pil.lookup_path(path))
            logger = logging.getLogger('GPhoto2Camera')
            logger.debug("Connecting to camera {} at {}".format(name, path))
            cam = pp.camera(autoInit=False)
            cam.port_info = pi
            cam.init()
            yield cls(config, cam)

    def __init__(self, config, camera):
        """ Set connection information and try to obtain target page.

        :param config:  spreads configuration
        :type config:   spreads.confit.ConfigView
        :param camera:  camera device
        :type camera:   `camera <http://github.com/piggyphoto>`

        """
        self.logger = logging.getLogger('GPhoto2Camera')
        self._camera = camera
        self.config = config

        try:
            serialnumber = self._camera.config['status']['serialnumber'].value
            self.target_page = config['target_page'][serialnumber].get()
        except:
            self.target_page = None

        self.logger = logging.getLogger('GPhoto2Camera[{0}]'
                                        .format(self.target_page))

    def connected(self):
        try:
            # check if we're connected by accessing the config, which is
            # backed by a getter function that attempts to retrieve the
            # config from the camera (and throws libgphoto2error if unable
            # to communicate with it).
            self._camera.config
            return True
        except pp.libgphoto2error:
            return False

    def set_target_page(self, target_page):
        """ Set the device target page.

        :param target_page: The target page name
        :type target_page:  unicode in (u"odd", u"even")

        """
        # Map this in the spreads config keyed by the camera serial number.
        # We can't use the approach taken by CHDKCameraDevice, because most
        # PTP cameras don't support writing files via PTP.
        serialnumber = self._camera.config['status']['serialnumber'].value
        self.config['target_page'][serialnumber].set(target_page)

    def prepare_capture(self, path):
        iso = str(self.config['iso'].get())
        shoot_raw = self.config['shoot_raw'].get(bool)
        shutter_speed = str(self.config["shutter_speed"].get())
        aperture = str(self.config['aperture'].get())

        cfg = self._camera.config
        mode = cfg['capturesettings']['autoexposuremode']

        self.logger.debug("Camera mode: {}".format(mode))
        self.logger.debug(
            "Setting iso={}, shutter_speed={}, aperture={}, raw={}"
            .format(iso, shutter_speed, aperture, shoot_raw))

        cfg['imgsettings']['iso'].value = iso

        if shoot_raw:
            format = 'RAW'
        else:
            format = 'Large Fine JPEG'
        cfg['imgsettings']['imageformat'].value = format
        cfg['imgsettings']['imageformatsd'].value = format

        if cfg['capturesettings']['shutterspeed']:
            cfg['capturesettings']['shutterspeed'].value = shutter_speed
        else:
            self.logger.debug(
                "Skipping shutter_speed config due to camera mode ({})"
                .format(mode))

        if cfg['capturesettings']['aperture']:
            cfg['capturesettings']['aperture'].value = aperture
        else:
            self.logger.debug(
                "Skipping aperture config due to camera mode ({})"
                .format(mode))

        self._camera.config = cfg

    def finish_capture(self):
        pass

    def get_preview_image(self):
        fpath = tempfile.mkstemp()[1]
        self._camera.capture_preview(fpath)
        with open(fpath, 'rb') as fp:
            data = fp.read()
        os.remove(fpath)
        return data

    def capture(self, path):
        shoot_raw = self.config['shoot_raw'].get(bool)

        # TODO: support choosing jpg size
        # TODO: support choosing sraw vs raw
        # TODO: support capturing raw + jpeg
        # TODO: choose raw extension based on camera vendor

        extension = 'cr2' if shoot_raw else 'jpg'
        local_path = "{0}.{1}".format(path, extension)

        self._camera.capture_image(local_path)

        # Set EXIF orientation
        self.logger.debug("Setting EXIF orientation on captured image")
        img = JPEGImage(local_path)
        if self.target_page == 'odd':
            img.exif_orientation = 6  # -90°
        else:
            img.exif_orientation = 8  # 90°
        img.save(local_path)

    def _acquire_focus(self):
        raise NotImplementedError
<|endoftext|>


<commit_before># from .data_properties import DataProperties
from collections import OrderedDict
import odo            # Make optional?
import blinker
from .data_conversion import DataConversion, ConversionUnknown

class _DataObjectRegistry():
    registered_types = OrderedDict()

    registered_default_types = {}

    @staticmethod
    def register_type(default=False):
        """Decorator that registers the data type

        :param default: Whether to serve as DataObject.from_native handler
           for the real type of the data object.
        :return:

        Automatically discovers conversion in the form of __to_type__ and __from_type__
        (see DataConversion.discover)
        """
        if isinstance(default, type):
            raise RuntimeError("Invalid use of decorator. Please, use DataObject.register_type() ")
        def wrap(boadata_type):
            DataObject.registered_types[boadata_type.type_name] = boadata_type
            DataConversion.discover(boadata_type)
            if default:
                DataObject.registered_default_types[boadata_type.real_type] = boadata_type
            boadata_type._registered = True
            return boadata_type
        return wrap

class _DataObjectConversions():
    @classmethod
    def accepts_uri(cls, uri):
        """

        :type uri: str
        """
        return False

    @classmethod
    def from_uri(cls, uri, **kwargs):
        """"Create an object of this class from an URI.

        :param uri: URI in the odo sense
        :type uri: str

        This method can be (but needn't be) overridden in daughter classes:
        By default, it uses odo to import the data.

        When called as DataObject.from_uri, it first tries to find an appropriate class
        by checking all registered types.
        """
        if cls == DataObject:
            for type_ in DataObject.registered_types.values():
                if type_.accepts_uri(uri):
                    return type_.from_uri(uri, **kwargs)
            raise BaseException("Cannot interpret " + uri + ".")
        else:
            inner_data = odo.odo(uri, cls.real_type, **kwargs)
            return cls(inner_data=inner_data, uri=uri, **kwargs)

    @classmethod
    def from_native(cls, native_object, **kwargs):
        """

        :param native_object:
        :param kwargs:
        :return:

        Is idempotent
        """
        if cls == DataObject:
            if isinstance(native_object, DataObject):
                return native_object
            boadata_type = DataObject.registered_default_types.get(type(native_object))
            if not boadata_type:
                raise RuntimeError("Native object of the type {0} not understood.".format(type(native_object).__name__))
            return boadata_type.from_native(native_object, **kwargs)
        else:
            if isinstance(native_object, DataObject):
                return native_object.convert(cls.type_name, **kwargs)
            return cls(inner_data=native_object, **kwargs)

    def is_convertible_to(self, new_type_name):
        """

        :type new_type_name: str | type
        :rtype: bool
        """
        if isinstance(new_type_name, type):
            new_type, new_type_name = new_type_name, new_type_name.type_name
        else:
            if not new_type_name in DataObject.registered_types:
                return False
            new_type = DataObject.registered_types[new_type_name]
        if isinstance(self, new_type):
            return True
        if not (self.type_name, new_type_name) in DataConversion.registered_conversions:
            return False
        conversion = DataConversion.registered_conversions[(self.type_name, new_type_name)]
        return conversion.applies(self)

    @classmethod
    def is_convertible_from(cls, data_object):
        return data_object.is_convertible_to(cls)

    @property
    def allowed_conversions(self):
        return [ key for (key, conversion) in DataConversion.registered_conversions.items() if key[0] == self.type_name and conversion.applies(self, key[1])]

    def convert(self, new_type_name, **kwargs):
        """Convert to another boadata-supported type.

        :type new_type_name: str
        :rtype DataObject

        Auto-conversion returns the same object.
        Default implementation is based on odo.
        """
        # TODO: check argument?

        new_type = DataObject.registered_types[new_type_name]
        if isinstance(self, new_type):
            return self
        conversion = DataConversion.registered_conversions.get((self.__class__.type_name, new_type_name))
        if not conversion:
            raise ConversionUnknown("Unknown conversion from {0} to {1}".format(self.__class__.type_name, new_type_name))
        return conversion.convert(self, new_type, **kwargs)

class _DataObjectInterface():
    """

    Possible methods:
    - add_column(key, expression, **kwargs) - based on evaluate
    -
    """
    @property
    def shape(self):
        """Shape of the data.

        :rtype: tuple(int)

        Example: Shape of the 4x3 matrix is (4, 3)
        """
        if hasattr(self.inner_data, "shape"):
            return tuple(self.inner_data.shape)
        return ()

    @property
    def ndim(self):
        """Dimensionality of the data.

        :rtype: int

        Example: A 4x3 matrix has dimensionality 2.
        """
        if hasattr(self.inner_data, "ndim"):
            return int(self.inner_data.ndim)
        else:
            return len(self.shape)

    @property
    def size(self):
        if hasattr(self.inner_data, "size"):
            return int(self.inner_data.size)
        else:
            from operator import mul
            from functools import reduce
            reduce(mul, self.shape, 1)

    @property
    def dtype(self):
        if hasattr(self.inner_data, "dtype"):
            return self.inner_data.dtype
        else:
            return None

    @property
    def columns(self):
        """Column names (in multidimensional mappings, the value variables)

        :rtype: list[str] | None

        Default variant understands pandas DataFrames
        """
        if hasattr(self.inner_data, "columns"):
            return list(self.inner_data.columns.values)
        else:
            return None

class DataObject(_DataObjectRegistry, _DataObjectConversions, _DataObjectInterface):
    '''A basic object that contains data representable by boadata.

    :type registered_types: OrderedDict[str, type]
    :type real_type: type | None
    :type type_name: str

    It is necessary to keep all arguments keyword (enforceable in Python 3).
    '''
    def __init__(self, inner_data=None, uri=None, source=None, **kwargs):
        if self.real_type and not isinstance(inner_data, self.real_type):
            raise RuntimeError("Invalid type of inner data: `{0}` instead of expected `{1}`".format(
                inner_data.__class__.__name__, self.real_type.__name__
            ))
        self.inner_data = inner_data
        self.uri = uri
        self.source = source

    changed = blinker.Signal("changed")    # For dynamic data objects

    real_type = None

    type_name = None

    @property
    def title(self):
        return repr(self)

    def __repr__(self):
        return "{0}(\"{1}\")".format(self.__class__.__name__, self.uri)

    @staticmethod
    def proxy_methods(methods, wrap=True, unwrap_args=True, same_class=True, through=None):
        """Decorator to apply on DataObject descendants.

        :param wrap: Whether to wrap result
        :param unwrap_args: Whether to unwrap arguments
        :param same_class: Whether to try to convert to self's class
        :param through: if None, done via inner_data, otherwise through a named type

        It is not possible to proxy slots, but it is possible to inherit proxied slots :-)
        """
        import boadata
        def wrapper(boadata_type):
            if isinstance(methods, str):
                method_names = [methods]
            else:
                method_names = methods

            def make_method(method_name):
                def proxied_method(self, *args, **kwargs):
                    if unwrap_args:
                        args = [boadata.unwrap(arg) for arg in args]
                        kwargs = {key: boadata.unwrap(value) for key, value in kwargs.items()}

                    if through:
                        native_method = getattr(self.convert(through), method_name)
                    else:
                        native_method = getattr(self.inner_data, method_name)
                    result = native_method(*args, **kwargs)
                    if not wrap:
                        return result
                    elif same_class and isinstance(result, self.real_type):
                        return self.__class__.from_native(result)
                    else:
                        try:
                            return DataObject.from_native(result)
                        except:
                            return result
                return proxied_method
            for method_name in method_names:
                setattr(boadata_type, method_name, make_method(method_name))
            return boadata_type
        return wrapper

    def evaluate(self, expression, wrap=True):
        """Do calculation on columns of the dataset.

        :param expression: a valid expression
        :type expression: string

        Based on numexpr library
        """
        import numexpr as ne
        import numpy as np
        local_dict = {
            col : self[col].inner_data for col in self.columns if isinstance(col, str)
        }
        global_dict = {
            "nan" : np.nan,
            "inf" : np.inf
        }
        result = ne.evaluate(expression, local_dict=local_dict, global_dict=global_dict)
        if wrap:
            return DataObject.from_native(result, source=self)
        else:
            return result

class OdoDataObject(DataObject):
    def __init__(self, uri, **kwargs):
        inner_data = odo.resource(uri)
        super(OdoDataObject, self).__init__(inner_data=inner_data, uri=uri, **kwargs)

    @classmethod
    def from_uri(cls, uri, **kwargs):
        return cls(uri=uri, **kwargs)<commit_msg>DataObject.name<commit_after># from .data_properties import DataProperties
from collections import OrderedDict
import odo            # Make optional?
import blinker
from .data_conversion import DataConversion, ConversionUnknown

class _DataObjectRegistry():
    registered_types = OrderedDict()

    registered_default_types = {}

    @staticmethod
    def register_type(default=False):
        """Decorator that registers the data type

        :param default: Whether to serve as DataObject.from_native handler
           for the real type of the data object.
        :return:

        Automatically discovers conversion in the form of __to_type__ and __from_type__
        (see DataConversion.discover)
        """
        if isinstance(default, type):
            raise RuntimeError("Invalid use of decorator. Please, use DataObject.register_type() ")
        def wrap(boadata_type):
            DataObject.registered_types[boadata_type.type_name] = boadata_type
            DataConversion.discover(boadata_type)
            if default:
                DataObject.registered_default_types[boadata_type.real_type] = boadata_type
            boadata_type._registered = True
            return boadata_type
        return wrap

class _DataObjectConversions():
    @classmethod
    def accepts_uri(cls, uri):
        """

        :type uri: str
        """
        return False

    @classmethod
    def from_uri(cls, uri, **kwargs):
        """"Create an object of this class from an URI.

        :param uri: URI in the odo sense
        :type uri: str

        This method can be (but needn't be) overridden in daughter classes:
        By default, it uses odo to import the data.

        When called as DataObject.from_uri, it first tries to find an appropriate class
        by checking all registered types.
        """
        if cls == DataObject:
            for type_ in DataObject.registered_types.values():
                if type_.accepts_uri(uri):
                    return type_.from_uri(uri, **kwargs)
            raise BaseException("Cannot interpret " + uri + ".")
        else:
            inner_data = odo.odo(uri, cls.real_type, **kwargs)
            return cls(inner_data=inner_data, uri=uri, **kwargs)

    @classmethod
    def from_native(cls, native_object, **kwargs):
        """

        :param native_object:
        :param kwargs:
        :return:

        Is idempotent
        """
        if cls == DataObject:
            if isinstance(native_object, DataObject):
                return native_object
            boadata_type = DataObject.registered_default_types.get(type(native_object))
            if not boadata_type:
                raise RuntimeError("Native object of the type {0} not understood.".format(type(native_object).__name__))
            return boadata_type.from_native(native_object, **kwargs)
        else:
            if isinstance(native_object, DataObject):
                return native_object.convert(cls.type_name, **kwargs)
            return cls(inner_data=native_object, **kwargs)

    def is_convertible_to(self, new_type_name):
        """

        :type new_type_name: str | type
        :rtype: bool
        """
        if isinstance(new_type_name, type):
            new_type, new_type_name = new_type_name, new_type_name.type_name
        else:
            if not new_type_name in DataObject.registered_types:
                return False
            new_type = DataObject.registered_types[new_type_name]
        if isinstance(self, new_type):
            return True
        if not (self.type_name, new_type_name) in DataConversion.registered_conversions:
            return False
        conversion = DataConversion.registered_conversions[(self.type_name, new_type_name)]
        return conversion.applies(self)

    @classmethod
    def is_convertible_from(cls, data_object):
        return data_object.is_convertible_to(cls)

    @property
    def allowed_conversions(self):
        return [ key for (key, conversion) in DataConversion.registered_conversions.items() if key[0] == self.type_name and conversion.applies(self, key[1])]

    def convert(self, new_type_name, **kwargs):
        """Convert to another boadata-supported type.

        :type new_type_name: str
        :rtype DataObject

        Auto-conversion returns the same object.
        Default implementation is based on odo.
        """
        # TODO: check argument?

        new_type = DataObject.registered_types[new_type_name]
        if isinstance(self, new_type):
            return self
        conversion = DataConversion.registered_conversions.get((self.__class__.type_name, new_type_name))
        if not conversion:
            raise ConversionUnknown("Unknown conversion from {0} to {1}".format(self.__class__.type_name, new_type_name))
        return conversion.convert(self, new_type, **kwargs)

class _DataObjectInterface():
    """

    Possible methods:
    - add_column(key, expression, **kwargs) - based on evaluate
    -
    """
    @property
    def shape(self):
        """Shape of the data.

        :rtype: tuple(int)

        Example: Shape of the 4x3 matrix is (4, 3)
        """
        if hasattr(self.inner_data, "shape"):
            return tuple(self.inner_data.shape)
        return ()

    @property
    def ndim(self):
        """Dimensionality of the data.

        :rtype: int

        Example: A 4x3 matrix has dimensionality 2.
        """
        if hasattr(self.inner_data, "ndim"):
            return int(self.inner_data.ndim)
        else:
            return len(self.shape)

    @property
    def size(self):
        if hasattr(self.inner_data, "size"):
            return int(self.inner_data.size)
        else:
            from operator import mul
            from functools import reduce
            reduce(mul, self.shape, 1)

    @property
    def dtype(self):
        if hasattr(self.inner_data, "dtype"):
            return self.inner_data.dtype
        else:
            return None

    @property
    def columns(self):
        """Column names (in multidimensional mappings, the value variables)

        :rtype: list[str] | None

        Default variant understands pandas DataFrames
        """
        if hasattr(self.inner_data, "columns"):
            return list(self.inner_data.columns.values)
        else:
            return None

    @property
    def name(self):
        if hasattr(self.inner_data, "name"):
            return self.inner_data.name
        else:
            return None

class DataObject(_DataObjectRegistry, _DataObjectConversions, _DataObjectInterface):
    '''A basic object that contains data representable by boadata.

    :type registered_types: OrderedDict[str, type]
    :type real_type: type | None
    :type type_name: str

    It is necessary to keep all arguments keyword (enforceable in Python 3).
    '''
    def __init__(self, inner_data=None, uri=None, source=None, **kwargs):
        if self.real_type and not isinstance(inner_data, self.real_type):
            raise RuntimeError("Invalid type of inner data: `{0}` instead of expected `{1}`".format(
                inner_data.__class__.__name__, self.real_type.__name__
            ))
        self.inner_data = inner_data
        self.uri = uri
        self.source = source

    changed = blinker.Signal("changed")    # For dynamic data objects

    real_type = None

    type_name = None

    @property
    def title(self):
        return repr(self)

    def __repr__(self):
        return "{0}(\"{1}\")".format(self.__class__.__name__, self.uri)

    @staticmethod
    def proxy_methods(methods, wrap=True, unwrap_args=True, same_class=True, through=None):
        """Decorator to apply on DataObject descendants.

        :param wrap: Whether to wrap result
        :param unwrap_args: Whether to unwrap arguments
        :param same_class: Whether to try to convert to self's class
        :param through: if None, done via inner_data, otherwise through a named type

        It is not possible to proxy slots, but it is possible to inherit proxied slots :-)
        """
        import boadata
        def wrapper(boadata_type):
            if isinstance(methods, str):
                method_names = [methods]
            else:
                method_names = methods

            def make_method(method_name):
                def proxied_method(self, *args, **kwargs):
                    if unwrap_args:
                        args = [boadata.unwrap(arg) for arg in args]
                        kwargs = {key: boadata.unwrap(value) for key, value in kwargs.items()}

                    if through:
                        native_method = getattr(self.convert(through), method_name)
                    else:
                        native_method = getattr(self.inner_data, method_name)
                    result = native_method(*args, **kwargs)
                    if not wrap:
                        return result
                    elif same_class and isinstance(result, self.real_type):
                        return self.__class__.from_native(result)
                    else:
                        try:
                            return DataObject.from_native(result)
                        except:
                            return result
                return proxied_method
            for method_name in method_names:
                setattr(boadata_type, method_name, make_method(method_name))
            return boadata_type
        return wrapper

    def evaluate(self, expression, wrap=True):
        """Do calculation on columns of the dataset.

        :param expression: a valid expression
        :type expression: string

        Based on numexpr library
        """
        import numexpr as ne
        import numpy as np
        local_dict = {
            col : self[col].inner_data for col in self.columns if isinstance(col, str)
        }
        global_dict = {
            "nan" : np.nan,
            "inf" : np.inf
        }
        result = ne.evaluate(expression, local_dict=local_dict, global_dict=global_dict)
        if wrap:
            return DataObject.from_native(result, source=self)
        else:
            return result

class OdoDataObject(DataObject):
    def __init__(self, uri, **kwargs):
        inner_data = odo.resource(uri)
        super(OdoDataObject, self).__init__(inner_data=inner_data, uri=uri, **kwargs)

    @classmethod
    def from_uri(cls, uri, **kwargs):
        return cls(uri=uri, **kwargs)<|endoftext|>


<commit_before>import argparse

from tornado.ioloop import IOLoop

from fadisco.app import App
from fadisco.database import Database
from fadisco.model import Model

def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('database')
    arg_parser.add_argument('--prefix', default='')
    arg_parser.add_argument('--port', default=8058, type=int)

    args = arg_parser.parse_args()

    database = Database(args.database)
    model = Model(database)

    app = App(model, prefix=args.prefix)
    app.listen(args.port, address='localhost')
    IOLoop.current().start()

if __name__ == '__main__':
    main()
<commit_msg>server: Add xheaders opt<commit_after>import argparse

from tornado.ioloop import IOLoop

from fadisco.app import App
from fadisco.database import Database
from fadisco.model import Model

def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('database')
    arg_parser.add_argument('--prefix', default='')
    arg_parser.add_argument('--port', default=8058, type=int)
    arg_parser.add_argument('--xheaders', action='store_true')

    args = arg_parser.parse_args()

    database = Database(args.database)
    model = Model(database)

    app = App(model, prefix=args.prefix)
    app.listen(args.port, address='localhost', xheaders=args.xheaders)
    IOLoop.current().start()

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before>import unittest

import numpy as np

from ifcb.tests.data.fileset_info import get_fileset_bin

from ifcb.viz.utils import square_letterboxed, SQUARE_LETTERBOXED_DEFAULT_SIZE

SL_BIN_LID = 'IFCB5_2012_028_081515'

SL_MEDIAN = np.array([[205, 205, 205, 205, 205],
       [207, 204, 207, 205, 204],
       [206, 206, 211, 204, 205],
       [205, 205, 205, 205, 205],
       [205, 205, 205, 205, 205]])

SL_MEAN = np.array([[202, 202, 202, 202, 202],
       [207, 204, 207, 205, 204],
       [206, 206, 211, 204, 205],
       [202, 202, 202, 202, 202],
       [202, 202, 202, 202, 202]])

SL_27 = np.array([[ 27,  27,  27,  27,  27],
       [207, 204, 207, 205, 204],
       [206, 206, 211, 204, 205],
       [ 27,  27,  27,  27,  27],
       [ 27,  27,  27,  27,  27]])

class TestSquareLetterboxed(unittest.TestCase):
    def setUp(self):
        b = get_fileset_bin(SL_BIN_LID)
        self.img = b.images[1]
    def test_fill_value_median(self):
        sl = square_letterboxed(self.img, size=5)
        assert np.allclose(sl, SL_MEDIAN)
        sl = square_letterboxed(self.img, size=5, fill_value='median')
        assert np.allclose(sl, SL_MEDIAN)
    def test_fill_value_mean(self):
        sl = square_letterboxed(self.img, size=5, fill_value='mean')
        assert np.allclose(sl, SL_MEAN)
    def test_fill_value_27(self):
        sl = square_letterboxed(self.img, size=5, fill_value=27)
        assert np.allclose(sl, SL_27)
    def test_size(self):
        sl = square_letterboxed(self.img, size=20)
        assert sl.shape == (20, 20)
    def test_default_size(self):
        sl = square_letterboxed(self.img)
        assert sl.shape[0] == SQUARE_LETTERBOXED_DEFAULT_SIZE
        assert sl.shape[1] == SQUARE_LETTERBOXED_DEFAULT_SIZE<commit_msg>test for new square util<commit_after>import unittest

import numpy as np

from ifcb.tests.data.fileset_info import get_fileset_bin

from ifcb.viz.utils import square_letterboxed, square, SQUARE_DEFAULT_SIZE

SL_BIN_LID = 'IFCB5_2012_028_081515'

SL_MEDIAN = np.array([[205, 205, 205, 205, 205],
       [207, 204, 207, 205, 204],
       [206, 206, 211, 204, 205],
       [205, 205, 205, 205, 205],
       [205, 205, 205, 205, 205]])

SL_MEAN = np.array([[202, 202, 202, 202, 202],
       [207, 204, 207, 205, 204],
       [206, 206, 211, 204, 205],
       [202, 202, 202, 202, 202],
       [202, 202, 202, 202, 202]])

SL_27 = np.array([[ 27,  27,  27,  27,  27],
       [207, 204, 207, 205, 204],
       [206, 206, 211, 204, 205],
       [ 27,  27,  27,  27,  27],
       [ 27,  27,  27,  27,  27]])

SQ = np.array([[206, 205, 204, 206, 204],
       [205, 204, 208, 205, 203],
       [204, 203, 215, 204, 204],
       [206, 204, 159, 207, 205],
       [206, 204, 205, 206, 205]])

class TestSquare(unittest.TestCase):
    def setUp(self):
        b = get_fileset_bin(SL_BIN_LID)
        self.img = b.images[1]
    def test_square(self):
        sq = square(self.img, size=5)
        assert np.allclose(sq, SQ)
    def test_size(self):
        sq = square(self.img, 20)
        assert sq.shape == (20, 20)
    def test_default_size(self):
        sq = square(self.img)
        assert sq.shape[0] == SQUARE_DEFAULT_SIZE
        assert sq.shape[1] == SQUARE_DEFAULT_SIZE

class TestSquareLetterboxed(unittest.TestCase):
    def setUp(self):
        b = get_fileset_bin(SL_BIN_LID)
        self.img = b.images[1]
    def test_fill_value_median(self):
        sl = square_letterboxed(self.img, size=5)
        assert np.allclose(sl, SL_MEDIAN)
        sl = square_letterboxed(self.img, size=5, fill_value='median')
        assert np.allclose(sl, SL_MEDIAN)
    def test_fill_value_mean(self):
        sl = square_letterboxed(self.img, size=5, fill_value='mean')
        assert np.allclose(sl, SL_MEAN)
    def test_fill_value_27(self):
        sl = square_letterboxed(self.img, size=5, fill_value=27)
        assert np.allclose(sl, SL_27)
    def test_size(self):
        sl = square_letterboxed(self.img, size=20)
        assert sl.shape == (20, 20)
    def test_default_size(self):
        sl = square_letterboxed(self.img)
        assert sl.shape[0] == SQUARE_DEFAULT_SIZE
        assert sl.shape[1] == SQUARE_DEFAULT_SIZE<|endoftext|>


<commit_before>#!/usr/bin/env python
'''Push changes in subversion repository to IRC channel'''

from twisted.words.protocols import irc
from twisted.internet.protocol import ReconnectingClientFactory
import re
from subprocess import Popen, PIPE
from xml.etree.cElementTree import parse as xmlparse
from cStringIO import StringIO

class IRCClient(irc.IRCClient):
    nickname = "svnbot"
    realname = "Subversion Bot"
    channel = "#dev"

    instance = None # Running instance

    def signedOn(self):
        IRCClient.instance = self
        self.join(self.channel)

    def svn(self, revision, author, comment):
        comment = (comment[:57] + "...") if  len(comment) > 60 else comment
        message = "SVN revision %s by %s: %s" % (revision, author, comment)
        self.say(self.channel, message)

class SVNPoller:
    def __init__(self, root, user, password):
        self.pre = ["svn", "--xml", "--username", user, "--password", password]
        self.root = root
        self.last_revision = self.get_last_revision()

    def check(self):
        if not IRCClient.instance:
            return

        try:
            last_revision = self.get_last_revision()
            if (not last_revision) or (last_revision == self.last_revision):
                return

            for rev in range(self.last_revision + 1, last_revision + 1):
                author, comment = self.revision_info(rev)
                IRCClient.instance.svn(rev, author, comment)
            self.last_revision = last_revision
        except Exception, e:
            print "ERROR: %s" % e

    def svn(self, *cmd):
        pipe = Popen(self.pre +  list(cmd) + [self.root], stdout=PIPE)
        try:
            data = pipe.stdout.read()
        except IOError: # FIXME: Find why
            data = ""
        return xmlparse(StringIO(data))

    def get_last_revision(self):
        tree = self.svn("info")
        revision = tree.find("//commit").get("revision")
        return int(revision)

    def revision_info(self, revision):
        tree = self.svn("log", "-r", str(revision))
        author = tree.find("//author").text
        comment = tree.find("//msg").text

        return author, comment

if __name__ == "__main__":
    from twisted.internet import reactor
    from twisted.internet.task import LoopingCall

    factory = ReconnectingClientFactory()
    factory.protocol = IRCClient
    reactor.connectTCP("irc.mycompany.com", 6667, factory)

    poller = SVNPoller("http://svn.mycompany.com", "bugs", "carrot")
    task = LoopingCall(poller.check)
    task.start(1)

    reactor.run()

<commit_msg>Use communicate<commit_after>#!/usr/bin/env python
'''Push changes in subversion repository to IRC channel'''

from twisted.words.protocols import irc
from twisted.internet.protocol import ReconnectingClientFactory
import re
from subprocess import Popen, PIPE
from xml.etree.cElementTree import parse as xmlparse
from cStringIO import StringIO

class IRCClient(irc.IRCClient):
    nickname = "svnbot"
    realname = "Subversion Bot"
    channel = "#dev"

    instance = None # Running instance

    def signedOn(self):
        IRCClient.instance = self
        self.join(self.channel)

    def svn(self, revision, author, comment):
        comment = (comment[:57] + "...") if  len(comment) > 60 else comment
        message = "SVN revision %s by %s: %s" % (revision, author, comment)
        self.say(self.channel, message)

class SVNPoller:
    def __init__(self, root, user, password):
        self.pre = ["svn", "--xml", "--username", user, "--password", password]
        self.root = root
        self.last_revision = self.get_last_revision()

    def check(self):
        if not IRCClient.instance:
            return

        try:
            last_revision = self.get_last_revision()
            if (not last_revision) or (last_revision == self.last_revision):
                return

            for rev in range(self.last_revision + 1, last_revision + 1):
                author, comment = self.revision_info(rev)
                IRCClient.instance.svn(rev, author, comment)
            self.last_revision = last_revision
        except Exception, e:
            print "ERROR: %s" % e

    def svn(self, *cmd):
        pipe = Popen(self.pre +  list(cmd) + [self.root], stdout=PIPE)
        try:
            data = pipe.communicate()[0]
        except IOError:
            data = ""
        return xmlparse(StringIO(data))

    def get_last_revision(self):
        tree = self.svn("info")
        revision = tree.find("//commit").get("revision")
        return int(revision)

    def revision_info(self, revision):
        tree = self.svn("log", "-r", str(revision))
        author = tree.find("//author").text
        comment = tree.find("//msg").text

        return author, comment

if __name__ == "__main__":
    from twisted.internet import reactor
    from twisted.internet.task import LoopingCall

    factory = ReconnectingClientFactory()
    factory.protocol = IRCClient
    reactor.connectTCP("irc.mycompany.com", 6667, factory)

    poller = SVNPoller("http://svn.mycompany.com", "bugs", "carrot")
    task = LoopingCall(poller.check)
    task.start(1)

    reactor.run()

<|endoftext|>


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

import sys
reload(sys)
sys.setdefaultencoding('UTF-8')
sys.path.append('..')

import Image
from cStringIO import StringIO
import urllib2

from administration.config import MIN_IMAGE_SIZE
from administration.config import IMAGES_LOCAL_DIR
from administration.config import IMAGES_PUBLIC_DIR

# TODO: boundary checker should not return None, instead probably an Exception
# TODO: this method should be moved to image_helper
def is_valid_image(image_url):
    """
    find out if the image has a resolution larger than MIN_IMAGE_SIZE
    """
    if not image_url:
        return None
    image_pil = Image.open(StringIO(urllib2.urlopen(image_url).read()))
    return True if image_pil.size[0]*image_pil.size[1] > MIN_IMAGE_SIZE[0]*MIN_IMAGE_SIZE[1] else False

# TODO: boundary checkers
# TODO: relative path could be a url including its suffix like jpg/png
def generate_thumbnail(image_url, relative_path):
    """
    docs needed!
    """
    if not image_url or not relative_path:
        return None
    image_web = StringIO(urllib2.urlopen(image_url).read())
    image_pil = Image.open(image_web)
    # generate thumbnail
    if image_pil.size > MIN_IMAGE_SIZE:
        image_thumbnail_local_path = '%s%si.jpg' % (
            IMAGES_LOCAL_DIR, relative_path)
        image_thumbnail_web_path = '%s%s.jpg' % (
            IMAGES_PUBLIC_DIR, relative_path)
        image_pil.thumbnail(config.MIN_IMAGE_SIZE, Image.ANTIALIAS)
        image_pil = image_pil.convert('RGB')
        image_pil.save(image_thumbnail_local_path, 'JPEG')
        return image_thumbnail_web_path
    else:
        return image_url

def get_image_size(image_url):
    """
    docs needed
    """
    try:
        image_web = StringIO(urllib2.urlopen(image_url).read())
    except Exception as e:
        print e
        image_web = image_url
    im = Image.open(image_web)
    width, height = im.size
    return width, height
<commit_msg>autopep8ed<commit_after>#!/usr/bin/env python
#-*- coding: utf-8 -*-

import sys
reload(sys)
sys.setdefaultencoding('UTF-8')
sys.path.append('..')

import Image
from cStringIO import StringIO
import urllib2

from administration.config import MIN_IMAGE_SIZE
from administration.config import IMAGES_LOCAL_DIR
from administration.config import IMAGES_PUBLIC_DIR

# TODO: boundary checker should not return None, instead probably an Exception
# TODO: this method should be moved to image_helper
def is_valid_image(image_url):
    """
    find out if the image has a resolution larger than MIN_IMAGE_SIZE
    """
    if not image_url:
        return None
    image_pil = Image.open(StringIO(urllib2.urlopen(image_url).read()))
    return True if image_pil.size[0] * image_pil.size[1] > MIN_IMAGE_SIZE[0] * MIN_IMAGE_SIZE[1] else False

# TODO: boundary checkers
# TODO: relative path could be a url including its suffix like jpg/png
def generate_thumbnail(image_url, relative_path):
    """
    docs needed!
    """
    if not image_url or not relative_path:
        return None
    image_web = StringIO(urllib2.urlopen(image_url).read())
    image_pil = Image.open(image_web)
    # generate thumbnail
    if image_pil.size > MIN_IMAGE_SIZE:
        image_thumbnail_local_path = '%s%si.jpg' % (
            IMAGES_LOCAL_DIR, relative_path)
        image_thumbnail_web_path = '%s%s.jpg' % (
            IMAGES_PUBLIC_DIR, relative_path)
        image_pil.thumbnail(config.MIN_IMAGE_SIZE, Image.ANTIALIAS)
        image_pil = image_pil.convert('RGB')
        image_pil.save(image_thumbnail_local_path, 'JPEG')
        return image_thumbnail_web_path
    else:
        return image_url

def get_image_size(image_url):
    """
    docs needed
    """
    try:
        image_web = StringIO(urllib2.urlopen(image_url).read())
    except Exception as e:
        print e
        image_web = image_url
    im = Image.open(image_web)
    width, height = im.size
    return width, height
<|endoftext|>


<commit_before>#pylint: disable=F0401
from helpers import *
import org.bukkit.inventory.ItemStack as ItemStack

#
# Welcome new players
#

@hook.event("player.PlayerJoinEvent", "monitor")
def onJoin(event):
  player = event.getPlayer()
  for item in player.getInventory():
    if (item != None and item.getTypeId() == 175 and item.getDurability() > 5):
      item.setDurability(0)
      log("&cPlayer '%s' had 175:6 or higher in his inventory! Replaced with 175:0" % player.getName())
      msg(player, " &a----------------------------------------------------")
      msg(player, " &4&lWARNING: &cYou had 175:7 (invalid flower) in your inventory.")
      msg(player, " &cThis crashes your client. We have replaced it with 175:0.")
      msg(player, " &a----------------------------------------------------")

  if not server.getOfflinePlayer(player.getName()).hasPlayedBefore():
    broadcast("utils.greet_new", "")
    broadcast("utils.greet_new", "&a&lPlease welcome &f" + player.getDisplayName() + " &a&lto Redstoner!")
    broadcast("utils.greet_new", "")

    # clear out some eventual crap before
    msg(player, " \n \n \n \n \n \n \n \n \n \n \n \n ")
    msg(player, "  &4Welcome to the Redstoner Server!")
    msg(player, "  &6please make sure to read the info here:")
    msg(player, "  &6/The FAQ at /spawn")
    msg(player, "  &6/rules")
    msg(player, "  &6/ranks")
    msg(player, "  &6thank you and happy playing ;)")
    msg(player, " \n ")

  loginloc = player.getLocation().getBlock().getType()
  headloc = player.getEyeLocation().getBlock().getType()
  if str(loginloc) == "PORTAL" or str(headloc) == "PORTAL":
    msg(player, "&4Looks like you spawned in a portal... Let me help you out")
    msg(player, "&6You can use /back if you &nreally&6 want to go back")
    player.teleport(player.getWorld().getSpawnLocation())

#
# /sudo - execute command/chat *as* a player/console
#

@hook.command("sudo")
def onSudoCommand(sender, args):
  if sender.hasPermission("utils.sudo"):
    plugHeader(sender, "Sudo")
    if not checkargs(sender, args, 2, -1):
      return True
    target = args[0]

    cmd =  " ".join(args[1:])
    msg(sender, "Running '&e%s&r' as &3%s" % (cmd, target))
    if cmd[0] == "/":
      cmd = cmd[1:]
      if target.lower() == "server" or target.lower() == "console":
        runas(server.getConsoleSender(), cmd)
      elif server.getPlayer(target):
        runas(server.getPlayer(target), cmd)
      else:
        msg(sender, "&cPlayer %s not found!" % target)
    else:
      if target.lower() == "server" or target.lower() == "console":
        runas(server.getConsoleSender(), "say %s" % cmd)
      elif server.getPlayer(target):
        server.getPlayer(target).chat(cmd)
      else:
        msg(sender, "&cPlayer %s not found!" % target)
  else:
    noperm(sender)
  return True

#
# Clicking redstone_sheep with shears will drop redstone + wool and makes a moo sound
#

@hook.event("player.PlayerInteractEntityEvent")
def onPlayerInteractEntity(event):
  if not event.isCancelled():
    sender = event.getPlayer()
    entity = event.getRightClicked()
    if isPlayer(entity) and str(entity.getUniqueId()) == "ae795aa8-6327-408e-92ab-25c8a59f3ba1" and str(sender.getItemInHand().getType()) == "SHEARS" and str(sender.getGameMode() == "CREATIVE"):
      for i in range(5):
        entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("REDSTONE")))
        entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("WOOL")))
      sender.playSound(entity.getLocation(), "mob.cow.say", 1, 1)

#
# Various text commands
#

@hook.command("rules")
def onRulesCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  arrow = u"\u2192"
  plugHeader(sender, "Redstoner rules")
  msg(sender, "&31 &7 " + arrow + " &6Make use of common sense and respect.")
  msg(sender, "&32 &7 " + arrow + " &6Do NOT ask for promotion.")
  msg(sender, "&33 &7 " + arrow + " &6Do NOT use cheats in Survival worlds.")
  msg(sender, "&34 &7 " + arrow + " &6Do NOT spam entities or leave clocks running.")
  msg(sender, "&35 &7 " + arrow + " &6Swearing is okay, offending is NOT.")
  msg(sender, "&36 &7 " + arrow + " &6Do NOT build huge walls around your plot.")
  msg(sender, "&37 &7 " + arrow + " &6Listen to the admins and mods, even if it is not in the rules.")
  msg(sender, "&38 &7 " + arrow + " &6Only english in public chat.")
  msg(sender, "&39 &7 " + arrow + " &6Everyone can get punished, even admins.")
  msg(sender, "&310 &7" + arrow + " &6Same rules for everyone.")
  msg(sender, "&311 &7" + arrow + " &6NO OP items.")
  msg(sender, "&312 &7" + arrow + " &6Do NOT trap other players.")
  return True

@hook.command("history")
def onHistoryCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  plugHeader(sender, "Redstoner history")
  msg(sender, "")
  msg(sender, " &2First, oliverissocool1 owned redstoner.com plus the server which usually had 10-15 players on.\n")
  msg(sender, " &2Oliver became lazy and thus moved ownership to oleerik, who was another admin there.\n")
  msg(sender, " &2Dico joined the server and later he became a moderator.\n")
  msg(sender, " &2But then oleerik also became lazy, lost interest and shut down the server.\n")
  msg(sender, " &2Some time later he offered dico to use the server and he was - of course - interested in it.\n")
  msg(sender, " &2The server did not have the old worlds and configuration anymore and it was down for a good while, so it was like a complete new server.\n")
  msg(sender, " &2He invited some friends to help him set up the server before opening it to the public (as his 'fan server').\n")
  msg(sender, " &2Redstone Sheep was one of these friends and made the website, he happened to become the guy who maintains the whole server.\n")
  msg(sender, " &2The server somtimes crashed or lost it's connection and we were not too happy plus oleerik was always paying for it, without using it himself.\n")
  msg(sender, " &2PanFritz first helped out by donating and then offered to host a physical server.\n")
  msg(sender, " &2We discussed a lot and moved everything, it worked very well.\n")
  msg(sender, " &2A month or two later, a new server was bought from donations and it took some time until the new machine was ready, but the move went quick and without much downtime.\n")
  msg(sender, " &2Another couple months later, the server underwent many major changes, this update was known as Redstoner 2.0 and vastly improved almost every aspect of the server.\n")

  msg(sender, " &2That's our story for now.")
  return True

@hook.command("nick")
def onNickCommand(sender, args):
  plugHeader(sender, "Nicknames")
  msg(sender, "&31. &aYou need to be Donor or Trusted. &8&o(See /ranks)")
  msg(sender, "&32. &aHas to begin with &nat least&3&o " + sender.getName()[:3] + "&a.")
  msg(sender, "&33. &aMore characters are required when other players")
  msg(sender, "&a   begin with the same 3 letters.")
  msg(sender, "&34. &aIt must not be longer than your name.")
  msg(sender, "&a   (e.g. No addons like '&3" + sender.getName() + "TheCoolOne&a'.)")
  msg(sender, "&6Ask any staff to get your nickname. Requests are ignored when requirements are not covered. Be patient.")
  return True

@hook.command("ranks")
def onRanksCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  plugHeader(sender, "Rank colours")
  msg(sender, " &7Guest")
  msg(sender, " &fMember")
  msg(sender, " &aBuilder")
  msg(sender, " &3Trusted")
  msg(sender, " &cModerator")
  msg(sender, " &4Admin")
  plugHeader(sender, "Rank info")
  msg(sender, " &oitalic &rnames are nicks. use &a/realname <nick>&r to check")
  msg(sender, " &eDonator&r rank has <name> &e$&r")
  msg(sender, " &eDonator+&r rank has <name> &e&l$&r")
  msg(sender, " To get the &e$&r, see &a/donate&r for more info")
  msg(sender, "")
  return True

@hook.command("donate")
def onDonateCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  msg(sender, "")
  plugHeader(sender, "Donations")
  msg(sender, " &aWant to donate? Awesome!")
  msg(sender, " &6all info is at &nredstoner.com/donate&r")
  msg(sender, "")
  return True

#
# /pluginversions - print all plugins + versions; useful when updating plugins
#

@hook.command("pluginversions")
def onPluginversionsCommand(sender, args):
  plugHeader(sender, "Plugin versions")
  plugins = server.getPluginManager().getPlugins().tolist()
  plugins.sort(key=lambda pl: pl.getName())
  msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:")
  for plugin in plugins:
    msg(sender, "&6" + plugin.getName() + "&r: &e" + plugin.getDescription().getVersion())
  return True

#
# Various command aliases
#

@hook.command("spawn")
def onSpawnCommand(sender, args):
  warp(sender, args, "spawn")
  return True

@hook.command("cr")
def onCrCommand(sender, args):
  warp(sender, args, "cr")
  return True

@hook.command("tr")
def onTrCommand(sender, args):
  warp(sender, args, "tr")
  return True

@hook.command("faq")
def onFaqCommand(sender, args):
  warp(sender, args, "faq")
  return True
<commit_msg>adjust rules<commit_after>#pylint: disable=F0401
from helpers import *
import org.bukkit.inventory.ItemStack as ItemStack

#
# Welcome new players
#

@hook.event("player.PlayerJoinEvent", "monitor")
def onJoin(event):
  player = event.getPlayer()
  for item in player.getInventory():
    if (item != None and item.getTypeId() == 175 and item.getDurability() > 5):
      item.setDurability(0)
      log("&cPlayer '%s' had 175:6 or higher in his inventory! Replaced with 175:0" % player.getName())
      msg(player, " &a----------------------------------------------------")
      msg(player, " &4&lWARNING: &cYou had 175:7 (invalid flower) in your inventory.")
      msg(player, " &cThis crashes your client. We have replaced it with 175:0.")
      msg(player, " &a----------------------------------------------------")

  if not server.getOfflinePlayer(player.getName()).hasPlayedBefore():
    broadcast("utils.greet_new", "")
    broadcast("utils.greet_new", "&a&lPlease welcome &f" + player.getDisplayName() + " &a&lto Redstoner!")
    broadcast("utils.greet_new", "")

    # clear out some eventual crap before
    msg(player, " \n \n \n \n \n \n \n \n \n \n \n \n ")
    msg(player, "  &4Welcome to the Redstoner Server!")
    msg(player, "  &6please make sure to read the info here:")
    msg(player, "  &6/The FAQ at /spawn")
    msg(player, "  &6/rules")
    msg(player, "  &6/ranks")
    msg(player, "  &6thank you and happy playing ;)")
    msg(player, " \n ")

  loginloc = player.getLocation().getBlock().getType()
  headloc = player.getEyeLocation().getBlock().getType()
  if str(loginloc) == "PORTAL" or str(headloc) == "PORTAL":
    msg(player, "&4Looks like you spawned in a portal... Let me help you out")
    msg(player, "&6You can use /back if you &nreally&6 want to go back")
    player.teleport(player.getWorld().getSpawnLocation())

#
# /sudo - execute command/chat *as* a player/console
#

@hook.command("sudo")
def onSudoCommand(sender, args):
  if sender.hasPermission("utils.sudo"):
    plugHeader(sender, "Sudo")
    if not checkargs(sender, args, 2, -1):
      return True
    target = args[0]

    cmd =  " ".join(args[1:])
    msg(sender, "Running '&e%s&r' as &3%s" % (cmd, target))
    if cmd[0] == "/":
      cmd = cmd[1:]
      if target.lower() == "server" or target.lower() == "console":
        runas(server.getConsoleSender(), cmd)
      elif server.getPlayer(target):
        runas(server.getPlayer(target), cmd)
      else:
        msg(sender, "&cPlayer %s not found!" % target)
    else:
      if target.lower() == "server" or target.lower() == "console":
        runas(server.getConsoleSender(), "say %s" % cmd)
      elif server.getPlayer(target):
        server.getPlayer(target).chat(cmd)
      else:
        msg(sender, "&cPlayer %s not found!" % target)
  else:
    noperm(sender)
  return True

#
# Clicking redstone_sheep with shears will drop redstone + wool and makes a moo sound
#

@hook.event("player.PlayerInteractEntityEvent")
def onPlayerInteractEntity(event):
  if not event.isCancelled():
    sender = event.getPlayer()
    entity = event.getRightClicked()
    if isPlayer(entity) and str(entity.getUniqueId()) == "ae795aa8-6327-408e-92ab-25c8a59f3ba1" and str(sender.getItemInHand().getType()) == "SHEARS" and str(sender.getGameMode() == "CREATIVE"):
      for i in range(5):
        entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("REDSTONE")))
        entity.getWorld().dropItemNaturally(entity.getLocation(), ItemStack(bukkit.Material.getMaterial("WOOL")))
      sender.playSound(entity.getLocation(), "mob.cow.say", 1, 1)

#
# Various text commands
#

@hook.command("rules")
def onRulesCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  arrow = u"\u2192"
  plugHeader(sender, "Redstoner rules")
  msg(sender, "&31 &7 " + arrow + " &6Make use of common sense and respect.")
  msg(sender, "&32 &7 " + arrow + " &6Do NOT ask for promotion.")
  msg(sender, "&33 &7 " + arrow + " &6Do NOT cheat in Survival worlds.")
  msg(sender, "&34 &7 " + arrow + " &6Do NOT spam entities or make big redstone clocks. (causes lag)")
  msg(sender, "&35 &7 " + arrow + " &6Swearing is okay, swearing &oat&6 people is NOT.")
  msg(sender, "&36 &7 " + arrow + " &6Do NOT build huge walls around your plot.")
  msg(sender, "&37 &7 " + arrow + " &6Only english in public chat. Use &e/msg&6 or &e/cg&6.")
  return True

@hook.command("history")
def onHistoryCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  plugHeader(sender, "Redstoner history")
  msg(sender, "")
  msg(sender, " &2First, oliverissocool1 owned redstoner.com plus the server which usually had 10-15 players on.\n")
  msg(sender, " &2Oliver became lazy and thus moved ownership to oleerik, who was another admin there.\n")
  msg(sender, " &2Dico joined the server and later he became a moderator.\n")
  msg(sender, " &2But then oleerik also became lazy, lost interest and shut down the server.\n")
  msg(sender, " &2Some time later he offered dico to use the server and he was - of course - interested in it.\n")
  msg(sender, " &2The server did not have the old worlds and configuration anymore and it was down for a good while, so it was like a complete new server.\n")
  msg(sender, " &2He invited some friends to help him set up the server before opening it to the public (as his 'fan server').\n")
  msg(sender, " &2Redstone Sheep was one of these friends and made the website, he happened to become the guy who maintains the whole server.\n")
  msg(sender, " &2The server somtimes crashed or lost it's connection and we were not too happy plus oleerik was always paying for it, without using it himself.\n")
  msg(sender, " &2PanFritz first helped out by donating and then offered to host a physical server.\n")
  msg(sender, " &2We discussed a lot and moved everything, it worked very well.\n")
  msg(sender, " &2A month or two later, a new server was bought from donations and it took some time until the new machine was ready, but the move went quick and without much downtime.\n")
  msg(sender, " &2Another couple months later, the server underwent many major changes, this update was known as Redstoner 2.0 and vastly improved almost every aspect of the server.\n")

  msg(sender, " &2That's our story for now.")
  return True

@hook.command("nick")
def onNickCommand(sender, args):
  plugHeader(sender, "Nicknames")
  msg(sender, "&31. &aYou need to be Donor or Trusted. &8&o(See /ranks)")
  msg(sender, "&32. &aHas to begin with &nat least&3&o " + sender.getName()[:3] + "&a.")
  msg(sender, "&33. &aMore characters are required when other players")
  msg(sender, "&a   begin with the same 3 letters.")
  msg(sender, "&34. &aIt must not be longer than your name.")
  msg(sender, "&a   (e.g. No addons like '&3" + sender.getName() + "TheCoolOne&a'.)")
  msg(sender, "&6Ask any staff to get your nickname. Requests are ignored when requirements are not covered. Be patient.")
  return True

@hook.command("ranks")
def onRanksCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  plugHeader(sender, "Rank colours")
  msg(sender, " &7Guest")
  msg(sender, " &fMember")
  msg(sender, " &aBuilder")
  msg(sender, " &3Trusted")
  msg(sender, " &cModerator")
  msg(sender, " &4Admin")
  plugHeader(sender, "Rank info")
  msg(sender, " &oitalic &rnames are nicks. use &a/realname <nick>&r to check")
  msg(sender, " &eDonator&r rank has <name> &e$&r")
  msg(sender, " &eDonator+&r rank has <name> &e&l$&r")
  msg(sender, " To get the &e$&r, see &a/donate&r for more info")
  msg(sender, "")
  return True

@hook.command("donate")
def onDonateCommand(sender, args):
  if not checkargs(sender, args, 0, 0):
    return True
  msg(sender, "")
  plugHeader(sender, "Donations")
  msg(sender, " &aWant to donate? Awesome!")
  msg(sender, " &6all info is at &nredstoner.com/donate&r")
  msg(sender, "")
  return True

#
# /pluginversions - print all plugins + versions; useful when updating plugins
#

@hook.command("pluginversions")
def onPluginversionsCommand(sender, args):
  plugHeader(sender, "Plugin versions")
  plugins = server.getPluginManager().getPlugins().tolist()
  plugins.sort(key=lambda pl: pl.getName())
  msg(sender, "&3Listing all " + str(len(plugins)) + " plugins and their version:")
  for plugin in plugins:
    msg(sender, "&6" + plugin.getName() + "&r: &e" + plugin.getDescription().getVersion())
  return True

#
# Various command aliases
#

@hook.command("spawn")
def onSpawnCommand(sender, args):
  warp(sender, args, "spawn")
  return True

@hook.command("cr")
def onCrCommand(sender, args):
  warp(sender, args, "cr")
  return True

@hook.command("tr")
def onTrCommand(sender, args):
  warp(sender, args, "tr")
  return True

@hook.command("faq")
def onFaqCommand(sender, args):
  warp(sender, args, "faq")
  return True
<|endoftext|>


<commit_before># Copyright 2018 Google LLC
#
# 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
#
#     https://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.

import sys

import pytest

from . import unit_testing

@pytest.mark.skipif(sys.version_info >= (3, 0), reason="requires Python 2")
def test_dag_import():
    """Test that the DAG file can be successfully imported.

    This tests that the DAG can be parsed, but does not run it in an Airflow
    environment. This is a recommended sanity check by the official Airflow
    docs: https://airflow.incubator.apache.org/tutorial.html#testing
    """
    from . import pythonvirtualenvoperator_python2 as module
    unit_testing.assert_has_valid_dag(module)
<commit_msg>Test pythonvirtualenvoperator sample in Python 3. (#1714)<commit_after># Copyright 2018 Google LLC
#
# 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
#
#     https://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.

import sys

import pytest

from . import unit_testing

def test_dag_import():
    """Test that the DAG file can be successfully imported.

    This tests that the DAG can be parsed, but does not run it in an Airflow
    environment. This is a recommended sanity check by the official Airflow
    docs: https://airflow.incubator.apache.org/tutorial.html#testing
    """
    from . import pythonvirtualenvoperator_python2 as module
    unit_testing.assert_has_valid_dag(module)
<|endoftext|>


<commit_before>from nose.tools import *  # flake8: noqa

from framework.auth.core import Auth, Q
from api.base.settings.defaults import API_BASE
from website.models import Node

from tests.base import ApiTestCase
from tests.factories import (
    ProjectFactory,
    PreprintFactory,
    AuthUserFactory
)

class TestPreprintList(ApiTestCase):

    def setUp(self):
        super(TestPreprintList, self).setUp()
        self.user = AuthUserFactory()

        self.preprint = PreprintFactory(creator=self.user)
        self.url = '/{}preprints/'.format(API_BASE)

        self.project = ProjectFactory(creator=self.user)

    def tearDown(self):
        super(TestPreprintList, self).tearDown()
        Node.remove()

    def test_return_preprints_logged_out(self):
        res = self.app.get(self.url)
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')

    def test_exclude_nodes_from_preprints_endpoint(self):
        res = self.app.get(self.url, auth=self.user.auth)
        ids = [each['id'] for each in res.json['data']]
        assert_in(self.preprint._id, ids)
        assert_not_in(self.project._id, ids)

class TestPreprintFiltering(ApiTestCase):

    def setUp(self):
        super(TestPreprintFiltering, self).setUp()
        self.user = AuthUserFactory()
        self.preprint = PreprintFactory(creator=self.user, provider='wwe')
        self.url = "/{}registrations/".format(API_BASE)

        self.preprint.add_tag('nature boy', Auth(self.user), save=False)
        self.preprint.add_tag('ric flair', Auth(self.user), save=False)
        self.preprint.save()

        self.preprint_two = PreprintFactory(creator=self.user, filename='woo.txt', provider='wcw')
        self.preprint_two.add_tag('nature boy', Auth(self.user), save=False)
        self.preprint_two.add_tag('woo', Auth(self.user), save=False)
        self.preprint_two.save()

        self.preprint_three = PreprintFactory(creator=self.user, filename='stonecold.txt', provider='wwe')
        self.preprint_three.add_tag('stone', Auth(self.user), save=False)
        self.preprint_two.add_tag('cold', Auth(self.user), save=False)
        self.preprint_three.save()

    def tearDown(self):
        super(TestPreprintFiltering, self).tearDown()
        Node.remove()

    def test_filtering_tags(self):
        # both preprint and preprint_two have nature boy
        url = '/{}preprints/?filter[tags]={}'.format(API_BASE, 'nature boy')

        res = self.app.get(url, auth=self.user.auth)
        reg_json = res.json['data']

        ids = [each['id'] for each in reg_json]
        assert_in(self.preprint._id, ids)
        assert_in(self.preprint_two._id, ids)
        assert_not_in(self.preprint_three._id, ids)

        # filtering two tags
        # preprint has both tags; preprint_two only has one
        url = '/{}preprints/?filter[tags]={}&filter[tags]={}'.format(API_BASE, 'nature boy', 'ric flair')

        res = self.app.get(url, auth=self.user.auth)
        reg_json = res.json['data']

        ids = [each['id'] for each in reg_json]
        assert_in(self.preprint._id, ids)
        assert_not_in(self.preprint_two._id, ids)
        assert_not_in(self.preprint_three._id, ids)

    def test_filter_by_provider(self):
        url = '/{}preprints/?filter[provider]={}'.format(API_BASE, 'wwe')
        res = self.app.get(url, auth=self.user.auth)
        data = res.json['data']

        assert_equal(len(data), 2)
        for result in data:
            assert 'wwe' in result['attributes']['provider']
<commit_msg>Add test filter by doi<commit_after>from nose.tools import *  # flake8: noqa

from framework.auth.core import Auth, Q
from api.base.settings.defaults import API_BASE
from website.models import Node

from tests.base import ApiTestCase
from tests.factories import (
    ProjectFactory,
    PreprintFactory,
    AuthUserFactory
)

class TestPreprintList(ApiTestCase):

    def setUp(self):
        super(TestPreprintList, self).setUp()
        self.user = AuthUserFactory()

        self.preprint = PreprintFactory(creator=self.user)
        self.url = '/{}preprints/'.format(API_BASE)

        self.project = ProjectFactory(creator=self.user)

    def tearDown(self):
        super(TestPreprintList, self).tearDown()
        Node.remove()

    def test_return_preprints_logged_out(self):
        res = self.app.get(self.url)
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')

    def test_exclude_nodes_from_preprints_endpoint(self):
        res = self.app.get(self.url, auth=self.user.auth)
        ids = [each['id'] for each in res.json['data']]
        assert_in(self.preprint._id, ids)
        assert_not_in(self.project._id, ids)

class TestPreprintFiltering(ApiTestCase):

    def setUp(self):
        super(TestPreprintFiltering, self).setUp()
        self.user = AuthUserFactory()
        self.preprint = PreprintFactory(creator=self.user, provider='wwe')
        self.url = "/{}registrations/".format(API_BASE)

        self.preprint.add_tag('nature boy', Auth(self.user), save=False)
        self.preprint.add_tag('ric flair', Auth(self.user), save=False)
        self.preprint.save()

        self.preprint_two = PreprintFactory(creator=self.user, filename='woo.txt', provider='wcw')
        self.preprint_two.add_tag('nature boy', Auth(self.user), save=False)
        self.preprint_two.add_tag('woo', Auth(self.user), save=False)
        self.preprint_two.save()

        self.preprint_three = PreprintFactory(creator=self.user, filename='stonecold.txt', provider='wwe')
        self.preprint_three.add_tag('stone', Auth(self.user), save=False)
        self.preprint_two.add_tag('cold', Auth(self.user), save=False)
        self.preprint_three.save()

    def tearDown(self):
        super(TestPreprintFiltering, self).tearDown()
        Node.remove()

    def test_filtering_tags(self):
        # both preprint and preprint_two have nature boy
        url = '/{}preprints/?filter[tags]={}'.format(API_BASE, 'nature boy')

        res = self.app.get(url, auth=self.user.auth)
        reg_json = res.json['data']

        ids = [each['id'] for each in reg_json]
        assert_in(self.preprint._id, ids)
        assert_in(self.preprint_two._id, ids)
        assert_not_in(self.preprint_three._id, ids)

        # filtering two tags
        # preprint has both tags; preprint_two only has one
        url = '/{}preprints/?filter[tags]={}&filter[tags]={}'.format(API_BASE, 'nature boy', 'ric flair')

        res = self.app.get(url, auth=self.user.auth)
        reg_json = res.json['data']

        ids = [each['id'] for each in reg_json]
        assert_in(self.preprint._id, ids)
        assert_not_in(self.preprint_two._id, ids)
        assert_not_in(self.preprint_three._id, ids)

    def test_filter_by_provider(self):
        url = '/{}preprints/?filter[provider]={}'.format(API_BASE, 'wwe')
        res = self.app.get(url, auth=self.user.auth)
        data = res.json['data']

        for result in data:
            assert_in('wwe', result['attributes']['provider'])
            assert_not_in('wcw', result['attributes']['provider'])

    def test_filter_by_doi(self):
        url = '/{}preprints/?filter[doi]={}'.format(API_BASE, self.preprint.preprint_doi)

        res = self.app.get(url, auth=self.user.auth)
        data = res.json['data']

        assert_equal(len(data), 1)
        for result in data:
            assert_equal(self.preprint._id, result['id'])
<|endoftext|>


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

from __future__ import unicode_literals

from staticgen.staticgen_pool import staticgen_pool
from staticgen.staticgen_views import StaticgenView

from .models import Post

class BlogPostListView(StaticgenView):
    is_paginated = True
    i18n = True

    def items(self):
        return ('blog:posts_list', )

class BlogPostDetailView(StaticgenView):
    i18n = True

    def items(self):
        return Post.objects.all()

staticgen_pool.register(BlogPostListView)
staticgen_pool.register(BlogPostDetailView)

<commit_msg>Blog pages will be auto discovered by the staticgen crawler.<commit_after><|endoftext|>


<commit_before>import cis_profile
import requests
import logging
import os
import time
from cis_profile.common import WellKnown
from cis_publisher import secret
from cis_publisher import common

logger = logging.getLogger(__name__)

class PublisherError(Exception):
    pass

class Publish:
    def __init__(self, profiles, login_method, publisher_name, discovery_url=None):
        """
        @profiles list of cis_profiles.User
        @login_method str a valid login_method for the user (such as "ad")
        @publisher_name str of your publisher name (such as 'ldap' or 'mozilliansorg')
        @user_ids list of str such as user_ids=['ad|bob|test', 'oauth2|alice|test', ..] which will be sent to CIS. When
        @discovery_url a discovery URL for CIS (CIS_DISCOVERY_URL env var will be used otherwise)
        """
        self.profiles = profiles
        self.login_method = login_method
        self.publisher_name = publisher_name
        if discovery_url is None:
            discovery_url = os.environ.get("CIS_DISCOVERY_URL", "https://auth.mozilla.com/.well-known/mozilla-iam")
        self.__discovery_url = discovery_url

        # Defaults
        self.api_url = None
        self.api_url_person = None
        self.api_url_change = None
        self.max_retries = 5
        # retry_delay is passed to time.sleep
        self.retry_delay = 5
        self.cis_user_list = None
        self.access_token = None
        self.__inited = False

    def __deferred_init(self):
        """
        Init all data that requires external resources
        """
        if self.__inited:
            return
        logger.info("Getting API URLs from well-known {}".format(self.__discovery_url))
        self.__well_known = WellKnown(self.__discovery_url)
        wk = self.__well_known.get_well_known()
        self.api_url = wk["api"]["endpoints"]
        self.api_audience = wk["api"]["audience"]
        self.api_url_person = self.api_url["person"]
        self.api_url_change = self.api_url["change"]
        self.publisher_rules = self.__well_known.get_publisher_rules()
        self.secret_manager = secret.Manager()
        self.config = common.get_config()
        self.__inited = True

    def post_all(self, user_ids=None):
        """
        Post all profiles
        @user_ids list of str which are user ids like 'ad|test'
        """

        self.__deferred_init()

        if user_ids is not None:
            logger.info("Requesting a specific list of user_id's to post {}".format(user_ids))
            if not isinstance(user_ids, list):
                raise PublisherError("user_ids must be a list", user_ids)

            for n in range(0, len(self.profiles)):
                profile = self.profiles[n]
                if profile.user_id.value not in user_ids:
                    del self.profiles[n]
            logger.info("After filtering, we have {} user profiles to post".format(len(self.profiles)))

        self.validate()

        access_token = self._get_authzero_token()

        for profile in self.profiles:
            response_ok = False
            retries = 0
            while not response_ok:
                logger.info(
                    "Attempting to post profile {} to API {}".format(profile.user_id.value, self.api_url_change)
                )
                response = self._request_post(
                    self.api_url_change,
                    data=profile.as_json(),
                    headers={"authorization": "Bearer {}".format(access_token)},
                )
                response_ok = response.ok
                if not response_ok:
                    logger.warning(
                        "Posting profile {} to API failed, retry is {} retry_delay is {}".format(
                            profile.user_id.value, retries, self.retry_delay
                        )
                    )
                    retries = retries + 1
                    time.sleep(self.retry_delay)
                    if retries >= self.max_retries:
                        logger.error(
                            "Maximum retries reached ({}), profile is not be sent {}".format(
                                retries, profile.user_id.value
                            )
                        )
                        raise PublisherError("Failed to publish profile")

    def _request_post(self, url, payload, headers):
        return requests.post(url, payload, headers)

    def _request_get(self, url, qs, headers):
        return requests.get("{}{}".format(url, qs), headers)

    def _get_authzero_client(self):
        authzero = secret.AuthZero(
            client_id=self.secret_manager.secret("client_id"),
            client_secret=self.secret_manager.secret("client_secret"),
            api_identifier=self.api_audience,
            authzero_tenant=self.config("authzero_tenant", namespace="cis", default="auth.mozilla.auth0.com"),
        )
        return authzero

    def _get_authzero_token(self):
        # This could check for expiration
        if self.access_token is not None:
            return self.access_token
        else:
            authzero = self._get_authzero_client()
            self.access_token = authzero.exchange_for_access_token()
            return self.access_token

    def get_known_cis_users(self):
        """
        Call CIS Person API and return a list of existing users
        """
        self.__deferred_init()

        logger.info("Requesting CIS Person API for a list of existing users for method {}".format(self.login_method))
        qs = "/v2/users/id/all?connectionMethod={}".format(self.login_method)
        access_token = self._get_authzero_token()
        response = self._request_get(
            self.api_url_person, qs, headers={"authorization": "Bearer {}".format(access_token)}
        )
        if not response.ok:
            logger.error(
                "Failed to query CIS Person API: {}{} response: {}".format(self.api_url_person, qs, response.text)
            )
            raise PublisherError("Failed to query CIS Person API", response.text)
        return response.json()

    def filter_known_cis_users(self):
        """
        Filters out fields that are not allowed to be updated by this publisher from the profile before posting
        This is for "new" users
        """
        self.__deferred_init()

        if self.profiles is None:
            raise PublisherError("No profiles to operate on")

        cis_users = self.get_known_cis_users()

        allowed_updates = self.publisher_rules["update"]
        for n in range(0, len(self.profiles)):
            p = self.profiles[n]
            if p.user_id.value in cis_users:
                logger.info(
                    "Filtering out non-updateable values from user {} because it already exist in CIS".format(
                        p.user_id.value
                    )
                )
                for pfield in p.__dict__:
                    if pfield not in allowed_updates:
                        continue

                    # sub-item?
                    if isinstance(allowed_updates[pfield], dict):
                        for subpfield in allowed_updates[pfield]:
                            if allowed_updates[pfield][subpfield] != self.publisher_name:
                                if "value" in p.__dict__[pfield][subpfield].keys():
                                    p.__dict__[pfield][subpfield]["value"] = None
                                elif "values" in p.__dict__[pfield][subpfield].keys():
                                    p.__dict__[pfield][subpfield]["values"] = None
                    else:
                        if allowed_updates[pfield] != self.publisher_name:
                            if "value" in p.__dict__[pfield].keys():
                                p.__dict__[pfield]["value"] = None
                            elif "values" in p.__dict__[pfield].keys():
                                p.__dict__[pfield]["values"] = None
                logger.info("Filtered fields for user {}".format(p.user_id.value))
                self.profiles[n] = p

    def validate(self):
        """
        Validates all profiles
        """
        logger.info("Validating {} profiles".format(len(self.profiles)))
        null_user = cis_profile.User()

        for profile in self.profiles:
            if profile.login_method.value != self.login_method:
                logger.error(
                    "Incorrect login method for this user {} - looking for {} but got {}".format(
                        profile.user_id.value, self.login_method, profile.login_method.value
                    )
                )
            profile.validate()
            profile.verify_all_signatures()
            # This should normally work since it's always like a create (even for update)
            profile.verify_all_publishers(null_user)
        logger.info("Validation completed for all profiles")
<commit_msg>hack to convert login methods<commit_after>import cis_profile
import requests
import logging
import os
import time
from cis_profile.common import WellKnown
from cis_publisher import secret
from cis_publisher import common

logger = logging.getLogger(__name__)

class PublisherError(Exception):
    pass

class Publish:
    def __init__(self, profiles, login_method, publisher_name, discovery_url=None):
        """
        @profiles list of cis_profiles.User
        @login_method str a valid login_method for the user (such as "ad")
        @publisher_name str of your publisher name (such as 'ldap' or 'mozilliansorg')
        @user_ids list of str such as user_ids=['ad|bob|test', 'oauth2|alice|test', ..] which will be sent to CIS. When
        @discovery_url a discovery URL for CIS (CIS_DISCOVERY_URL env var will be used otherwise)
        """
        self.profiles = profiles
        self.login_method = login_method
        self.publisher_name = publisher_name
        if discovery_url is None:
            discovery_url = os.environ.get("CIS_DISCOVERY_URL", "https://auth.mozilla.com/.well-known/mozilla-iam")
        self.__discovery_url = discovery_url

        # Defaults
        self.api_url = None
        self.api_url_person = None
        self.api_url_change = None
        self.max_retries = 5
        # retry_delay is passed to time.sleep
        self.retry_delay = 5
        self.cis_user_list = None
        self.access_token = None
        self.__inited = False

    def __deferred_init(self):
        """
        Init all data that requires external resources
        """
        if self.__inited:
            return
        logger.info("Getting API URLs from well-known {}".format(self.__discovery_url))
        self.__well_known = WellKnown(self.__discovery_url)
        wk = self.__well_known.get_well_known()
        self.api_url = wk["api"]["endpoints"]
        self.api_audience = wk["api"]["audience"]
        self.api_url_person = self.api_url["person"]
        self.api_url_change = self.api_url["change"]
        self.publisher_rules = self.__well_known.get_publisher_rules()
        self.secret_manager = secret.Manager()
        self.config = common.get_config()
        self.__inited = True

    def post_all(self, user_ids=None):
        """
        Post all profiles
        @user_ids list of str which are user ids like 'ad|test'
        """

        self.__deferred_init()

        if user_ids is not None:
            logger.info("Requesting a specific list of user_id's to post {}".format(user_ids))
            if not isinstance(user_ids, list):
                raise PublisherError("user_ids must be a list", user_ids)

            for n in range(0, len(self.profiles)):
                profile = self.profiles[n]
                if profile.user_id.value not in user_ids:
                    del self.profiles[n]
            logger.info("After filtering, we have {} user profiles to post".format(len(self.profiles)))

        self.validate()

        access_token = self._get_authzero_token()

        for profile in self.profiles:
            response_ok = False
            retries = 0
            while not response_ok:
                logger.info(
                    "Attempting to post profile {} to API {}".format(profile.user_id.value, self.api_url_change)
                )
                response = self._request_post(
                    self.api_url_change,
                    data=profile.as_json(),
                    headers={"authorization": "Bearer {}".format(access_token)},
                )
                response_ok = response.ok
                if not response_ok:
                    logger.warning(
                        "Posting profile {} to API failed, retry is {} retry_delay is {}".format(
                            profile.user_id.value, retries, self.retry_delay
                        )
                    )
                    retries = retries + 1
                    time.sleep(self.retry_delay)
                    if retries >= self.max_retries:
                        logger.error(
                            "Maximum retries reached ({}), profile is not be sent {}".format(
                                retries, profile.user_id.value
                            )
                        )
                        raise PublisherError("Failed to publish profile")

    def _request_post(self, url, payload, headers):
        return requests.post(url, payload, headers)

    def _request_get(self, url, qs, headers):
        return requests.get("{}{}".format(url, qs), headers)

    def _get_authzero_client(self):
        authzero = secret.AuthZero(
            client_id=self.secret_manager.secret("client_id"),
            client_secret=self.secret_manager.secret("client_secret"),
            api_identifier=self.api_audience,
            authzero_tenant=self.config("authzero_tenant", namespace="cis", default="auth.mozilla.auth0.com"),
        )
        return authzero

    def _get_authzero_token(self):
        # This could check for expiration
        if self.access_token is not None:
            return self.access_token
        else:
            authzero = self._get_authzero_client()
            self.access_token = authzero.exchange_for_access_token()
            return self.access_token

    def get_known_cis_users(self):
        """
        Call CIS Person API and return a list of existing users
        """
        self.__deferred_init()

        logger.info("Requesting CIS Person API for a list of existing users for method {}".format(self.login_method))
        qs = "/v2/users/id/all?connectionMethod={}".format(self.login_method)
        access_token = self._get_authzero_token()
        response = self._request_get(
            self.api_url_person, qs, headers={"authorization": "Bearer {}".format(access_token)}
        )
        if not response.ok:
            logger.error(
                "Failed to query CIS Person API: {}{} response: {}".format(self.api_url_person, qs, response.text)
            )
            raise PublisherError("Failed to query CIS Person API", response.text)
        return response.json()

    def filter_known_cis_users(self):
        """
        Filters out fields that are not allowed to be updated by this publisher from the profile before posting
        This is for "new" users
        """
        self.__deferred_init()

        if self.profiles is None:
            raise PublisherError("No profiles to operate on")

        cis_users = self.get_known_cis_users()

        allowed_updates = self.publisher_rules["update"]
        for n in range(0, len(self.profiles)):
            p = self.profiles[n]
            if p.user_id.value in cis_users:
                logger.info(
                    "Filtering out non-updateable values from user {} because it already exist in CIS".format(
                        p.user_id.value
                    )
                )
                for pfield in p.__dict__:
                    if pfield not in allowed_updates:
                        continue

                    # sub-item?
                    if isinstance(allowed_updates[pfield], dict):
                        for subpfield in allowed_updates[pfield]:
                            if allowed_updates[pfield][subpfield] != self.publisher_name:
                                if "value" in p.__dict__[pfield][subpfield].keys():
                                    p.__dict__[pfield][subpfield]["value"] = None
                                elif "values" in p.__dict__[pfield][subpfield].keys():
                                    p.__dict__[pfield][subpfield]["values"] = None
                    else:
                        if allowed_updates[pfield] != self.publisher_name:
                            if "value" in p.__dict__[pfield].keys():
                                p.__dict__[pfield]["value"] = None
                            elif "values" in p.__dict__[pfield].keys():
                                p.__dict__[pfield]["values"] = None
                logger.info("Filtered fields for user {}".format(p.user_id.value))
                self.profiles[n] = p

    def validate(self):
        """
        Validates all profiles
        """
        logger.info("Validating {} profiles".format(len(self.profiles)))
        null_user = cis_profile.User()

        # XXX ensure ldap2s3 use the right login_method
        # then remove this
        lm_map = {"ad": ["Mozilla-LDAP", "Mozilla-LDAP-Dev"]}
        if self.login_method in lm_map:
            local_login_method = lm_map[self.login_method]
        else:
            local_login_method = [self.login_method]

        for profile in self.profiles:
            if profile.login_method.value not in local_login_method:
                logger.error(
                    "Incorrect login method for this user {} - looking for {} but got {}".format(
                        profile.user_id.value, local_login_method, profile.login_method.value
                    )
                )
            profile.validate()
            profile.verify_all_signatures()
            # This should normally work since it's always like a create (even for update)
            profile.verify_all_publishers(null_user)
        logger.info("Validation completed for all profiles")
<|endoftext|>


<commit_before>from apps.auth.db import DbAuthService
from settings import SUBSCRIPTION_LEVEL, ACCESS_SUBSCRIPTIONS_MOBILE
from superdesk.errors import SuperdeskApiError
from superdesk import get_resource_service
from apps.auth.errors import CredentialsAuthError

class AccessAuthService(DbAuthService):

    def authenticate(self, credentials):
        self._check_subscription_level()
        self.disable_sd_desktop_notification(credentials)
        return super().authenticate(credentials)

    def _check_subscription_level(self):
        subscription = SUBSCRIPTION_LEVEL
        if subscription not in ACCESS_SUBSCRIPTIONS_MOBILE:
            raise SuperdeskApiError.forbiddenError(message='Liveblog mobile can not access on this subscription')

    def disable_sd_desktop_notification(self, credentials):
        user = get_resource_service('users').find_one(req=None, username=credentials.get('username'))
        if not user:
            raise CredentialsAuthError(credentials)
        user_updates = user
        user_updates['user_preferences']['desktop:notification']['enabled'] = False
        get_resource_service('users').system_update(user['_id'], user_updates, user)
<commit_msg>fix: issue with sd pop up hide method<commit_after>from apps.auth.db import DbAuthService
from settings import SUBSCRIPTION_LEVEL, ACCESS_SUBSCRIPTIONS_MOBILE
from superdesk.errors import SuperdeskApiError
from superdesk import get_resource_service
from apps.auth.errors import CredentialsAuthError

class AccessAuthService(DbAuthService):

    def authenticate(self, credentials):
        self._check_subscription_level()
        self.disable_sd_desktop_notification(credentials)
        return super().authenticate(credentials)

    def _check_subscription_level(self):
        subscription = SUBSCRIPTION_LEVEL
        if subscription not in ACCESS_SUBSCRIPTIONS_MOBILE:
            raise SuperdeskApiError.forbiddenError(message='Liveblog mobile can not access on this subscription')

    def disable_sd_desktop_notification(self, credentials):
        user = get_resource_service('users').find_one(req=None, username=credentials.get('username'))
        if not user:
            raise CredentialsAuthError(credentials)
        user_updates = user
        user_preferences = user_updates.get('user_preferences')
        if user_preferences:
            desktop_notification = user_preferences.get('desktop:notification')
            if desktop_notification:
                enabled = desktop_notification.get('enabled')
                if enabled:
                    user_updates['user_preferences']['desktop:notification']['enabled'] = False
        get_resource_service('users').system_update(user['_id'], user_updates, user)
<|endoftext|>