<commit_before>import os
import signal

from hokusai.command import command
from hokusai.config import HokusaiConfig
from hokusai.common import print_red, EXIT_SIGNALS, shout

@command
def development(skip_build):
  HokusaiConfig().check()
  docker_compose_yml = os.path.join(os.getcwd(), 'hokusai/development.yml')
  if not os.path.isfile(docker_compose_yml):
    print_red("Yaml file %s does not exist." % docker_compose_yml)
    return -1

  def cleanup(*args):
    pass
  for sig in EXIT_SIGNALS:
    signal.signal(sig, cleanup)

  if skip_build:
    opts = ''
  else:
    opts = '--build'
  shout("docker-compose -f %s up %s" % (docker_compose_yml, opts), print_output=True)
<commit_msg>refactor opts building in dev command<commit_after>import os
import signal

from hokusai.command import command
from hokusai.config import HokusaiConfig
from hokusai.common import print_red, EXIT_SIGNALS, shout

@command
def development(skip_build):
  HokusaiConfig().check()
  docker_compose_yml = os.path.join(os.getcwd(), 'hokusai/development.yml')
  if not os.path.isfile(docker_compose_yml):
    print_red("Yaml file %s does not exist." % docker_compose_yml)
    return -1

  def cleanup(*args):
    pass
  for sig in EXIT_SIGNALS:
    signal.signal(sig, cleanup)

  opts = ''
  if not skip_build:
    opts += ' --build'
  shout("docker-compose -f %s up%s" % (docker_compose_yml, opts), print_output=True)
<|endoftext|>


<commit_before>import os

from .base import *

DEBUG = False
SECRET_KEY = os.environ['SECRET_KEY']
STATIC_ROOT = os.environ['STATIC_ROOT']
MEDIA_ROOT = os.environ['STATIC_ROOT']

# I think more setup is required to force HTTPS
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

ALLOWED_HOSTS = [
    'aabmass.it.cx'
]

CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

# this can probably be tuned better
CONN_MAX_AGE = 60
<commit_msg>Oops, wrong envar for MEDIA_ROOT<commit_after>import os

from .base import *

DEBUG = False
SECRET_KEY = os.environ['SECRET_KEY']
STATIC_ROOT = os.environ['STATIC_ROOT']
MEDIA_ROOT = os.environ['MEDIA_ROOT']

# I think more setup is required to force HTTPS
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

ALLOWED_HOSTS = [
    'aabmass.it.cx'
]

CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

# this can probably be tuned better
CONN_MAX_AGE = 60
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# (c) 2017 Daniel Campos - AvanzOSC
# (c) 2017 Alfredo de la Fuente - AvanzOSC
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from openerp import fields, models, api, exceptions, _
import base64
import cStringIO
import tempfile
import csv

class ImportPriceFile(models.TransientModel):
    _name = 'import.price.file'
    _description = 'Wizard for import price list file'

    data = fields.Binary(string='File', required=True)
    name = fields.Char(string='Filename', required=False)
    delimeter = fields.Char(
        string='Delimeter', default=',', help='Default delimeter is ","')
    file_type = fields.Selection([('csv', 'CSV'),
                                  ('xls', 'XLS')], string='File type',
                                 required=True, default='csv')

    def _prepare_data_dict(self, data_dict):
        return data_dict

    def _import_csv(self, load_id, file_data, delimeter=';'):
        """ Imports data from a CSV file in defined object.
        @param load_id: Loading id
        @param file_data: Input data to load
        @param delimeter: CSV file data delimeter
        @return: Imported file number
        """
        file_line_obj = self.env['product.supplierinfo.load.line']
        data = base64.b64decode(file_data)
        file_input = cStringIO.StringIO(data)
        file_input.seek(0)
        reader_info = []
        reader = csv.reader(file_input, delimiter=str(delimeter),
                            lineterminator='\r\n')
        try:
            reader_info.extend(reader)
        except Exception:
            raise exceptions.Warning(_("Not a valid file!"))
        keys = reader_info[0]
        counter = 0
        if not isinstance(keys, list):
            raise exceptions.Warning(_("Not a valid file!"))
        del reader_info[0]
        for i in range(len(reader_info)):
            field = reader_info[i]
            values = dict(zip(keys, field))
            data_dict = self._prepare_data_dict(
                {'supplier': values.get('Supplier', ''),
                 'code': values.get('ProductCode', ''),
                 'sequence': values.get('Sequence', 0),
                 'supplier_code': values.get('ProductSupplierCode', ''),
                 'info': values.get('ProductSupplierName', ''),
                 'delay': values.get('Delay', 0),
                 'price': values.get('Price', 0.00).replace(',', '.'),
                 'min_qty': values.get('MinQty', 0.00),
                 'fail': True,
                 'fail_reason': _('No processed'),
                 'file_load': load_id})
            file_line_obj.create(data_dict)
            counter += 1
        return counter

    def _import_xls(self, load_id, file_data):
        """ Imports data from a XLS file in defined object.
        @param load_id: Loading id
        @param file_data: Input data to load
        @return: Imported file number
        """
        try:
            import xlrd
        except ImportError:
            exceptions.Warning(_("xlrd python lib  not installed"))
        file_line_obj = self.env['product.supplierinfo.load.line']
        file_1 = base64.decodestring(file_data)
        (fileno, fp_name) = tempfile.mkstemp('.xls', 'openerp_')
        openfile = open(fp_name, "w")
        openfile.write(file_1)
        openfile.seek(0)
        book = xlrd.open_workbook(fp_name)
        sheet = book.sheet_by_index(0)
        values = {}
        keys = sheet.row_values(0, 0, end_colx=sheet.ncols)
        for counter in range(sheet.nrows - 1):
            # grab the current row
            rowValues = sheet.row_values(counter + 1, 0,
                                         end_colx=sheet.ncols)
            row_lst = []
            for val in rowValues:  # codification format control
                if isinstance(val, unicode):
                    valor = val.encode('utf8')
                    row_lst.append(valor)
                elif isinstance(val, float):
                    if float(val) % 1 == 0.0:
                        row_lst.append(
                            '{0:.5f}'.format(float(val)).split('.')[0])
                    else:
                        row_lst.append('{0:g}'.format(float(val)))
                else:
                    row_lst.append(val)
            row = map(lambda x: str(x), row_lst)
            values = dict(zip(keys, row))
            data_dict = self._prepare_data_dict(
                {'supplier': values.get('Supplier', ''),
                 'code': values.get('ProductCode', ''),
                 'sequence': values.get('Sequence', 0),
                 'supplier_code': values.get('ProductSupplierCode', ''),
                 'info': values.get('ProductSupplierName', ''),
                 'delay': values.get('Delay', 0),
                 'price': values.get('Price', 0.00).replace(',', '.'),
                 'min_qty': values.get('MinQty', 0.00),
                 'fail': True,
                 'fail_reason': _('No processed'),
                 'file_load': load_id
                 })
            file_line_obj.create(data_dict)
            counter += 1
        return counter

    @api.multi
    def action_import(self):
        file_load_obj = self.env['product.supplierinfo.load']
        if self.env.context.get('active_id', False):
            load_id = self.env.context.get('active_id')
            file_load = file_load_obj.browse(load_id)
        for line in file_load.file_lines:
            line.unlink()
        for wiz in self:
            if not wiz.data:
                raise exceptions.Warning(_("You need to select a file!"))
            date_hour = fields.datetime.now()
            actual_date = fields.date.today()
            filename = wiz.name
            if wiz.file_type == 'csv':
                counter = self._import_csv(load_id, wiz.data, wiz.delimeter)
            elif wiz.file_type == 'xls':
                counter = self._import_xls(load_id, wiz.data)
            else:
                raise exceptions.Warning(_("Not a .csv/.xls file found"))
            file_load.write({'name': ('%s_%s') % (filename, actual_date),
                             'date': date_hour, 'fails': counter,
                             'file_name': filename, 'process': counter})
        return counter
<commit_msg>[IMP] product_supplierinfo_import: Change default minimun_qty to 1<commit_after># -*- coding: utf-8 -*-
# (c) 2017 Daniel Campos - AvanzOSC
# (c) 2017 Alfredo de la Fuente - AvanzOSC
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from openerp import fields, models, api, exceptions, _
import base64
import cStringIO
import tempfile
import csv

class ImportPriceFile(models.TransientModel):
    _name = 'import.price.file'
    _description = 'Wizard for import price list file'

    data = fields.Binary(string='File', required=True)
    name = fields.Char(string='Filename', required=False)
    delimeter = fields.Char(
        string='Delimeter', default=',', help='Default delimeter is ","')
    file_type = fields.Selection([('csv', 'CSV'),
                                  ('xls', 'XLS')], string='File type',
                                 required=True, default='csv')

    def _prepare_data_dict(self, data_dict):
        return data_dict

    def _import_csv(self, load_id, file_data, delimeter=';'):
        """ Imports data from a CSV file in defined object.
        @param load_id: Loading id
        @param file_data: Input data to load
        @param delimeter: CSV file data delimeter
        @return: Imported file number
        """
        file_line_obj = self.env['product.supplierinfo.load.line']
        data = base64.b64decode(file_data)
        file_input = cStringIO.StringIO(data)
        file_input.seek(0)
        reader_info = []
        reader = csv.reader(file_input, delimiter=str(delimeter),
                            lineterminator='\r\n')
        try:
            reader_info.extend(reader)
        except Exception:
            raise exceptions.Warning(_("Not a valid file!"))
        keys = reader_info[0]
        counter = 0
        if not isinstance(keys, list):
            raise exceptions.Warning(_("Not a valid file!"))
        del reader_info[0]
        for i in range(len(reader_info)):
            field = reader_info[i]
            values = dict(zip(keys, field))
            data_dict = self._prepare_data_dict(
                {'supplier': values.get('Supplier', ''),
                 'code': values.get('ProductCode', ''),
                 'sequence': values.get('Sequence', 0),
                 'supplier_code': values.get('ProductSupplierCode', ''),
                 'info': values.get('ProductSupplierName', ''),
                 'delay': values.get('Delay', 0),
                 'price': values.get('Price', 0.00).replace(',', '.'),
                 'min_qty': values.get('MinQty', 1.00),
                 'fail': True,
                 'fail_reason': _('No processed'),
                 'file_load': load_id})
            file_line_obj.create(data_dict)
            counter += 1
        return counter

    def _import_xls(self, load_id, file_data):
        """ Imports data from a XLS file in defined object.
        @param load_id: Loading id
        @param file_data: Input data to load
        @return: Imported file number
        """
        try:
            import xlrd
        except ImportError:
            exceptions.Warning(_("xlrd python lib  not installed"))
        file_line_obj = self.env['product.supplierinfo.load.line']
        file_1 = base64.decodestring(file_data)
        (fileno, fp_name) = tempfile.mkstemp('.xls', 'openerp_')
        openfile = open(fp_name, "w")
        openfile.write(file_1)
        openfile.seek(0)
        book = xlrd.open_workbook(fp_name)
        sheet = book.sheet_by_index(0)
        values = {}
        keys = sheet.row_values(0, 0, end_colx=sheet.ncols)
        for counter in range(sheet.nrows - 1):
            # grab the current row
            rowValues = sheet.row_values(counter + 1, 0,
                                         end_colx=sheet.ncols)
            row_lst = []
            for val in rowValues:  # codification format control
                if isinstance(val, unicode):
                    valor = val.encode('utf8')
                    row_lst.append(valor)
                elif isinstance(val, float):
                    if float(val) % 1 == 0.0:
                        row_lst.append(
                            '{0:.5f}'.format(float(val)).split('.')[0])
                    else:
                        row_lst.append('{0:g}'.format(float(val)))
                else:
                    row_lst.append(val)
            row = map(lambda x: str(x), row_lst)
            values = dict(zip(keys, row))
            data_dict = self._prepare_data_dict(
                {'supplier': values.get('Supplier', ''),
                 'code': values.get('ProductCode', ''),
                 'sequence': values.get('Sequence', 0),
                 'supplier_code': values.get('ProductSupplierCode', ''),
                 'info': values.get('ProductSupplierName', ''),
                 'delay': values.get('Delay', 0),
                 'price': values.get('Price', 0.00).replace(',', '.'),
                 'min_qty': values.get('MinQty', 0.00),
                 'fail': True,
                 'fail_reason': _('No processed'),
                 'file_load': load_id
                 })
            file_line_obj.create(data_dict)
            counter += 1
        return counter

    @api.multi
    def action_import(self):
        file_load_obj = self.env['product.supplierinfo.load']
        if self.env.context.get('active_id', False):
            load_id = self.env.context.get('active_id')
            file_load = file_load_obj.browse(load_id)
        for line in file_load.file_lines:
            line.unlink()
        for wiz in self:
            if not wiz.data:
                raise exceptions.Warning(_("You need to select a file!"))
            date_hour = fields.datetime.now()
            actual_date = fields.date.today()
            filename = wiz.name
            if wiz.file_type == 'csv':
                counter = self._import_csv(load_id, wiz.data, wiz.delimeter)
            elif wiz.file_type == 'xls':
                counter = self._import_xls(load_id, wiz.data)
            else:
                raise exceptions.Warning(_("Not a .csv/.xls file found"))
            file_load.write({'name': ('%s_%s') % (filename, actual_date),
                             'date': date_hour, 'fails': counter,
                             'file_name': filename, 'process': counter})
        return counter
<|endoftext|>


<commit_before>"""An abstract class for entities."""
import asyncio
import logging
from timeit import default_timer as timer

from typing import Any, Optional, List, Dict

from homeassistant.const import (
    ATTR_ASSUMED_STATE, ATTR_FRIENDLY_NAME, ATTR_HIDDEN, ATTR_ICON,
    ATTR_UNIT_OF_MEASUREMENT, DEVICE_DEFAULT_NAME, STATE_OFF, STATE_ON,
    STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT,
    ATTR_ENTITY_PICTURE)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import NoEntitySpecifiedError
from homeassistant.util import ensure_unique_string, slugify
from homeassistant.util.async import (
    run_coroutine_threadsafe, run_callback_threadsafe)

# Entity attributes that we will overwrite
_OVERWRITE = {}  # type: Dict[str, Any]

_LOGGER = logging.getLogger(__name__)

def generate_entity_id(entity_id_format: str, name: Optional[str],
                       current_ids: Optional[List[str]]=None,
                       hass: Optional[HomeAssistant]=None) -> str:
    """Generate a unique entity ID based on given entity IDs or used IDs."""
    if current_ids is None:
        if hass is None:
            raise ValueError("Missing required parameter currentids or hass")
        else:
            return run_callback_threadsafe(
                hass.loop, async_generate_entity_id, entity_id_format, name,
                current_ids, hass
            ).result()

    name = (name or DEVICE_DEFAULT_NAME).lower()

    return ensure_unique_string(
        entity_id_format.format(slugify(name)), current_ids)

def async_generate_entity_id(entity_id_format: str, name: Optional[str],
                             current_ids: Optional[List[str]]=None,
                             hass: Optional[HomeAssistant]=None) -> str:
    """Generate a unique entity ID based on given entity IDs or used IDs."""
    if current_ids is None:
        if hass is None:
            raise ValueError("Missing required parameter currentids or hass")

        current_ids = hass.states.async_entity_ids()
    name = (name or DEVICE_DEFAULT_NAME).lower()

    return ensure_unique_string(
        entity_id_format.format(slugify(name)), current_ids)

def set_customize(customize: Dict[str, Any]) -> None:
    """Overwrite all current customize settings.

    Async friendly.
    """
    global _OVERWRITE

    _OVERWRITE = {key.lower(): val for key, val in customize.items()}

class Entity(object):
    """An abstract class for Home Assistant entities."""

    # pylint: disable=no-self-use
    # SAFE TO OVERWRITE
    # The properties and methods here are safe to overwrite when inheriting
    # this class. These may be used to customize the behavior of the entity.
    entity_id = None  # type: str

    # Owning hass instance. Will be set by EntityComponent
    hass = None  # type: Optional[HomeAssistant]

    @property
    def should_poll(self) -> bool:
        """Return True if entity has to be polled for state.

        False if entity pushes its state to HA.
        """
        return True

    @property
    def unique_id(self) -> str:
        """Return an unique ID."""
        return "{}.{}".format(self.__class__, id(self))

    @property
    def name(self) -> Optional[str]:
        """Return the name of the entity."""
        return None

    @property
    def state(self) -> str:
        """Return the state of the entity."""
        return STATE_UNKNOWN

    @property
    def state_attributes(self):
        """Return the state attributes.

        Implemented by component base class.
        """
        return None

    @property
    def device_state_attributes(self):
        """Return device specific state attributes.

        Implemented by platform classes.
        """
        return None

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement of this entity, if any."""
        return None

    @property
    def icon(self):
        """Return the icon to use in the frontend, if any."""
        return None

    @property
    def entity_picture(self):
        """Return the entity picture to use in the frontend, if any."""
        return None

    @property
    def hidden(self) -> bool:
        """Return True if the entity should be hidden from UIs."""
        return False

    @property
    def available(self) -> bool:
        """Return True if entity is available."""
        return True

    @property
    def assumed_state(self) -> bool:
        """Return True if unable to access real state of the entity."""
        return False

    @property
    def force_update(self) -> bool:
        """Return True if state updates should be forced.

        If True, a state change will be triggered anytime the state property is
        updated, not just when the value changes.
        """
        return False

    def update(self):
        """Retrieve latest state.

        When not implemented, will forward call to async version if available.
        """
        async_update = getattr(self, 'async_update', None)

        if async_update is None:
            return

        run_coroutine_threadsafe(async_update(), self.hass.loop).result()

    # DO NOT OVERWRITE
    # These properties and methods are either managed by Home Assistant or they
    # are used to perform a very specific function. Overwriting these may
    # produce undesirable effects in the entity's operation.

    def update_ha_state(self, force_refresh=False):
        """Update Home Assistant with current state of entity.

        If force_refresh == True will update entity before setting state.
        """
        # We're already in a thread, do the force refresh here.
        if force_refresh and not hasattr(self, 'async_update'):
            self.update()
            force_refresh = False

        run_coroutine_threadsafe(
            self.async_update_ha_state(force_refresh), self.hass.loop
        ).result()

    @asyncio.coroutine
    def async_update_ha_state(self, force_refresh=False):
        """Update Home Assistant with current state of entity.

        If force_refresh == True will update entity before setting state.

        This method must be run in the event loop.
        """
        if self.hass is None:
            raise RuntimeError("Attribute hass is None for {}".format(self))

        if self.entity_id is None:
            raise NoEntitySpecifiedError(
                "No entity id specified for entity {}".format(self.name))

        if force_refresh:
            if hasattr(self, 'async_update'):
                # pylint: disable=no-member
                yield from self.async_update()
            else:
                # PS: Run this in our own thread pool once we have
                #     future support?
                yield from self.hass.loop.run_in_executor(None, self.update)

        start = timer()

        state = self.state

        if state is None:
            state = STATE_UNKNOWN
        else:
            state = str(state)

        attr = self.state_attributes or {}

        device_attr = self.device_state_attributes

        if device_attr is not None:
            attr.update(device_attr)

        self._attr_setter('unit_of_measurement', str, ATTR_UNIT_OF_MEASUREMENT,
                          attr)

        if not self.available:
            state = STATE_UNAVAILABLE
            attr = {}

        self._attr_setter('name', str, ATTR_FRIENDLY_NAME, attr)
        self._attr_setter('icon', str, ATTR_ICON, attr)
        self._attr_setter('entity_picture', str, ATTR_ENTITY_PICTURE, attr)
        self._attr_setter('hidden', bool, ATTR_HIDDEN, attr)
        self._attr_setter('assumed_state', bool, ATTR_ASSUMED_STATE, attr)

        end = timer()

        if end - start > 0.2:
            _LOGGER.warning('Updating state for %s took %.3f seconds. '
                            'Please report platform to the developers at '
                            'https://goo.gl/Nvioub', self.entity_id,
                            end - start)

        # Overwrite properties that have been set in the config file.
        attr.update(_OVERWRITE.get(self.entity_id, {}))

        # Remove hidden property if false so it won't show up.
        if not attr.get(ATTR_HIDDEN, True):
            attr.pop(ATTR_HIDDEN)

        # Convert temperature if we detect one
        try:
            unit_of_measure = attr.get(ATTR_UNIT_OF_MEASUREMENT)
            if unit_of_measure in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
                units = self.hass.config.units
                state = str(units.temperature(float(state), unit_of_measure))
                attr[ATTR_UNIT_OF_MEASUREMENT] = units.temperature_unit
        except ValueError:
            # Could not convert state to float
            pass

        self.hass.states.async_set(
            self.entity_id, state, attr, self.force_update)

    def remove(self) -> None:
        """Remove entitiy from HASS."""
        run_coroutine_threadsafe(
            self.async_remove(), self.hass.loop
        ).result()

    @asyncio.coroutine
    def async_remove(self) -> None:
        """Remove entitiy from async HASS.

        This method must be run in the event loop.
        """
        self.hass.states.async_remove(self.entity_id)

    def _attr_setter(self, name, typ, attr, attrs):
        """Helper method to populate attributes based on properties."""
        if attr in attrs:
            return

        value = getattr(self, name)

        if not value:
            return

        try:
            attrs[attr] = typ(value)
        except (TypeError, ValueError):
            pass

    def __eq__(self, other):
        """Return the comparison."""
        return (isinstance(other, Entity) and
                other.unique_id == self.unique_id)

    def __repr__(self):
        """Return the representation."""
        return "<Entity {}: {}>".format(self.name, self.state)

class ToggleEntity(Entity):
    """An abstract class for entities that can be turned on and off."""

    # pylint: disable=no-self-use
    @property
    def state(self) -> str:
        """Return the state."""
        return STATE_ON if self.is_on else STATE_OFF

    @property
    def is_on(self) -> bool:
        """Return True if entity is on."""
        raise NotImplementedError()

    def turn_on(self, **kwargs) -> None:
        """Turn the entity on."""
        run_coroutine_threadsafe(self.async_turn_on(**kwargs),
                                 self.hass.loop).result()

    @asyncio.coroutine
    def async_turn_on(self, **kwargs):
        """Turn the entity on."""
        raise NotImplementedError()

    def turn_off(self, **kwargs) -> None:
        """Turn the entity off."""
        run_coroutine_threadsafe(self.async_turn_off(**kwargs),
                                 self.hass.loop).result()

    @asyncio.coroutine
    def async_turn_off(self, **kwargs):
        """Turn the entity off."""
        raise NotImplementedError()

    def toggle(self) -> None:
        """Toggle the entity."""
        if self.is_on:
            self.turn_off()
        else:
            self.turn_on()

    @asyncio.coroutine
    def async_toggle(self):
        """Toggle the entity."""
        if self.is_on:
            yield from self.async_turn_off()
        else:
            yield from self.async_turn_on()
<commit_msg>Increase update delay (#4321)<commit_after>"""An abstract class for entities."""
import asyncio
import logging
from timeit import default_timer as timer

from typing import Any, Optional, List, Dict

from homeassistant.const import (
    ATTR_ASSUMED_STATE, ATTR_FRIENDLY_NAME, ATTR_HIDDEN, ATTR_ICON,
    ATTR_UNIT_OF_MEASUREMENT, DEVICE_DEFAULT_NAME, STATE_OFF, STATE_ON,
    STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT,
    ATTR_ENTITY_PICTURE)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import NoEntitySpecifiedError
from homeassistant.util import ensure_unique_string, slugify
from homeassistant.util.async import (
    run_coroutine_threadsafe, run_callback_threadsafe)

# Entity attributes that we will overwrite
_OVERWRITE = {}  # type: Dict[str, Any]

_LOGGER = logging.getLogger(__name__)

def generate_entity_id(entity_id_format: str, name: Optional[str],
                       current_ids: Optional[List[str]]=None,
                       hass: Optional[HomeAssistant]=None) -> str:
    """Generate a unique entity ID based on given entity IDs or used IDs."""
    if current_ids is None:
        if hass is None:
            raise ValueError("Missing required parameter currentids or hass")
        else:
            return run_callback_threadsafe(
                hass.loop, async_generate_entity_id, entity_id_format, name,
                current_ids, hass
            ).result()

    name = (name or DEVICE_DEFAULT_NAME).lower()

    return ensure_unique_string(
        entity_id_format.format(slugify(name)), current_ids)

def async_generate_entity_id(entity_id_format: str, name: Optional[str],
                             current_ids: Optional[List[str]]=None,
                             hass: Optional[HomeAssistant]=None) -> str:
    """Generate a unique entity ID based on given entity IDs or used IDs."""
    if current_ids is None:
        if hass is None:
            raise ValueError("Missing required parameter currentids or hass")

        current_ids = hass.states.async_entity_ids()
    name = (name or DEVICE_DEFAULT_NAME).lower()

    return ensure_unique_string(
        entity_id_format.format(slugify(name)), current_ids)

def set_customize(customize: Dict[str, Any]) -> None:
    """Overwrite all current customize settings.

    Async friendly.
    """
    global _OVERWRITE

    _OVERWRITE = {key.lower(): val for key, val in customize.items()}

class Entity(object):
    """An abstract class for Home Assistant entities."""

    # pylint: disable=no-self-use
    # SAFE TO OVERWRITE
    # The properties and methods here are safe to overwrite when inheriting
    # this class. These may be used to customize the behavior of the entity.
    entity_id = None  # type: str

    # Owning hass instance. Will be set by EntityComponent
    hass = None  # type: Optional[HomeAssistant]

    @property
    def should_poll(self) -> bool:
        """Return True if entity has to be polled for state.

        False if entity pushes its state to HA.
        """
        return True

    @property
    def unique_id(self) -> str:
        """Return an unique ID."""
        return "{}.{}".format(self.__class__, id(self))

    @property
    def name(self) -> Optional[str]:
        """Return the name of the entity."""
        return None

    @property
    def state(self) -> str:
        """Return the state of the entity."""
        return STATE_UNKNOWN

    @property
    def state_attributes(self):
        """Return the state attributes.

        Implemented by component base class.
        """
        return None

    @property
    def device_state_attributes(self):
        """Return device specific state attributes.

        Implemented by platform classes.
        """
        return None

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement of this entity, if any."""
        return None

    @property
    def icon(self):
        """Return the icon to use in the frontend, if any."""
        return None

    @property
    def entity_picture(self):
        """Return the entity picture to use in the frontend, if any."""
        return None

    @property
    def hidden(self) -> bool:
        """Return True if the entity should be hidden from UIs."""
        return False

    @property
    def available(self) -> bool:
        """Return True if entity is available."""
        return True

    @property
    def assumed_state(self) -> bool:
        """Return True if unable to access real state of the entity."""
        return False

    @property
    def force_update(self) -> bool:
        """Return True if state updates should be forced.

        If True, a state change will be triggered anytime the state property is
        updated, not just when the value changes.
        """
        return False

    def update(self):
        """Retrieve latest state.

        When not implemented, will forward call to async version if available.
        """
        async_update = getattr(self, 'async_update', None)

        if async_update is None:
            return

        run_coroutine_threadsafe(async_update(), self.hass.loop).result()

    # DO NOT OVERWRITE
    # These properties and methods are either managed by Home Assistant or they
    # are used to perform a very specific function. Overwriting these may
    # produce undesirable effects in the entity's operation.

    def update_ha_state(self, force_refresh=False):
        """Update Home Assistant with current state of entity.

        If force_refresh == True will update entity before setting state.
        """
        # We're already in a thread, do the force refresh here.
        if force_refresh and not hasattr(self, 'async_update'):
            self.update()
            force_refresh = False

        run_coroutine_threadsafe(
            self.async_update_ha_state(force_refresh), self.hass.loop
        ).result()

    @asyncio.coroutine
    def async_update_ha_state(self, force_refresh=False):
        """Update Home Assistant with current state of entity.

        If force_refresh == True will update entity before setting state.

        This method must be run in the event loop.
        """
        if self.hass is None:
            raise RuntimeError("Attribute hass is None for {}".format(self))

        if self.entity_id is None:
            raise NoEntitySpecifiedError(
                "No entity id specified for entity {}".format(self.name))

        if force_refresh:
            if hasattr(self, 'async_update'):
                # pylint: disable=no-member
                yield from self.async_update()
            else:
                # PS: Run this in our own thread pool once we have
                #     future support?
                yield from self.hass.loop.run_in_executor(None, self.update)

        start = timer()

        state = self.state

        if state is None:
            state = STATE_UNKNOWN
        else:
            state = str(state)

        attr = self.state_attributes or {}

        device_attr = self.device_state_attributes

        if device_attr is not None:
            attr.update(device_attr)

        self._attr_setter('unit_of_measurement', str, ATTR_UNIT_OF_MEASUREMENT,
                          attr)

        if not self.available:
            state = STATE_UNAVAILABLE
            attr = {}

        self._attr_setter('name', str, ATTR_FRIENDLY_NAME, attr)
        self._attr_setter('icon', str, ATTR_ICON, attr)
        self._attr_setter('entity_picture', str, ATTR_ENTITY_PICTURE, attr)
        self._attr_setter('hidden', bool, ATTR_HIDDEN, attr)
        self._attr_setter('assumed_state', bool, ATTR_ASSUMED_STATE, attr)

        end = timer()

        if end - start > 0.4:
            _LOGGER.warning('Updating state for %s took %.3f seconds. '
                            'Please report platform to the developers at '
                            'https://goo.gl/Nvioub', self.entity_id,
                            end - start)

        # Overwrite properties that have been set in the config file.
        attr.update(_OVERWRITE.get(self.entity_id, {}))

        # Remove hidden property if false so it won't show up.
        if not attr.get(ATTR_HIDDEN, True):
            attr.pop(ATTR_HIDDEN)

        # Convert temperature if we detect one
        try:
            unit_of_measure = attr.get(ATTR_UNIT_OF_MEASUREMENT)
            if unit_of_measure in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
                units = self.hass.config.units
                state = str(units.temperature(float(state), unit_of_measure))
                attr[ATTR_UNIT_OF_MEASUREMENT] = units.temperature_unit
        except ValueError:
            # Could not convert state to float
            pass

        self.hass.states.async_set(
            self.entity_id, state, attr, self.force_update)

    def remove(self) -> None:
        """Remove entitiy from HASS."""
        run_coroutine_threadsafe(
            self.async_remove(), self.hass.loop
        ).result()

    @asyncio.coroutine
    def async_remove(self) -> None:
        """Remove entitiy from async HASS.

        This method must be run in the event loop.
        """
        self.hass.states.async_remove(self.entity_id)

    def _attr_setter(self, name, typ, attr, attrs):
        """Helper method to populate attributes based on properties."""
        if attr in attrs:
            return

        value = getattr(self, name)

        if not value:
            return

        try:
            attrs[attr] = typ(value)
        except (TypeError, ValueError):
            pass

    def __eq__(self, other):
        """Return the comparison."""
        return (isinstance(other, Entity) and
                other.unique_id == self.unique_id)

    def __repr__(self):
        """Return the representation."""
        return "<Entity {}: {}>".format(self.name, self.state)

class ToggleEntity(Entity):
    """An abstract class for entities that can be turned on and off."""

    # pylint: disable=no-self-use
    @property
    def state(self) -> str:
        """Return the state."""
        return STATE_ON if self.is_on else STATE_OFF

    @property
    def is_on(self) -> bool:
        """Return True if entity is on."""
        raise NotImplementedError()

    def turn_on(self, **kwargs) -> None:
        """Turn the entity on."""
        run_coroutine_threadsafe(self.async_turn_on(**kwargs),
                                 self.hass.loop).result()

    @asyncio.coroutine
    def async_turn_on(self, **kwargs):
        """Turn the entity on."""
        raise NotImplementedError()

    def turn_off(self, **kwargs) -> None:
        """Turn the entity off."""
        run_coroutine_threadsafe(self.async_turn_off(**kwargs),
                                 self.hass.loop).result()

    @asyncio.coroutine
    def async_turn_off(self, **kwargs):
        """Turn the entity off."""
        raise NotImplementedError()

    def toggle(self) -> None:
        """Toggle the entity."""
        if self.is_on:
            self.turn_off()
        else:
            self.turn_on()

    @asyncio.coroutine
    def async_toggle(self):
        """Toggle the entity."""
        if self.is_on:
            yield from self.async_turn_off()
        else:
            yield from self.async_turn_on()
<|endoftext|>


<commit_before>from pygame.surface import locked
from pygame.color import create_color
from pygame.rect import Rect
import pygame.surface

def _check_surface(surface):
    if not isinstance(surface, pygame.surface.Surface):
        raise TypeError("First argument must be a Surface.")
    # TODO: depth check.

def _check_point(point, msg="points must be number pairs"):
    if not (hasattr(point, '__iter__') and len(point) == 2
            and all(isinstance(p, int) for p in point)):
        raise TypeError(msg)
    return point

def _check_and_filter_points(points, minlen=1):
    if not hasattr(points, '__iter__'):
        raise TypeError("points argument must be a sequence of number pairs")

    if len(points) < minlen:
        raise ValueError("points argument must contain %s or more points" % (
            minlen,))

    _check_point(points[0])

    filtered = []
    for point in points:
        try:
            x, y = _check_point(point)
        except TypeError:
            # Silently skip over bad points, because pygame does. :-(
            continue
        filtered.append((x, y))
    return filtered

def _make_drawn_rect(points, surface):
    rect = surface.get_clip()
    left = max(rect.left, min(p[0] for p in points))
    right = min(rect.right, max(p[0] for p in points))
    top = max(rect.top, min(p[1] for p in points))
    bottom = min(rect.bottom, max(p[1] for p in points))
    return Rect(left, top, right - left + 1, bottom - top + 1)

_CLIP_LEFT = 1
_CLIP_RIGHT = 2
_CLIP_TOP = 4
_CLIP_BOTTOM = 8

def _outcode(rect, x, y):
    code = 0
    if x < rect.left:
        code |= _CLIP_LEFT
    elif x >= rect.right:
        code |= _CLIP_RIGHT
    if y < rect.top:
        code |= _CLIP_TOP
    elif y >= rect.bottom:
        code |= _CLIP_BOTTOM
    return code

def _clipline(rect, start, end):
    # Cohen-Sutherland algorithm
    x0, y0 = start
    x1, y1 = end

    left = rect.left
    right = rect.right - 1
    top = rect.top
    bottom = rect.bottom - 1

    out0 = _outcode(rect, x0, y0)
    out1 = _outcode(rect, x1, y1)

    while True:
        if not (out0 | out1):
            return (x0, y0), (x1, y1)
        elif (out0 & out1):
            return None, None

        if not out0:
            x0, x1 = x1, x0
            y0, y1 = y1, y0
            out0, out1 = out1, out0

        m = 1.0
        if x0 != x1:
            m = float(y1 - y0) / float(x1 - x0)

        if out0 & _CLIP_LEFT:
            y0 += int(m * (left - x0))
            x0 = left

        elif out0 & _CLIP_RIGHT:
            y0 += int(m * (right - x0))
            x0 = right

        elif out0 & _CLIP_TOP:
            if x0 != x1:
                x0 += int((top - y0) / m)
            y0 = top

        elif out0 & _CLIP_BOTTOM:
            if x0 != x1:
                x0 += int((bottom - y0) / m)
            y0 = bottom

        out0 = _outcode(rect, x0, y0)

def _drawline(surface, c_color, start, end):
    # Bresenham algorithm (more or less as approximated by pygame)
    x0, y0 = start
    x1, y1 = end

    # Because of how we approximate pygame's pointer
    # arthimetic, we don't handle the ends of the lines
    # the same way - this fakes it
    surface._set_at(x0, y0, c_color)
    surface._set_at(x1, y1, c_color)
    steep = False
    if abs(y1 - y0) > abs(x1 - x0):
        steep = True
        x0, y0 = y0, x0
        x1, y1 = y1, x1
    dx = abs(x1 - x0) + 1
    dy = abs(y1 - y0) + 1
    ystep = 1 if y0 < y1 else -1
    xstep = 1 if x0 < x1 else -1
    y = y0
    error = 0
    for x in range(x0, x1, xstep):
        if steep:
            surface._set_at(y, x, c_color)
        else:
            surface._set_at(x, y, c_color)
        error = error + dy
        if error >= dx:
            y += ystep
            error -= dx

def _clip_and_draw_line(surface, c_color, start, end):
    # rect = surface.get_clip().inflate(-60, -60)
    # start, end = _clipline(rect, start, end)
    start, end = _clipline(surface.get_clip(), start, end)
    if start is None:
        return False

    _drawline(surface, c_color, start, end)
    return True

def _clip_and_draw_line_width(surface, c_color, width, start, end):
    x0, y0 = start
    x1, y1 = end

    xinc = yinc = 0
    if abs(x1 - x0) > abs(y1 - y0):
        yinc = 1
    else:
        xinc = 1

    # XXX: Instead of getting the minimum and maximum for each direction (which
    #      we do here), pygame gets the minimum of the start coords and the
    #      maximum of the end coords. I think we're right, but we should maybe
    #      match what pygame does instead even though it's more of a pain to
    #      implement.

    points = set()
    p0 = (x0, y0)
    p1 = (x1, y1)
    if _clip_and_draw_line(surface, c_color, p0, p1):
        points.update((p0, p1))

    for i in xrange(width / 2):
        p0 = (x0 + xinc * (i + 1), y0 + yinc * (i + 1))
        p1 = (x1 + xinc * (i + 1), y1 + yinc * (i + 1))
        if _clip_and_draw_line(surface, c_color, p0, p1):
            points.update((p0, p1))
        # When the width is odd, we only draw the +xinc case
        # on the last pass through the loop
        if (2 * i + 2 < width):
            p0 = (x0 - xinc * (i + 1), y0 - yinc * (i + 1))
            p1 = (x1 - xinc * (i + 1), y1 - yinc * (i + 1))
            if _clip_and_draw_line(surface, c_color, p0, p1):
                points.update((p0, p1))

    if points:
        # points would be empty if nothing was drawn
        return _make_drawn_rect(points, surface)
    return None

def line(surface, color, start, end, width=1):
    _check_surface(surface)
    c_color = create_color(color, surface._format)

    _check_point(start, "Invalid start position argument")
    _check_point(end, "Invalid end position argument")

    [start] = _check_and_filter_points([start])
    [end] = _check_and_filter_points([end])

    if width < 1:
        return Rect(start, (0, 0))

    with locked(surface._c_surface):
        drawn = _clip_and_draw_line_width(surface, c_color, width, start, end)

    if drawn is None:
        return Rect(start, (0, 0))
    return drawn

def lines(surface, color, closed, points, width=1):
    _check_surface(surface)
    c_color = create_color(color, surface._format)
    points = _check_and_filter_points(points, 2)
    drawn_points = set()

    with locked(surface._c_surface):
        start_point = points[0]
        for point in points[1:]:
            drawn = _clip_and_draw_line_width(
                surface, c_color, width, start_point, point)
            if drawn is not None:
                drawn_points.add(drawn.topleft)
                drawn_points.add(drawn.bottomright)
            start_point = point

        if closed and len(points) > 2:
            _clip_and_draw_line_width(
                surface, c_color, width, points[-1], points[0])

    return _make_drawn_rect(drawn_points, surface)

def _draw_fillpoly(surface, points, c_color):
    # Very traditional scanline fill approach
    # (also the approach used by pygame)
    ys = [p[1] for p in points]
    miny = min(ys)
    maxy = max(ys)
    times = []
    # For speed reasons, we integrate clipping into the calculations,
    # rather than calling _clip_and_draw_line
    clip_rect = surface.get_clip()
    all_points = zip(points, points[-1:] + points[:-1])
    for y in range(miny, maxy + 1):
        if y < clip_rect.top or y >= clip_rect.bottom:
            continue
        intercepts = []
        for p1, p2 in all_points:
            if p1[1] == p2[1]:
                # Edge of the polygon, so skip (due to division by 0)
                continue
            elif p1[1] < p2[1]:
                x1, y1 = p1
                x2, y2 = p2
            else:
                x1, y1 = p2
                x2, y2 = p1

            if not (y1 <= y < y2) and not (y == maxy and y1 < y <= y2):
                continue
            x = (y - y1) * (x2 - x1) / (y2 - y1) + x1
            # This works because we're drawing horizontal lines
            if x < clip_rect.left:
                x = clip_rect.left
            elif x >= clip_rect.right:
                x = clip_rect.right - 1
            intercepts.append(x)
        intercepts.sort()
        for x1, x2 in zip(intercepts[::2], intercepts[1::2]):
            _drawline(surface, c_color, (x1, y), (x2, y))

def polygon(surface, color, points, width=0):
    _check_surface(surface)

    if width != 0:
        return lines(surface, color, 1, points, width)

    c_color = create_color(color, surface._format)
    points = _check_and_filter_points(points, 3)

    with locked(surface._c_surface):
        _draw_fillpoly(surface, points, c_color)

    return _make_drawn_rect(points, surface)

def rect(surface, color, rect, width=0):
    if not isinstance(surface, pygame.surface.Surface):
        raise TypeError("First argument must be a Surface.")

    rect = Rect(rect)
    l = rect.x
    r = rect.x + rect.w - 1
    t = rect.y
    b = rect.y + rect.h - 1

    points = ((l, t), (r, t), (r, b), (l, b))
    return polygon(surface, color, points, width)
<commit_msg>Investigator spends 1 sanity to fix polygon conformance tests<commit_after>from pygame.surface import locked
from pygame.color import create_color
from pygame.rect import Rect
import pygame.surface

def _check_surface(surface):
    if not isinstance(surface, pygame.surface.Surface):
        raise TypeError("First argument must be a Surface.")
    # TODO: depth check.

def _check_point(point, msg="points must be number pairs"):
    if not (hasattr(point, '__iter__') and len(point) == 2
            and all(isinstance(p, int) for p in point)):
        raise TypeError(msg)
    return point

def _check_and_filter_points(points, minlen=1):
    if not hasattr(points, '__iter__'):
        raise TypeError("points argument must be a sequence of number pairs")

    if len(points) < minlen:
        raise ValueError("points argument must contain %s or more points" % (
            minlen,))

    _check_point(points[0])

    filtered = []
    for point in points:
        try:
            x, y = _check_point(point)
        except TypeError:
            # Silently skip over bad points, because pygame does. :-(
            continue
        filtered.append((x, y))
    return filtered

def _make_drawn_rect(points, surface):
    rect = surface.get_clip()
    left = max(rect.left, min(p[0] for p in points))
    right = min(rect.right, max(p[0] for p in points))
    top = max(rect.top, min(p[1] for p in points))
    bottom = min(rect.bottom, max(p[1] for p in points))
    return Rect(left, top, right - left + 1, bottom - top + 1)

_CLIP_LEFT = 1
_CLIP_RIGHT = 2
_CLIP_TOP = 4
_CLIP_BOTTOM = 8

def _outcode(rect, x, y):
    code = 0
    if x < rect.left:
        code |= _CLIP_LEFT
    elif x >= rect.right:
        code |= _CLIP_RIGHT
    if y < rect.top:
        code |= _CLIP_TOP
    elif y >= rect.bottom:
        code |= _CLIP_BOTTOM
    return code

def _clipline(rect, start, end):
    # Cohen-Sutherland algorithm
    x0, y0 = start
    x1, y1 = end

    left = rect.left
    right = rect.right - 1
    top = rect.top
    bottom = rect.bottom - 1

    out0 = _outcode(rect, x0, y0)
    out1 = _outcode(rect, x1, y1)

    while True:
        if not (out0 | out1):
            return (x0, y0), (x1, y1)
        elif (out0 & out1):
            return None, None

        if not out0:
            x0, x1 = x1, x0
            y0, y1 = y1, y0
            out0, out1 = out1, out0

        m = 1.0
        if x0 != x1:
            m = float(y1 - y0) / float(x1 - x0)

        if out0 & _CLIP_LEFT:
            y0 += int(m * (left - x0))
            x0 = left

        elif out0 & _CLIP_RIGHT:
            y0 += int(m * (right - x0))
            x0 = right

        elif out0 & _CLIP_TOP:
            if x0 != x1:
                x0 += int((top - y0) / m)
            y0 = top

        elif out0 & _CLIP_BOTTOM:
            if x0 != x1:
                x0 += int((bottom - y0) / m)
            y0 = bottom

        out0 = _outcode(rect, x0, y0)

def _drawline(surface, c_color, start, end):
    # Bresenham algorithm (more or less as approximated by pygame)
    x0, y0 = start
    x1, y1 = end

    # Because of how we approximate pygame's pointer
    # arthimetic, we don't handle the ends of the lines
    # the same way - this fakes it
    surface._set_at(x0, y0, c_color)
    surface._set_at(x1, y1, c_color)
    steep = False
    if abs(y1 - y0) > abs(x1 - x0):
        steep = True
        x0, y0 = y0, x0
        x1, y1 = y1, x1
    dx = abs(x1 - x0) + 1
    dy = abs(y1 - y0) + 1
    ystep = 1 if y0 < y1 else -1
    xstep = 1 if x0 < x1 else -1
    y = y0
    error = 0
    for x in range(x0, x1, xstep):
        if steep:
            surface._set_at(y, x, c_color)
        else:
            surface._set_at(x, y, c_color)
        error = error + dy
        if error >= dx:
            y += ystep
            error -= dx

def _clip_and_draw_line(surface, c_color, start, end):
    # rect = surface.get_clip().inflate(-60, -60)
    # start, end = _clipline(rect, start, end)
    start, end = _clipline(surface.get_clip(), start, end)
    if start is None:
        return False

    _drawline(surface, c_color, start, end)
    return True

def _clip_and_draw_line_width(surface, c_color, width, start, end):
    x0, y0 = start
    x1, y1 = end

    xinc = yinc = 0
    if abs(x1 - x0) > abs(y1 - y0):
        yinc = 1
    else:
        xinc = 1

    # XXX: Instead of getting the minimum and maximum for each direction (which
    #      we do here), pygame gets the minimum of the start coords and the
    #      maximum of the end coords. I think we're right, but we should maybe
    #      match what pygame does instead even though it's more of a pain to
    #      implement.

    points = set()
    p0 = (x0, y0)
    p1 = (x1, y1)
    if _clip_and_draw_line(surface, c_color, p0, p1):
        points.update((p0, p1))

    for i in xrange(width / 2):
        p0 = (x0 + xinc * (i + 1), y0 + yinc * (i + 1))
        p1 = (x1 + xinc * (i + 1), y1 + yinc * (i + 1))
        if _clip_and_draw_line(surface, c_color, p0, p1):
            points.update((p0, p1))
        # When the width is odd, we only draw the +xinc case
        # on the last pass through the loop
        if (2 * i + 2 < width):
            p0 = (x0 - xinc * (i + 1), y0 - yinc * (i + 1))
            p1 = (x1 - xinc * (i + 1), y1 - yinc * (i + 1))
            if _clip_and_draw_line(surface, c_color, p0, p1):
                points.update((p0, p1))

    if points:
        # points would be empty if nothing was drawn
        return _make_drawn_rect(points, surface)
    return None

def line(surface, color, start, end, width=1):
    _check_surface(surface)
    c_color = create_color(color, surface._format)

    _check_point(start, "Invalid start position argument")
    _check_point(end, "Invalid end position argument")

    [start] = _check_and_filter_points([start])
    [end] = _check_and_filter_points([end])

    if width < 1:
        return Rect(start, (0, 0))

    with locked(surface._c_surface):
        drawn = _clip_and_draw_line_width(surface, c_color, width, start, end)

    if drawn is None:
        return Rect(start, (0, 0))
    return drawn

def lines(surface, color, closed, points, width=1):
    _check_surface(surface)
    c_color = create_color(color, surface._format)
    points = _check_and_filter_points(points, 2)
    drawn_points = set()

    with locked(surface._c_surface):
        start_point = points[0]
        for point in points[1:]:
            drawn = _clip_and_draw_line_width(
                surface, c_color, width, start_point, point)
            if drawn is not None:
                drawn_points.add(drawn.topleft)
                drawn_points.add(drawn.bottomright)
            start_point = point

        if closed and len(points) > 2:
            _clip_and_draw_line_width(
                surface, c_color, width, points[-1], points[0])

    return _make_drawn_rect(drawn_points, surface)

def _draw_fillpoly(surface, points, c_color):
    # Very traditional scanline fill approach
    # (also the approach used by pygame)
    ys = [p[1] for p in points]
    miny = min(ys)
    maxy = max(ys)
    times = []
    # For speed reasons, we integrate clipping into the calculations,
    # rather than calling _clip_and_draw_line
    clip_rect = surface.get_clip()
    all_points = zip(points, points[-1:] + points[:-1])
    for y in range(miny, maxy + 1):
        if y < clip_rect.top or y >= clip_rect.bottom:
            continue
        intercepts = []
        for p1, p2 in all_points:
            if p1[1] == p2[1]:
                # Edge of the polygon, so skip (due to division by 0)
                continue
            elif p1[1] < p2[1]:
                x1, y1 = p1
                x2, y2 = p2
            else:
                x1, y1 = p2
                x2, y2 = p1

            if not (y1 <= y < y2) and not (y == maxy and y1 < y <= y2):
                continue
            # XXX: Here be dragons with very sharp teeth
            # C99 specifies truncates integer division towards zero always,
            # python integer division takes the floor, so they differ
            # on negatives
            numerator = (y - y1) * (x2 - x1)
            if numerator < 0:
                # N.B. order matters - force the postive division before
                # multiplication by -1
                x = -1 * (-numerator / (y2 - y1)) + x1
            else:
                x = numerator / (y2 - y1) + x1
            # This works because we're drawing horizontal lines
            if x < clip_rect.left:
                x = clip_rect.left
            elif x >= clip_rect.right:
                x = clip_rect.right - 1
            intercepts.append(x)
        intercepts.sort()
        for x1, x2 in zip(intercepts[::2], intercepts[1::2]):
            _drawline(surface, c_color, (x1, y), (x2, y))

def polygon(surface, color, points, width=0):
    _check_surface(surface)

    if width != 0:
        return lines(surface, color, 1, points, width)

    c_color = create_color(color, surface._format)
    points = _check_and_filter_points(points, 3)

    with locked(surface._c_surface):
        _draw_fillpoly(surface, points, c_color)

    return _make_drawn_rect(points, surface)

def rect(surface, color, rect, width=0):
    if not isinstance(surface, pygame.surface.Surface):
        raise TypeError("First argument must be a Surface.")

    rect = Rect(rect)
    l = rect.x
    r = rect.x + rect.w - 1
    t = rect.y
    b = rect.y + rect.h - 1

    points = ((l, t), (r, t), (r, b), (l, b))
    return polygon(surface, color, points, width)
<|endoftext|>


<commit_before>import sys
import re
import subprocess
import os.path

from fnmatch import filter as fnfilter
from os import walk, getcwd

from pygt.greptree import GrepTree, count_lines

def glob_recursive(ptrn):
    """Returns a list of paths under ./ that match a given glob pattern."""
    ptrn = ptrn[:-1] if ptrn[-1] == '/' else ptrn

    dir_matches = []
    file_matches = []
    for root, dirnames, filenames in walk(getcwd()):
        for dirname in fnfilter(dirnames, ptrn):
            dir_matches.append(os.path.relpath(os.path.join(root, dirname)))
        for filename in fnfilter(filenames, ptrn):
            file_matches.append(os.path.join(root, filename))

    return dir_matches, file_matches

def set_op(a_subtree, b_subtree, func1, func2):
    """Convienience function for performing a set operation on two sub trees."""
    # Using a closure as a counter is difficult so we'll sum a list instead
    count = []

    def _set_op(a_subtree, b_subtree, func1, func2):
        a_nodes = set(a_subtree.keys())
        b_nodes = set(b_subtree.keys())

        floor = {}
        for node in func1(a_nodes, b_nodes):
            if node == 'lines':
                a_set = set(tuple(z) for z in a_subtree.get(node, []))
                b_set = set(tuple(z) for z in b_subtree.get(node, []))

                temp = func2(a_set, b_set)
                count.append(len(temp))
                if temp != []:
                    floor[node] = temp

            else:
                a_branch = a_subtree.get(node, {})
                b_branch = b_subtree.get(node, {})

                if not a_branch and b_branch:
                    temp = a_branch if a_branch else b_branch
                    count.append(count_lines(temp))
                else:
                    temp = _set_op(a_branch, b_branch, func1, func2)

                if temp != {}:
                    floor[node] = temp

        return floor

    return _set_op(a_subtree, b_subtree, func1, func2), sum(count)

class BaseReader(object):
    """Base class only. Please subclass and implement the following:

    - FILE_PATTERNS : a list of file extensions to read.
    - TYPE : The name of the programming language this Reader pertains to
    - get_context() : Given a file and line number,
                        this should return the lines context."""

    GREP_TEMPLATE = 'grep ./ -Irne "%s"%s%s'
    INCLUDES_TEMPLATE = ' --include="%s"'
    EXCLUDES_TEMPLATE = ' --exclude-dir="%s" --exclude="%s"'

    # Things that should be defined by subclass
    FILE_PATTERNS = []
    TYPE = ''

    def __init__(self, config):
        self.tree = GrepTree()
        self.config = config
        self.debug = config.debug

    @classmethod
    def from_file(cls, config, path):
        """Create Reader and populate tree from file."""
        temp = cls(config)
        temp.tree = GrepTree.load_path(path)

        return temp

    @classmethod
    def from_grep(cls, config):
        """Create Reader and populate tree by grepping files."""
        temp = cls(config)
        temp.tree = temp.build_tree(config.search_term)

        return temp

    @classmethod
    def from_pipe(cls, config):
        """Create Reader and read tree from incomming pipe."""
        temp = cls(config)
        temp.tree = GrepTree.load(sys.stdin)

        return temp

    def build_tree(self, query):
        """Perform grep search and sort results into GrepTree."""
        # Grep for expresion
        results = self.grep_for(query)

        # Create a temp tree and add all results to tree
        tree = GrepTree()
        self.add_to_tree(results, tree)

        return tree

    # TODO: The methods below should print additional debug info of the comparison tree

    def union(self):
        """Perform union set operation against GrepTree piped in."""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a | b
        func2 = lambda a, b: list(a | b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def diff(self):
        """Perform XOR set operation against GrepTree piped in."""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a | b
        func2 = lambda a, b: list(a ^ b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def exclude(self):
        """Filter results piped in from those in current GrepTree"""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a
        func2 = lambda a, b: list(a - b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def inter(self):
        """Perform intersection set operation against GrepTree piped in."""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a & b
        func2 = lambda a, b: list(a & b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def _get_exclds(self):
        """Decide which file should be used to build list of paths to ignore."""
        if not self.config.no_ignore:
            return self.config.ignore_file

    def grep_for(self, exp):
        """
        Execute a grep command to search for the given expression.
        Then add each result to self.tree.
        """
        results = []
        exclds = self._get_exclds()
        try:
            response = subprocess.check_output(
                    [self._grep_cmd(exp, self.FILE_PATTERNS, exclds)],
                    shell=True
                    )
            results = response.splitlines()

            if self.debug:
                print "=== Grep results ==="
                print response, "Total results: %d\n" % len(results)
        except subprocess.CalledProcessError, e:
            if e.returncode == 1:
                print "Couldn't find anything matching '%s'" % exp
            else:
                print "Whoops, grep returned errorcode %d" % e.errorcode
            sys.exit()

        return results

    def add_to_tree(self, results, tree=None):
        """Take result and add it to current GrepTree."""
        if tree is None:
            tree = self.tree

        for row in results:
            file_name, file_line, _ = row.split(':')[:3]

            self.get_context(file_name, int(file_line), tree)

    def _grep_cmd(self, exp, file_patterns, exclude_from=None):
        """Build the grep command used to perform search."""
        excld_flags = ''
        if exclude_from:
            exclds = set()
            excld_dirs = set()
            with open(exclude_from, 'r') as inp:
                for row in inp:
                    dirs, files = glob_recursive(row.strip())
                    excld_dirs.update(dirs)
                    exclds.update(files)

            excld_dirs = '" --exclude-dir="'.join(excld_dirs)
            exclds = '" --exclude="'.join(exclds)

            excld_flags = self.EXCLUDES_TEMPLATE % (excld_dirs, exclds)

        inclds = ' '.join([self.INCLUDES_TEMPLATE % z for z in file_patterns])
        return self.GREP_TEMPLATE % (exp, excld_flags, inclds)

    def get_context(self, file_path, file_line, tree=None):
        """
        Given the file path and the line number, determine the context of that line.
        """
        raise NotImplementedError

class PythonReader(BaseReader):
    """An implementation of a Reader for Python code."""
    # CONSTANTS
    INDENT_RE = re.compile("^(\s*)")
    DEF_CLASS_RE = re.compile("^\s*(def|class) (.*?)[(:]")
    TAB = '\t'
    FOUR_SPACES = '    '
    FILE_PATTERNS = ['*.py']
    TYPE = 'Python'

    def _get_indent(self, line):
        """
        Returns the indentation on a line as a substring.
        """
        match = re.match(self.INDENT_RE, line)
        indent = match.group(1)

        return re.sub(self.TAB, self.FOUR_SPACES, indent)

    def get_context(self, file_path, file_line, tree=None):
        # Zero-based index for file line number
        file_indx = file_line - 1

        if tree is None:
            tree = self.tree

        # Create a branch in the tree for this file
        tree.touch(file_path)

        # Read in all lines up to and including the line given
        lines = []
        with open(file_path) as file_:
            for i, line in enumerate(file_):
                if i <= file_indx:
                    lines.append(line)
                else:
                    break
        assert len(lines) == file_line

        # Get indent of specified line
        init_indent = self._get_indent(lines[file_indx])

        results = []
        for line_no in range(file_indx-1, -1, -1):
            # Ignore empty lines
            if lines[line_no].strip():
                # Get indent of relevant lines
                next_indent = self._get_indent(lines[line_no])

                # if line has less indentation
                if len(next_indent) < len(init_indent):
                    # Ignore lines that aren't a function or a class
                    kw_match = re.search(self.DEF_CLASS_RE, lines[line_no])
                    if kw_match:
                        # add to results
                        results.append(
                            ' '.join(kw_match.groups())
                            )

                    # then change init_indent
                    init_indent = next_indent

        # Add this entry to context tree
        tree.append(
                file_path,
                file_line,
                lines[file_indx].strip('\n'),
                reversed(results)
                )
<commit_msg>@bugfix catch error if no .gitignore is found.<commit_after>import sys
import re
import subprocess
import os.path

from fnmatch import filter as fnfilter
from os import walk, getcwd

from pygt.greptree import GrepTree, count_lines

def glob_recursive(ptrn):
    """Returns a list of paths under ./ that match a given glob pattern."""
    ptrn = ptrn[:-1] if ptrn[-1] == '/' else ptrn

    dir_matches = []
    file_matches = []
    for root, dirnames, filenames in walk(getcwd()):
        for dirname in fnfilter(dirnames, ptrn):
            dir_matches.append(os.path.relpath(os.path.join(root, dirname)))
        for filename in fnfilter(filenames, ptrn):
            file_matches.append(os.path.join(root, filename))

    return dir_matches, file_matches

def set_op(a_subtree, b_subtree, func1, func2):
    """Convienience function for performing a set operation on two sub trees."""
    # Using a closure as a counter is difficult so we'll sum a list instead
    count = []

    def _set_op(a_subtree, b_subtree, func1, func2):
        a_nodes = set(a_subtree.keys())
        b_nodes = set(b_subtree.keys())

        floor = {}
        for node in func1(a_nodes, b_nodes):
            if node == 'lines':
                a_set = set(tuple(z) for z in a_subtree.get(node, []))
                b_set = set(tuple(z) for z in b_subtree.get(node, []))

                temp = func2(a_set, b_set)
                count.append(len(temp))
                if temp != []:
                    floor[node] = temp

            else:
                a_branch = a_subtree.get(node, {})
                b_branch = b_subtree.get(node, {})

                if not a_branch and b_branch:
                    temp = a_branch if a_branch else b_branch
                    count.append(count_lines(temp))
                else:
                    temp = _set_op(a_branch, b_branch, func1, func2)

                if temp != {}:
                    floor[node] = temp

        return floor

    return _set_op(a_subtree, b_subtree, func1, func2), sum(count)

class BaseReader(object):
    """Base class only. Please subclass and implement the following:

    - FILE_PATTERNS : a list of file extensions to read.
    - TYPE : The name of the programming language this Reader pertains to
    - get_context() : Given a file and line number,
                        this should return the lines context."""

    GREP_TEMPLATE = 'grep ./ -Irne "%s"%s%s'
    INCLUDES_TEMPLATE = ' --include="%s"'
    EXCLUDES_TEMPLATE = ' --exclude-dir="%s" --exclude="%s"'

    # Things that should be defined by subclass
    FILE_PATTERNS = []
    TYPE = ''

    def __init__(self, config):
        self.tree = GrepTree()
        self.config = config
        self.debug = config.debug

    @classmethod
    def from_file(cls, config, path):
        """Create Reader and populate tree from file."""
        temp = cls(config)
        temp.tree = GrepTree.load_path(path)

        return temp

    @classmethod
    def from_grep(cls, config):
        """Create Reader and populate tree by grepping files."""
        temp = cls(config)
        temp.tree = temp.build_tree(config.search_term)

        return temp

    @classmethod
    def from_pipe(cls, config):
        """Create Reader and read tree from incomming pipe."""
        temp = cls(config)
        temp.tree = GrepTree.load(sys.stdin)

        return temp

    def build_tree(self, query):
        """Perform grep search and sort results into GrepTree."""
        # Grep for expresion
        results = self.grep_for(query)

        # Create a temp tree and add all results to tree
        tree = GrepTree()
        self.add_to_tree(results, tree)

        return tree

    # TODO: The methods below should print additional debug info of the comparison tree

    def union(self):
        """Perform union set operation against GrepTree piped in."""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a | b
        func2 = lambda a, b: list(a | b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def diff(self):
        """Perform XOR set operation against GrepTree piped in."""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a | b
        func2 = lambda a, b: list(a ^ b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def exclude(self):
        """Filter results piped in from those in current GrepTree"""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a
        func2 = lambda a, b: list(a - b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def inter(self):
        """Perform intersection set operation against GrepTree piped in."""
        tree = self.build_tree(self.config.search_term)

        func1 = lambda a, b: a & b
        func2 = lambda a, b: list(a & b)

        self.tree.data, self.tree._count = set_op(
                self.tree.data,
                tree.data,
                func1,
                func2
                )

    def _get_exclds(self):
        """Decide which file should be used to build list of paths to ignore."""
        if not self.config.no_ignore:
            return self.config.ignore_file

    def grep_for(self, exp):
        """
        Execute a grep command to search for the given expression.
        Then add each result to self.tree.
        """
        results = []
        exclds = self._get_exclds()
        try:
            response = subprocess.check_output(
                    [self._grep_cmd(exp, self.FILE_PATTERNS, exclds)],
                    shell=True
                    )
            results = response.splitlines()

            if self.debug:
                print "=== Grep results ==="
                print response, "Total results: %d\n" % len(results)
        except subprocess.CalledProcessError, e:
            if e.returncode == 1:
                print "Couldn't find anything matching '%s'" % exp
            else:
                print "Whoops, grep returned errorcode %d" % e.errorcode
            sys.exit()

        return results

    def add_to_tree(self, results, tree=None):
        """Take result and add it to current GrepTree."""
        if tree is None:
            tree = self.tree

        for row in results:
            file_name, file_line, _ = row.split(':')[:3]

            self.get_context(file_name, int(file_line), tree)

    def _grep_cmd(self, exp, file_patterns, exclude_from=None):
        """Build the grep command used to perform search."""
        excld_flags = ''
        if exclude_from:
            exclds = set()
            excld_dirs = set()
            try:
                with open(exclude_from, 'r') as inp:
                    for row in inp:
                        dirs, files = glob_recursive(row.strip())
                        excld_dirs.update(dirs)
                        exclds.update(files)
            except IOError:
                excld_flags = ''
            else:
                excld_dirs = '" --exclude-dir="'.join(excld_dirs)
                exclds = '" --exclude="'.join(exclds)
                excld_flags = self.EXCLUDES_TEMPLATE % (excld_dirs, exclds)
            finally:
                inclds = ' '.join([self.INCLUDES_TEMPLATE % z for z in file_patterns])
                return self.GREP_TEMPLATE % (exp, excld_flags, inclds)

    def get_context(self, file_path, file_line, tree=None):
        """
        Given the file path and the line number, determine the context of that line.
        """
        raise NotImplementedError

class PythonReader(BaseReader):
    """An implementation of a Reader for Python code."""
    # CONSTANTS
    INDENT_RE = re.compile("^(\s*)")
    DEF_CLASS_RE = re.compile("^\s*(def|class) (.*?)[(:]")
    TAB = '\t'
    FOUR_SPACES = '    '
    FILE_PATTERNS = ['*.py']
    TYPE = 'Python'

    def _get_indent(self, line):
        """
        Returns the indentation on a line as a substring.
        """
        match = re.match(self.INDENT_RE, line)
        indent = match.group(1)

        return re.sub(self.TAB, self.FOUR_SPACES, indent)

    def get_context(self, file_path, file_line, tree=None):
        # Zero-based index for file line number
        file_indx = file_line - 1

        if tree is None:
            tree = self.tree

        # Create a branch in the tree for this file
        tree.touch(file_path)

        # Read in all lines up to and including the line given
        lines = []
        with open(file_path) as file_:
            for i, line in enumerate(file_):
                if i <= file_indx:
                    lines.append(line)
                else:
                    break
        assert len(lines) == file_line

        # Get indent of specified line
        init_indent = self._get_indent(lines[file_indx])

        results = []
        for line_no in range(file_indx-1, -1, -1):
            # Ignore empty lines
            if lines[line_no].strip():
                # Get indent of relevant lines
                next_indent = self._get_indent(lines[line_no])

                # if line has less indentation
                if len(next_indent) < len(init_indent):
                    # Ignore lines that aren't a function or a class
                    kw_match = re.search(self.DEF_CLASS_RE, lines[line_no])
                    if kw_match:
                        # add to results
                        results.append(
                            ' '.join(kw_match.groups())
                            )

                    # then change init_indent
                    init_indent = next_indent

        # Add this entry to context tree
        tree.append(
                file_path,
                file_line,
                lines[file_indx].strip('\n'),
                reversed(results)
                )
<|endoftext|>


<commit_before>from keras.callbacks import Callback

class LearningRateManager():
    def __init__(self, learning_rate, decay=0.1, step_epochs=None):
        self.decay = decay
        self.learning_rate = learning_rate
        self.step_epochs = step_epochs

    def schedule(self, epoch):
        if epoch in self.step_epochs:
            self.learning_rate = self.learning_rate * self.decay
        return self.learning_rate

class MultiGPUModelCheckpoint(Callback):
    def __init__(self, save_path, cpu_model):
        self.save_path = save_path
        self.cpu_model = cpu_model

    def on_epoch_end(self, epoch, logs=None):
        val_loss = logs['val_loss']
        self.cpu_model.save(self.save_path.format(epoch, val_loss))
<commit_msg>Added learning rate manager<commit_after>from keras.callbacks import Callback

class MultiGPUModelCheckpoint(Callback):
    def __init__(self, save_path, cpu_model):
        self.save_path = save_path
        self.cpu_model = cpu_model

    def on_epoch_end(self, epoch, logs=None):
        val_loss = logs['val_loss']
        self.cpu_model.save(self.save_path.format(epoch, val_loss))

class LearningRateManager():
    def __init__(self, learning_rate, gamma_decay, scheduled_epochs):
        self.learning_rate = learning_rate
        self.gamma_decay = gamma_decay
        self.scheduled_epochs = scheduled_epochs

    def schedule(self, epoch):
        if epoch in self.scheduled_epochs:
            self.learning_rate = self.learning_rate * self.gamma_decay
        return self.learning_rate
<|endoftext|>