<commit_before>from __future__ import unicode_literals
import pkg_resources
import binascii
import math
import msgpack
import random
import redis
import six
import string
import time
import uuid

__version__ = pkg_resources.require('asgi_redis')[0].version

class RedisChannelLayer(object):
    """
    ORM-backed channel environment. For development use only; it will span
    multiple processes fine, but it's going to be pretty bad at throughput.
    """

    blpop_timeout = 5

    def __init__(self, expiry=60, hosts=None, prefix="asgi:"):
        # Make sure they provided some hosts, or provide a default
        if not hosts:
            hosts = [("localhost", 6379)]
        self.hosts = []
        for entry in hosts:
            if isinstance(entry, six.string_types):
                self.hosts.append(entry)
            else:
                self.hosts.append("redis://%s:%d/0" % (entry[0],entry[1]))
        self.prefix = prefix
        assert isinstance(self.prefix, six.text_type), "Prefix must be unicode"
        self.expiry = expiry
        # Precalculate some values for ring selection
        self.ring_size = len(self.hosts)
        self.ring_divisor = int(math.ceil(4096 / float(self.ring_size)))
        # Create connections ahead of time (they won't call out just yet, but
        # we want to connection-pool them later)
        self._connection_list = [
            redis.Redis.from_url(host)
            for host in self.hosts
        ]
        # Register scripts
        connection = self.connection(None)
        self.lpopmany = connection.register_script(self.lua_lpopmany)

    ### ASGI API ###

    extensions = ["groups"]

    class MessageTooLarge(Exception):
        pass

    def send(self, channel, message):
        # Typecheck
        assert isinstance(message, dict), "message is not a dict"
        assert isinstance(channel, six.text_type), "%s is not unicode" % channel
        # Write out message into expiring key (avoids big items in list)
        # TODO: Use extended set, drop support for older redis?
        key = self.prefix + uuid.uuid4().hex
        # Pick a connection to the right server - consistent for response
        # channels, random for normal channels
        if "!" in channel:
            index = self.consistent_hash(channel)
            connection = self.connection(index)
        else:
            connection = self.connection(None)
        # Make a key for the message and set to expire
        connection.set(
            key,
            self.serialize(message),
        )
        connection.expire(
            key,
            self.expiry,
        )
        # Add key to list
        connection.rpush(
            self.prefix + channel,
            key,
        )
        # Set list to expire when message does (any later messages will bump this)
        connection.expire(
            self.prefix + channel,
            self.expiry + 10,
        )

    def receive_many(self, channels, block=False):
        if not channels:
            return None, None
        channels = list(channels)
        assert all(isinstance(channel, six.text_type) for channel in channels)
        # Work out what servers to listen on for the given channels
        indexes = {}
        random_index = self.random_index()
        for channel in channels:
            if "!" in channel:
                indexes.setdefault(self.consistent_hash(channel), []).append(channel)
            else:
                indexes.setdefault(random_index, []).append(channel)
        # Get a message from one of our channels
        while True:
            # Select a random connection to use
            index = random.choice(list(indexes.keys()))
            connection = self.connection(index)
            channels = indexes[index]
            # Shuffle channels to avoid the first ones starving others of workers
            random.shuffle(channels)
            # Pop off any waiting message
            list_names = [self.prefix + channel for channel in channels]
            if block:
                result = connection.blpop(list_names, timeout=self.blpop_timeout)
            else:
                result = self.lpopmany(keys=list_names)
            if result:
                content = connection.get(result[1])
                # If the content key expired, keep going.
                if content is None:
                    continue
                # Return the channel it's from and the message
                return result[0][len(self.prefix):].decode("utf8"), self.deserialize(content)
            else:
                return None, None

    def new_channel(self, pattern):
        assert isinstance(pattern, six.text_type)
        # Keep making channel names till one isn't present.
        while True:
            random_string = "".join(random.choice(string.ascii_letters) for i in range(12))
            assert pattern.endswith("!")
            new_name = pattern + random_string
            # Get right connection
            index = self.consistent_hash(new_name)
            connection = self.connection(index)
            # Check to see if it's in the connected Redis.
            # This fails to stop collisions for sharding where the channel is
            # non-single-listener, but that seems very unlikely.
            key = self.prefix + new_name
            if not connection.exists(key):
                return new_name

    ### ASGI Group extension ###

    def group_add(self, group, channel, expiry=None):
        """
        Adds the channel to the named group for at least 'expiry'
        seconds (expiry defaults to message expiry if not provided).
        """
        key = "%s:group:%s" % (self.prefix, group)
        key = key.encode("utf8")
        self.connection(self.consistent_hash(group)).zadd(
            key,
            **{channel: time.time() + (expiry or self.expiry)}
        )

    def group_discard(self, group, channel):
        """
        Removes the channel from the named group if it is in the group;
        does nothing otherwise (does not error)
        """
        key = "%s:group:%s" % (self.prefix, group)
        key = key.encode("utf8")
        self.connection(self.consistent_hash(group)).zrem(
            key,
            channel,
        )

    def send_group(self, group, message):
        """
        Sends a message to the entire group.
        """
        # TODO: More efficient implementation (lua script per shard?)
        for channel in self._group_channels(group):
            self.send(channel, message)

    def _group_key(self, group):
        return ("%s:group:%s" % (self.prefix, group)).encode("utf8")

    def _group_channels(self, group):
        """
        Returns an iterable of all channels in the group.
        """
        key = self._group_key(group)
        connection = self.connection(self.consistent_hash(group))
        # Return current lot
        return [x.decode("utf8") for x in connection.zrange(
            key,
            0,
            -1,
        )]

    ### Serialization ###

    def serialize(self, message):
        """
        Serializes message to a byte string.
        """
        return msgpack.packb(message, use_bin_type=True)

    def deserialize(self, message):
        """
        Deserializes from a byte string.
        """
        return msgpack.unpackb(message, encoding="utf8")

    ### Redis Lua scripts ###

    lua_lpopmany = """
        for keyCount = 1, #KEYS do
            local result = redis.call('LPOP', KEYS[keyCount])
            if result then
                return {KEYS[keyCount], result}
            end
        end
        return {nil, nil}
    """

    ### Internal functions ###

    def consistent_hash(self, value):
        """
        Maps the value to a node value between 0 and 4095
        using MD5, then down to one of the ring nodes.
        """
        if isinstance(value, six.text_type):
            value = value.encode("utf8")
        bigval = binascii.crc32(value) & 0xffffffff
        return (bigval // 0x100000) // self.ring_divisor

    def random_index(self):
        return random.randint(0, len(self.hosts) - 1)

    def connection(self, index):
        """
        Returns the correct connection for the current thread.

        Pass key to use a server based on consistent hashing of the key value;
        pass None to use a random server instead.
        """
        # If index is explicitly None, pick a random server
        if index is None:
            index = self.random_index()
        # Catch bad indexes
        if not 0 <= index < self.ring_size:
            raise ValueError("There are only %s hosts - you asked for %s!" % (self.ring_size, index))
        return self._connection_list[index]

    def __str__(self):
        return "%s(hosts=%s)" % (self.__class__.__name__, self.hosts)

<commit_msg>Add group expiry back properly, implement flush extension<commit_after>from __future__ import unicode_literals
import pkg_resources
import binascii
import math
import msgpack
import random
import redis
import six
import string
import time
import uuid

__version__ = pkg_resources.require('asgi_redis')[0].version

class RedisChannelLayer(object):
    """
    ORM-backed channel environment. For development use only; it will span
    multiple processes fine, but it's going to be pretty bad at throughput.
    """

    blpop_timeout = 5

    def __init__(self, expiry=60, hosts=None, prefix="asgi:", group_expiry=86400):
        # Make sure they provided some hosts, or provide a default
        if not hosts:
            hosts = [("localhost", 6379)]
        self.hosts = []
        for entry in hosts:
            if isinstance(entry, six.string_types):
                self.hosts.append(entry)
            else:
                self.hosts.append("redis://%s:%d/0" % (entry[0],entry[1]))
        self.prefix = prefix
        assert isinstance(self.prefix, six.text_type), "Prefix must be unicode"
        self.expiry = expiry
        self.group_expiry = group_expiry
        # Precalculate some values for ring selection
        self.ring_size = len(self.hosts)
        self.ring_divisor = int(math.ceil(4096 / float(self.ring_size)))
        # Create connections ahead of time (they won't call out just yet, but
        # we want to connection-pool them later)
        self._connection_list = [
            redis.Redis.from_url(host)
            for host in self.hosts
        ]
        # Register scripts
        connection = self.connection(None)
        self.lpopmany = connection.register_script(self.lua_lpopmany)
        self.delprefix = connection.register_script(self.lua_delprefix)

    ### ASGI API ###

    extensions = ["groups", "flush"]

    class MessageTooLarge(Exception):
        pass

    def send(self, channel, message):
        # Typecheck
        assert isinstance(message, dict), "message is not a dict"
        assert isinstance(channel, six.text_type), "%s is not unicode" % channel
        # Write out message into expiring key (avoids big items in list)
        # TODO: Use extended set, drop support for older redis?
        key = self.prefix + uuid.uuid4().hex
        # Pick a connection to the right server - consistent for response
        # channels, random for normal channels
        if "!" in channel:
            index = self.consistent_hash(channel)
            connection = self.connection(index)
        else:
            connection = self.connection(None)
        # Make a key for the message and set to expire
        connection.set(
            key,
            self.serialize(message),
        )
        connection.expire(
            key,
            self.expiry,
        )
        # Add key to list
        connection.rpush(
            self.prefix + channel,
            key,
        )
        # Set list to expire when message does (any later messages will bump this)
        connection.expire(
            self.prefix + channel,
            self.expiry + 10,
        )

    def receive_many(self, channels, block=False):
        if not channels:
            return None, None
        channels = list(channels)
        assert all(isinstance(channel, six.text_type) for channel in channels)
        # Work out what servers to listen on for the given channels
        indexes = {}
        random_index = self.random_index()
        for channel in channels:
            if "!" in channel:
                indexes.setdefault(self.consistent_hash(channel), []).append(channel)
            else:
                indexes.setdefault(random_index, []).append(channel)
        # Get a message from one of our channels
        while True:
            # Select a random connection to use
            index = random.choice(list(indexes.keys()))
            connection = self.connection(index)
            channels = indexes[index]
            # Shuffle channels to avoid the first ones starving others of workers
            random.shuffle(channels)
            # Pop off any waiting message
            list_names = [self.prefix + channel for channel in channels]
            if block:
                result = connection.blpop(list_names, timeout=self.blpop_timeout)
            else:
                result = self.lpopmany(keys=list_names, client=connection)
            if result:
                content = connection.get(result[1])
                # If the content key expired, keep going.
                if content is None:
                    continue
                # Return the channel it's from and the message
                return result[0][len(self.prefix):].decode("utf8"), self.deserialize(content)
            else:
                return None, None

    def new_channel(self, pattern):
        assert isinstance(pattern, six.text_type)
        # Keep making channel names till one isn't present.
        while True:
            random_string = "".join(random.choice(string.ascii_letters) for i in range(12))
            assert pattern.endswith("!")
            new_name = pattern + random_string
            # Get right connection
            index = self.consistent_hash(new_name)
            connection = self.connection(index)
            # Check to see if it's in the connected Redis.
            # This fails to stop collisions for sharding where the channel is
            # non-single-listener, but that seems very unlikely.
            key = self.prefix + new_name
            if not connection.exists(key):
                return new_name

    ### ASGI Group extension ###

    def group_add(self, group, channel):
        """
        Adds the channel to the named group for at least 'expiry'
        seconds (expiry defaults to message expiry if not provided).
        """
        key = "%s:group:%s" % (self.prefix, group)
        key = key.encode("utf8")
        self.connection(self.consistent_hash(group)).zadd(
            key,
            **{channel: time.time()}
        )

    def group_discard(self, group, channel):
        """
        Removes the channel from the named group if it is in the group;
        does nothing otherwise (does not error)
        """
        key = "%s:group:%s" % (self.prefix, group)
        key = key.encode("utf8")
        self.connection(self.consistent_hash(group)).zrem(
            key,
            channel,
        )

    def send_group(self, group, message):
        """
        Sends a message to the entire group.
        """
        # TODO: More efficient implementation (lua script per shard?)
        for channel in self._group_channels(group):
            self.send(channel, message)

    def _group_key(self, group):
        return ("%s:group:%s" % (self.prefix, group)).encode("utf8")

    def _group_channels(self, group):
        """
        Returns an iterable of all channels in the group.
        """
        key = self._group_key(group)
        connection = self.connection(self.consistent_hash(group))
        # Discard old channels based on group_expiry
        connection.zremrangebyscore(key, 0, int(time.time()) - self.group_expiry)
        # Return current lot
        return [x.decode("utf8") for x in connection.zrange(
            key,
            0,
            -1,
        )]

    ### Flush extension ###

    def flush(self):
        """
        Deletes all messages and groups on all shards.
        """
        for connection in self._connection_list:
            self.delprefix(keys=[], args=[self.prefix+"*"], client=connection)

    ### Serialization ###

    def serialize(self, message):
        """
        Serializes message to a byte string.
        """
        return msgpack.packb(message, use_bin_type=True)

    def deserialize(self, message):
        """
        Deserializes from a byte string.
        """
        return msgpack.unpackb(message, encoding="utf8")

    ### Redis Lua scripts ###

    lua_lpopmany = """
        for keyCount = 1, #KEYS do
            local result = redis.call('LPOP', KEYS[keyCount])
            if result then
                return {KEYS[keyCount], result}
            end
        end
        return {nil, nil}
    """

    lua_delprefix = """
        local keys = redis.call('keys', ARGV[1])
        for i=1,#keys,5000 do
            redis.call('del', unpack(keys, i, math.min(i+4999, #keys)))
        end
    """

    ### Internal functions ###

    def consistent_hash(self, value):
        """
        Maps the value to a node value between 0 and 4095
        using MD5, then down to one of the ring nodes.
        """
        if isinstance(value, six.text_type):
            value = value.encode("utf8")
        bigval = binascii.crc32(value) & 0xffffffff
        return (bigval // 0x100000) // self.ring_divisor

    def random_index(self):
        return random.randint(0, len(self.hosts) - 1)

    def connection(self, index):
        """
        Returns the correct connection for the current thread.

        Pass key to use a server based on consistent hashing of the key value;
        pass None to use a random server instead.
        """
        # If index is explicitly None, pick a random server
        if index is None:
            index = self.random_index()
        # Catch bad indexes
        if not 0 <= index < self.ring_size:
            raise ValueError("There are only %s hosts - you asked for %s!" % (self.ring_size, index))
        return self._connection_list[index]

    def __str__(self):
        return "%s(hosts=%s)" % (self.__class__.__name__, self.hosts)

<|endoftext|>


<commit_before>"""Config flow for HERE Travel Time integration."""
from __future__ import annotations

import logging
from typing import Any

from herepy import HEREError, InvalidCredentialsError, RouteMode, RoutingApi
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import (
    CONF_API_KEY,
    CONF_ENTITY_NAMESPACE,
    CONF_LATITUDE,
    CONF_LONGITUDE,
    CONF_MODE,
    CONF_NAME,
    CONF_UNIT_SYSTEM,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.selector import (
    EntitySelector,
    LocationSelector,
    TimeSelector,
    selector,
)

from .const import (
    CONF_ARRIVAL,
    CONF_ARRIVAL_TIME,
    CONF_DEPARTURE,
    CONF_DEPARTURE_TIME,
    CONF_DESTINATION,
    CONF_ORIGIN,
    CONF_ROUTE_MODE,
    CONF_TRAFFIC_MODE,
    DEFAULT_NAME,
    DOMAIN,
    ROUTE_MODE_FASTEST,
    ROUTE_MODES,
    TRAFFIC_MODE_DISABLED,
    TRAFFIC_MODE_ENABLED,
    TRAFFIC_MODES,
    TRAVEL_MODE_CAR,
    TRAVEL_MODE_PUBLIC_TIME_TABLE,
    TRAVEL_MODES,
    UNITS,
)
from .sensor import (
    CONF_DESTINATION_ENTITY_ID,
    CONF_DESTINATION_LATITUDE,
    CONF_DESTINATION_LONGITUDE,
    CONF_ORIGIN_ENTITY_ID,
    CONF_ORIGIN_LATITUDE,
    CONF_ORIGIN_LONGITUDE,
)

_LOGGER = logging.getLogger(__name__)

def is_dupe_import(
    entry: config_entries.ConfigEntry,
    user_input: dict[str, Any],
    options: dict[str, Any],
) -> bool:
    """Return whether imported config already exists."""
    # Check the main data keys
    if any(
        user_input[key] != entry.data[key]
        for key in (CONF_API_KEY, CONF_MODE, CONF_NAME)
    ):
        return False

    # Check origin/destination
    for key in (
        CONF_DESTINATION_LATITUDE,
        CONF_DESTINATION_LONGITUDE,
        CONF_ORIGIN_LATITUDE,
        CONF_ORIGIN_LONGITUDE,
        CONF_DESTINATION_ENTITY_ID,
        CONF_ORIGIN_ENTITY_ID,
    ):
        if user_input.get(key) != entry.data.get(key):
            return False

    # We have to check for options that don't have defaults
    for key in (
        CONF_TRAFFIC_MODE,
        CONF_UNIT_SYSTEM,
        CONF_ROUTE_MODE,
        CONF_ARRIVAL_TIME,
        CONF_DEPARTURE_TIME,
    ):
        if options.get(key) != entry.options.get(key):
            return False

    return True

def validate_api_key(api_key: str) -> None:
    """Validate the user input allows us to connect."""
    known_working_origin = [38.9, -77.04833]
    known_working_destination = [39.0, -77.1]
    RoutingApi(api_key).public_transport_timetable(
        known_working_origin,
        known_working_destination,
        True,
        [
            RouteMode[ROUTE_MODE_FASTEST],
            RouteMode[TRAVEL_MODE_CAR],
            RouteMode[TRAFFIC_MODE_ENABLED],
        ],
        arrival=None,
        departure="now",
    )

def get_user_step_schema(data: dict[str, Any]) -> vol.Schema:
    """Get a populated schema or default."""
    return vol.Schema(
        {
            vol.Optional(
                CONF_NAME, default=data.get(CONF_NAME, DEFAULT_NAME)
            ): cv.string,
            vol.Required(CONF_API_KEY, default=data.get(CONF_API_KEY)): cv.string,
            vol.Optional(
                CONF_MODE, default=data.get(CONF_MODE, TRAVEL_MODE_CAR)
            ): vol.In(TRAVEL_MODES),
        }
    )

def default_options(hass: HomeAssistant) -> dict[str, str | None]:
    """Get the default options."""
    return {
        CONF_TRAFFIC_MODE: TRAFFIC_MODE_ENABLED,
        CONF_ROUTE_MODE: ROUTE_MODE_FASTEST,
        CONF_ARRIVAL_TIME: None,
        CONF_DEPARTURE_TIME: None,
        CONF_UNIT_SYSTEM: hass.config.units.name,
    }

class HERETravelTimeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """Handle a config flow for HERE Travel Time."""

    VERSION = 1

    def __init__(self) -> None:
        """Init Config Flow."""
        self._config: dict[str, Any] = {}

    @staticmethod
    @callback
    def async_get_options_flow(
        config_entry: config_entries.ConfigEntry,
    ) -> HERETravelTimeOptionsFlow:
        """Get the options flow."""
        return HERETravelTimeOptionsFlow(config_entry)

    async def async_step_user(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Handle the initial step."""
        errors = {}
        user_input = user_input or {}
        if user_input:
            try:
                await self.hass.async_add_executor_job(
                    validate_api_key, user_input[CONF_API_KEY]
                )
            except InvalidCredentialsError:
                errors["base"] = "invalid_auth"
            except HEREError as error:
                _LOGGER.exception("Unexpected exception: %s", error)
                errors["base"] = "unknown"
            if not errors:
                self._config = user_input
                return self.async_show_menu(
                    step_id="origin_menu",
                    menu_options=["origin_coordinates", "origin_entity"],
                )
        return self.async_show_form(
            step_id="user", data_schema=get_user_step_schema(user_input), errors=errors
        )

    async def async_step_origin_coordinates(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure origin by using gps coordinates."""
        if user_input is not None:
            self._config[CONF_ORIGIN_LATITUDE] = user_input[CONF_ORIGIN][CONF_LATITUDE]
            self._config[CONF_ORIGIN_LONGITUDE] = user_input[CONF_ORIGIN][
                CONF_LONGITUDE
            ]
            return self.async_show_menu(
                step_id="destination_menu",
                menu_options=["destination_coordinates", "destination_entity"],
            )
        schema = vol.Schema(
            {
                vol.Required(
                    CONF_ORIGIN,
                    default={
                        CONF_LATITUDE: self.hass.config.latitude,
                        CONF_LONGITUDE: self.hass.config.longitude,
                    },
                ): LocationSelector()
            }
        )
        return self.async_show_form(step_id="origin_coordinates", data_schema=schema)

    async def async_step_origin_entity(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure origin by using an entity."""
        if user_input is not None:
            self._config[CONF_ORIGIN_ENTITY_ID] = user_input[CONF_ORIGIN_ENTITY_ID]
            return self.async_show_menu(
                step_id="destination_menu",
                menu_options=["destination_coordinates", "destination_entity"],
            )
        schema = vol.Schema({vol.Required(CONF_ORIGIN_ENTITY_ID): EntitySelector()})
        return self.async_show_form(step_id="origin_entity", data_schema=schema)

    async def async_step_destination_coordinates(
        self,
        user_input: dict[str, Any] | None = None,
    ) -> FlowResult:
        """Configure destination by using gps coordinates."""
        if user_input is not None:
            self._config[CONF_DESTINATION_LATITUDE] = user_input[CONF_DESTINATION][
                CONF_LATITUDE
            ]
            self._config[CONF_DESTINATION_LONGITUDE] = user_input[CONF_DESTINATION][
                CONF_LONGITUDE
            ]
            return self.async_create_entry(
                title=self._config[CONF_NAME],
                data=self._config,
                options=default_options(self.hass),
            )
        schema = vol.Schema(
            {
                vol.Required(
                    CONF_DESTINATION,
                    default={
                        CONF_LATITUDE: self.hass.config.latitude,
                        CONF_LONGITUDE: self.hass.config.longitude,
                    },
                ): LocationSelector()
            }
        )
        return self.async_show_form(
            step_id="destination_coordinates", data_schema=schema
        )

    async def async_step_destination_entity(
        self,
        user_input: dict[str, Any] | None = None,
    ) -> FlowResult:
        """Configure destination by using an entity."""
        if user_input is not None:
            self._config[CONF_DESTINATION_ENTITY_ID] = user_input[
                CONF_DESTINATION_ENTITY_ID
            ]
            return self.async_create_entry(
                title=self._config[CONF_NAME],
                data=self._config,
                options=default_options(self.hass),
            )
        schema = vol.Schema(
            {vol.Required(CONF_DESTINATION_ENTITY_ID): EntitySelector()}
        )
        return self.async_show_form(step_id="destination_entity", data_schema=schema)

    async def async_step_import(self, user_input: dict[str, Any]) -> FlowResult:
        """Import from configuration.yaml."""
        options: dict[str, Any] = {}
        user_input, options = self._transform_import_input(user_input)
        # We need to prevent duplicate imports
        if any(
            is_dupe_import(entry, user_input, options)
            for entry in self.hass.config_entries.async_entries(DOMAIN)
            if entry.source == config_entries.SOURCE_IMPORT
        ):
            return self.async_abort(reason="already_configured")
        return self.async_create_entry(
            title=user_input[CONF_NAME], data=user_input, options=options
        )

    def _transform_import_input(
        self, import_input: dict[str, Any]
    ) -> tuple[dict[str, Any], dict[str, Any]]:
        """Transform platform schema input to new model."""
        options: dict[str, Any] = {}
        user_input: dict[str, Any] = {}

        if import_input.get(CONF_ORIGIN_LATITUDE) is not None:
            user_input[CONF_ORIGIN_LATITUDE] = import_input[CONF_ORIGIN_LATITUDE]
            user_input[CONF_ORIGIN_LONGITUDE] = import_input[CONF_ORIGIN_LONGITUDE]
        else:
            user_input[CONF_ORIGIN_ENTITY_ID] = import_input[CONF_ORIGIN_ENTITY_ID]

        if import_input.get(CONF_DESTINATION_LATITUDE) is not None:
            user_input[CONF_DESTINATION_LATITUDE] = import_input[
                CONF_DESTINATION_LATITUDE
            ]
            user_input[CONF_DESTINATION_LONGITUDE] = import_input[
                CONF_DESTINATION_LONGITUDE
            ]
        else:
            user_input[CONF_DESTINATION_ENTITY_ID] = import_input[
                CONF_DESTINATION_ENTITY_ID
            ]

        user_input[CONF_API_KEY] = import_input[CONF_API_KEY]
        user_input[CONF_MODE] = import_input[CONF_MODE]
        user_input[CONF_NAME] = import_input[CONF_NAME]
        if (namespace := import_input.get(CONF_ENTITY_NAMESPACE)) is not None:
            user_input[CONF_NAME] = f"{namespace} {user_input[CONF_NAME]}"

        options[CONF_TRAFFIC_MODE] = (
            TRAFFIC_MODE_ENABLED
            if import_input.get(CONF_TRAFFIC_MODE, False)
            else TRAFFIC_MODE_DISABLED
        )
        options[CONF_ROUTE_MODE] = import_input.get(CONF_ROUTE_MODE)
        options[CONF_UNIT_SYSTEM] = import_input.get(
            CONF_UNIT_SYSTEM, self.hass.config.units.name
        )
        options[CONF_ARRIVAL_TIME] = import_input.get(CONF_ARRIVAL, None)
        options[CONF_DEPARTURE_TIME] = import_input.get(CONF_DEPARTURE, None)

        return user_input, options

class HERETravelTimeOptionsFlow(config_entries.OptionsFlow):
    """Handle HERE Travel Time options."""

    def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
        """Initialize HERE Travel Time options flow."""
        self.config_entry = config_entry
        self._config: dict[str, Any] = {}

    async def async_step_init(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Manage the HERE Travel Time options."""
        if user_input is not None:
            self._config = user_input
            if self.config_entry.data[CONF_MODE] == TRAVEL_MODE_PUBLIC_TIME_TABLE:
                return self.async_show_menu(
                    step_id="time_menu",
                    menu_options=["departure_time", "arrival_time", "no_time"],
                )
            return self.async_show_menu(
                step_id="time_menu",
                menu_options=["departure_time", "no_time"],
            )

        options = {
            vol.Optional(
                CONF_TRAFFIC_MODE,
                default=self.config_entry.options.get(
                    CONF_TRAFFIC_MODE, TRAFFIC_MODE_ENABLED
                ),
            ): vol.In(TRAFFIC_MODES),
            vol.Optional(
                CONF_ROUTE_MODE,
                default=self.config_entry.options.get(
                    CONF_ROUTE_MODE, ROUTE_MODE_FASTEST
                ),
            ): vol.In(ROUTE_MODES),
            vol.Optional(
                CONF_UNIT_SYSTEM,
                default=self.config_entry.options.get(
                    CONF_UNIT_SYSTEM, self.hass.config.units.name
                ),
            ): vol.In(UNITS),
        }

        return self.async_show_form(step_id="init", data_schema=vol.Schema(options))

    async def async_step_no_time(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Create Options Entry."""
        return self.async_create_entry(title="", data=self._config)

    async def async_step_arrival_time(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure arrival time."""
        if user_input is not None:
            self._config[CONF_ARRIVAL_TIME] = user_input[CONF_ARRIVAL_TIME]
            return self.async_create_entry(title="", data=self._config)

        options = {"arrival_time": selector({TimeSelector.selector_type: {}})}

        return self.async_show_form(
            step_id="arrival_time", data_schema=vol.Schema(options)
        )

    async def async_step_departure_time(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure departure time."""
        if user_input is not None:
            self._config[CONF_DEPARTURE_TIME] = user_input[CONF_DEPARTURE_TIME]
            return self.async_create_entry(title="", data=self._config)

        options = {"departure_time": selector({TimeSelector.selector_type: {}})}

        return self.async_show_form(
            step_id="departure_time", data_schema=vol.Schema(options)
        )
<commit_msg>Required option_flow values for here_travel_time (#77651)<commit_after>"""Config flow for HERE Travel Time integration."""
from __future__ import annotations

import logging
from typing import Any

from herepy import HEREError, InvalidCredentialsError, RouteMode, RoutingApi
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import (
    CONF_API_KEY,
    CONF_ENTITY_NAMESPACE,
    CONF_LATITUDE,
    CONF_LONGITUDE,
    CONF_MODE,
    CONF_NAME,
    CONF_UNIT_SYSTEM,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.selector import (
    EntitySelector,
    LocationSelector,
    TimeSelector,
)

from .const import (
    CONF_ARRIVAL,
    CONF_ARRIVAL_TIME,
    CONF_DEPARTURE,
    CONF_DEPARTURE_TIME,
    CONF_DESTINATION,
    CONF_ORIGIN,
    CONF_ROUTE_MODE,
    CONF_TRAFFIC_MODE,
    DEFAULT_NAME,
    DOMAIN,
    ROUTE_MODE_FASTEST,
    ROUTE_MODES,
    TRAFFIC_MODE_DISABLED,
    TRAFFIC_MODE_ENABLED,
    TRAFFIC_MODES,
    TRAVEL_MODE_CAR,
    TRAVEL_MODE_PUBLIC_TIME_TABLE,
    TRAVEL_MODES,
    UNITS,
)
from .sensor import (
    CONF_DESTINATION_ENTITY_ID,
    CONF_DESTINATION_LATITUDE,
    CONF_DESTINATION_LONGITUDE,
    CONF_ORIGIN_ENTITY_ID,
    CONF_ORIGIN_LATITUDE,
    CONF_ORIGIN_LONGITUDE,
)

_LOGGER = logging.getLogger(__name__)

def is_dupe_import(
    entry: config_entries.ConfigEntry,
    user_input: dict[str, Any],
    options: dict[str, Any],
) -> bool:
    """Return whether imported config already exists."""
    # Check the main data keys
    if any(
        user_input[key] != entry.data[key]
        for key in (CONF_API_KEY, CONF_MODE, CONF_NAME)
    ):
        return False

    # Check origin/destination
    for key in (
        CONF_DESTINATION_LATITUDE,
        CONF_DESTINATION_LONGITUDE,
        CONF_ORIGIN_LATITUDE,
        CONF_ORIGIN_LONGITUDE,
        CONF_DESTINATION_ENTITY_ID,
        CONF_ORIGIN_ENTITY_ID,
    ):
        if user_input.get(key) != entry.data.get(key):
            return False

    # We have to check for options that don't have defaults
    for key in (
        CONF_TRAFFIC_MODE,
        CONF_UNIT_SYSTEM,
        CONF_ROUTE_MODE,
        CONF_ARRIVAL_TIME,
        CONF_DEPARTURE_TIME,
    ):
        if options.get(key) != entry.options.get(key):
            return False

    return True

def validate_api_key(api_key: str) -> None:
    """Validate the user input allows us to connect."""
    known_working_origin = [38.9, -77.04833]
    known_working_destination = [39.0, -77.1]
    RoutingApi(api_key).public_transport_timetable(
        known_working_origin,
        known_working_destination,
        True,
        [
            RouteMode[ROUTE_MODE_FASTEST],
            RouteMode[TRAVEL_MODE_CAR],
            RouteMode[TRAFFIC_MODE_ENABLED],
        ],
        arrival=None,
        departure="now",
    )

def get_user_step_schema(data: dict[str, Any]) -> vol.Schema:
    """Get a populated schema or default."""
    return vol.Schema(
        {
            vol.Optional(
                CONF_NAME, default=data.get(CONF_NAME, DEFAULT_NAME)
            ): cv.string,
            vol.Required(CONF_API_KEY, default=data.get(CONF_API_KEY)): cv.string,
            vol.Optional(
                CONF_MODE, default=data.get(CONF_MODE, TRAVEL_MODE_CAR)
            ): vol.In(TRAVEL_MODES),
        }
    )

def default_options(hass: HomeAssistant) -> dict[str, str | None]:
    """Get the default options."""
    return {
        CONF_TRAFFIC_MODE: TRAFFIC_MODE_ENABLED,
        CONF_ROUTE_MODE: ROUTE_MODE_FASTEST,
        CONF_ARRIVAL_TIME: None,
        CONF_DEPARTURE_TIME: None,
        CONF_UNIT_SYSTEM: hass.config.units.name,
    }

class HERETravelTimeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """Handle a config flow for HERE Travel Time."""

    VERSION = 1

    def __init__(self) -> None:
        """Init Config Flow."""
        self._config: dict[str, Any] = {}

    @staticmethod
    @callback
    def async_get_options_flow(
        config_entry: config_entries.ConfigEntry,
    ) -> HERETravelTimeOptionsFlow:
        """Get the options flow."""
        return HERETravelTimeOptionsFlow(config_entry)

    async def async_step_user(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Handle the initial step."""
        errors = {}
        user_input = user_input or {}
        if user_input:
            try:
                await self.hass.async_add_executor_job(
                    validate_api_key, user_input[CONF_API_KEY]
                )
            except InvalidCredentialsError:
                errors["base"] = "invalid_auth"
            except HEREError as error:
                _LOGGER.exception("Unexpected exception: %s", error)
                errors["base"] = "unknown"
            if not errors:
                self._config = user_input
                return self.async_show_menu(
                    step_id="origin_menu",
                    menu_options=["origin_coordinates", "origin_entity"],
                )
        return self.async_show_form(
            step_id="user", data_schema=get_user_step_schema(user_input), errors=errors
        )

    async def async_step_origin_coordinates(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure origin by using gps coordinates."""
        if user_input is not None:
            self._config[CONF_ORIGIN_LATITUDE] = user_input[CONF_ORIGIN][CONF_LATITUDE]
            self._config[CONF_ORIGIN_LONGITUDE] = user_input[CONF_ORIGIN][
                CONF_LONGITUDE
            ]
            return self.async_show_menu(
                step_id="destination_menu",
                menu_options=["destination_coordinates", "destination_entity"],
            )
        schema = vol.Schema(
            {
                vol.Required(
                    CONF_ORIGIN,
                    default={
                        CONF_LATITUDE: self.hass.config.latitude,
                        CONF_LONGITUDE: self.hass.config.longitude,
                    },
                ): LocationSelector()
            }
        )
        return self.async_show_form(step_id="origin_coordinates", data_schema=schema)

    async def async_step_origin_entity(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure origin by using an entity."""
        if user_input is not None:
            self._config[CONF_ORIGIN_ENTITY_ID] = user_input[CONF_ORIGIN_ENTITY_ID]
            return self.async_show_menu(
                step_id="destination_menu",
                menu_options=["destination_coordinates", "destination_entity"],
            )
        schema = vol.Schema({vol.Required(CONF_ORIGIN_ENTITY_ID): EntitySelector()})
        return self.async_show_form(step_id="origin_entity", data_schema=schema)

    async def async_step_destination_coordinates(
        self,
        user_input: dict[str, Any] | None = None,
    ) -> FlowResult:
        """Configure destination by using gps coordinates."""
        if user_input is not None:
            self._config[CONF_DESTINATION_LATITUDE] = user_input[CONF_DESTINATION][
                CONF_LATITUDE
            ]
            self._config[CONF_DESTINATION_LONGITUDE] = user_input[CONF_DESTINATION][
                CONF_LONGITUDE
            ]
            return self.async_create_entry(
                title=self._config[CONF_NAME],
                data=self._config,
                options=default_options(self.hass),
            )
        schema = vol.Schema(
            {
                vol.Required(
                    CONF_DESTINATION,
                    default={
                        CONF_LATITUDE: self.hass.config.latitude,
                        CONF_LONGITUDE: self.hass.config.longitude,
                    },
                ): LocationSelector()
            }
        )
        return self.async_show_form(
            step_id="destination_coordinates", data_schema=schema
        )

    async def async_step_destination_entity(
        self,
        user_input: dict[str, Any] | None = None,
    ) -> FlowResult:
        """Configure destination by using an entity."""
        if user_input is not None:
            self._config[CONF_DESTINATION_ENTITY_ID] = user_input[
                CONF_DESTINATION_ENTITY_ID
            ]
            return self.async_create_entry(
                title=self._config[CONF_NAME],
                data=self._config,
                options=default_options(self.hass),
            )
        schema = vol.Schema(
            {vol.Required(CONF_DESTINATION_ENTITY_ID): EntitySelector()}
        )
        return self.async_show_form(step_id="destination_entity", data_schema=schema)

    async def async_step_import(self, user_input: dict[str, Any]) -> FlowResult:
        """Import from configuration.yaml."""
        options: dict[str, Any] = {}
        user_input, options = self._transform_import_input(user_input)
        # We need to prevent duplicate imports
        if any(
            is_dupe_import(entry, user_input, options)
            for entry in self.hass.config_entries.async_entries(DOMAIN)
            if entry.source == config_entries.SOURCE_IMPORT
        ):
            return self.async_abort(reason="already_configured")
        return self.async_create_entry(
            title=user_input[CONF_NAME], data=user_input, options=options
        )

    def _transform_import_input(
        self, import_input: dict[str, Any]
    ) -> tuple[dict[str, Any], dict[str, Any]]:
        """Transform platform schema input to new model."""
        options: dict[str, Any] = {}
        user_input: dict[str, Any] = {}

        if import_input.get(CONF_ORIGIN_LATITUDE) is not None:
            user_input[CONF_ORIGIN_LATITUDE] = import_input[CONF_ORIGIN_LATITUDE]
            user_input[CONF_ORIGIN_LONGITUDE] = import_input[CONF_ORIGIN_LONGITUDE]
        else:
            user_input[CONF_ORIGIN_ENTITY_ID] = import_input[CONF_ORIGIN_ENTITY_ID]

        if import_input.get(CONF_DESTINATION_LATITUDE) is not None:
            user_input[CONF_DESTINATION_LATITUDE] = import_input[
                CONF_DESTINATION_LATITUDE
            ]
            user_input[CONF_DESTINATION_LONGITUDE] = import_input[
                CONF_DESTINATION_LONGITUDE
            ]
        else:
            user_input[CONF_DESTINATION_ENTITY_ID] = import_input[
                CONF_DESTINATION_ENTITY_ID
            ]

        user_input[CONF_API_KEY] = import_input[CONF_API_KEY]
        user_input[CONF_MODE] = import_input[CONF_MODE]
        user_input[CONF_NAME] = import_input[CONF_NAME]
        if (namespace := import_input.get(CONF_ENTITY_NAMESPACE)) is not None:
            user_input[CONF_NAME] = f"{namespace} {user_input[CONF_NAME]}"

        options[CONF_TRAFFIC_MODE] = (
            TRAFFIC_MODE_ENABLED
            if import_input.get(CONF_TRAFFIC_MODE, False)
            else TRAFFIC_MODE_DISABLED
        )
        options[CONF_ROUTE_MODE] = import_input.get(CONF_ROUTE_MODE)
        options[CONF_UNIT_SYSTEM] = import_input.get(
            CONF_UNIT_SYSTEM, self.hass.config.units.name
        )
        options[CONF_ARRIVAL_TIME] = import_input.get(CONF_ARRIVAL, None)
        options[CONF_DEPARTURE_TIME] = import_input.get(CONF_DEPARTURE, None)

        return user_input, options

class HERETravelTimeOptionsFlow(config_entries.OptionsFlow):
    """Handle HERE Travel Time options."""

    def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
        """Initialize HERE Travel Time options flow."""
        self.config_entry = config_entry
        self._config: dict[str, Any] = {}

    async def async_step_init(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Manage the HERE Travel Time options."""
        if user_input is not None:
            self._config = user_input
            if self.config_entry.data[CONF_MODE] == TRAVEL_MODE_PUBLIC_TIME_TABLE:
                return self.async_show_menu(
                    step_id="time_menu",
                    menu_options=["departure_time", "arrival_time", "no_time"],
                )
            return self.async_show_menu(
                step_id="time_menu",
                menu_options=["departure_time", "no_time"],
            )

        schema = vol.Schema(
            {
                vol.Optional(
                    CONF_TRAFFIC_MODE,
                    default=self.config_entry.options.get(
                        CONF_TRAFFIC_MODE, TRAFFIC_MODE_ENABLED
                    ),
                ): vol.In(TRAFFIC_MODES),
                vol.Optional(
                    CONF_ROUTE_MODE,
                    default=self.config_entry.options.get(
                        CONF_ROUTE_MODE, ROUTE_MODE_FASTEST
                    ),
                ): vol.In(ROUTE_MODES),
                vol.Optional(
                    CONF_UNIT_SYSTEM,
                    default=self.config_entry.options.get(
                        CONF_UNIT_SYSTEM, self.hass.config.units.name
                    ),
                ): vol.In(UNITS),
            }
        )

        return self.async_show_form(step_id="init", data_schema=schema)

    async def async_step_no_time(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Create Options Entry."""
        return self.async_create_entry(title="", data=self._config)

    async def async_step_arrival_time(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure arrival time."""
        if user_input is not None:
            self._config[CONF_ARRIVAL_TIME] = user_input[CONF_ARRIVAL_TIME]
            return self.async_create_entry(title="", data=self._config)

        schema = vol.Schema(
            {vol.Required(CONF_ARRIVAL_TIME, default="00:00:00"): TimeSelector()}
        )

        return self.async_show_form(step_id="arrival_time", data_schema=schema)

    async def async_step_departure_time(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Configure departure time."""
        if user_input is not None:
            self._config[CONF_DEPARTURE_TIME] = user_input[CONF_DEPARTURE_TIME]
            return self.async_create_entry(title="", data=self._config)

        schema = vol.Schema(
            {vol.Required(CONF_DEPARTURE_TIME, default="00:00:00"): TimeSelector()}
        )

        return self.async_show_form(step_id="departure_time", data_schema=schema)
<|endoftext|>


<commit_before>import re

class PlatformDetector(object):
    def __init__(self):
        self.rawinfo = []

    def getCPUInfo(self):
        self.rawinfo = self.readCPUInfo()
        info = {}
        info['numCores'] = self.parseNumCores()
        info['vendorID'] = self.parseCPUInfo('vendor_id')
        info['model'] = int(self.parseCPUInfo('model'))
        info['cpuFamily'] = int(self.parseCPUInfo('cpu family'))
        info['cacheSize'] = int(self.parseCPUInfo('cache size'))
        info['capabilities'] = self.parseCapabilities()
        return info

    def parseCapabilities(self):
        matcher = re.compile("flags\s+:")
        for line in self.rawinfo:
            if re.match(matcher, line):
                return line.split(":")[1].split(" ")

    def parseNumCores(self):
        matcher = re.compile("processor\s+:")
        count = 0
        for line in self.rawinfo:
            if re.match(matcher, line):
                count +=1
        return count

    def parseCPUInfo(self, item):
        matcher = re.compile(item +"\s+:\s*(\w+)")
        for line in self.rawinfo:
            if re.match(matcher, line):
                return re.match(matcher, line).group(1)

    def readCPUInfo(self):
        return open("/proc/cpuinfo", "r").readlines()
<commit_msg>GPUinfo is not implemented<commit_after>import re

class PlatformDetector(object):
    def __init__(self):
        self.rawinfo = []

    def getGPUInfo(self):
        raise NotImplementedError

    def getCPUInfo(self):
        self.rawinfo = self.readCPUInfo()
        info = {}
        info['numCores'] = self.parseNumCores()
        info['vendorID'] = self.parseCPUInfo('vendor_id')
        info['model'] = int(self.parseCPUInfo('model'))
        info['cpuFamily'] = int(self.parseCPUInfo('cpu family'))
        info['cacheSize'] = int(self.parseCPUInfo('cache size'))
        info['capabilities'] = self.parseCapabilities()
        return info

    def parseCapabilities(self):
        matcher = re.compile("flags\s+:")
        for line in self.rawinfo:
            if re.match(matcher, line):
                return line.split(":")[1].split(" ")

    def parseNumCores(self):
        matcher = re.compile("processor\s+:")
        count = 0
        for line in self.rawinfo:
            if re.match(matcher, line):
                count +=1
        return count

    def parseCPUInfo(self, item):
        matcher = re.compile(item +"\s+:\s*(\w+)")
        for line in self.rawinfo:
            if re.match(matcher, line):
                return re.match(matcher, line).group(1)

    def readCPUInfo(self):
        return open("/proc/cpuinfo", "r").readlines()
<|endoftext|>


<commit_before>#Distributed under the MIT licesnse.
#Copyright (c) 2014 Dave McCoy (dave.mccoy@cospandesign.com)

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

"""
Dionysus Interface
"""
__author__ = 'dave.mccoy@cospandesign.com (Dave McCoy)'

import sys
import os

from nplatform import Platform
import usb.core
import usb.util
from pyftdi.pyftdi.ftdi import Ftdi

sys.path.append(os.path.join(os.path.dirname(__file__),
                             os.pardir,
                             os.pardir))

import nysa
from dionysus.dionysus import Dionysus

class DionysusPlatform(Platform):
    def __init__(self, status = None):
        super (DionysusPlatform, self).__init__(status)
        self.vendor = 0x0403
        self.product = 0x8530

    def get_type(self):
        return "Dionysus"

    def scan(self):
        #print ("Scanning...")
        devices = usb.core.find(find_all = True)
        for device in devices:
            if device.idVendor == self.vendor and device.idProduct == self.product:
                sernum = usb.util.get_string(device, 64, device.iSerialNumber)
                #print "Found a Dionysus Device: Serial Number: %s" % sernum

                self.add_device_dict(sernum, Dionysus(idVendor = self.vendor,
                                                      idProduct = self.product,
                                                      sernum = sernum,
                                                      debug = False))
        return self.dev_dict

<commit_msg>BUG: Dionysus platform did not setup new FTDI structure correctly<commit_after>#Distributed under the MIT licesnse.
#Copyright (c) 2014 Dave McCoy (dave.mccoy@cospandesign.com)

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

"""
Dionysus Interface
"""
__author__ = 'dave.mccoy@cospandesign.com (Dave McCoy)'

import sys
import os

from nplatform import Platform
import usb.core
import usb.util
from pyftdi.pyftdi.ftdi import Ftdi

sys.path.append(os.path.join(os.path.dirname(__file__),
                             os.pardir,
                             os.pardir))

import nysa
from dionysus.dionysus import Dionysus

class DionysusPlatform(Platform):
    def __init__(self, status = None):
        super (DionysusPlatform, self).__init__(status)
        self.vendor = 0x0403
        self.product = 0x8530

    def get_type(self):
        return "Dionysus"

    def scan(self):
        #print ("Scanning...")
        devices = usb.core.find(find_all = True)
        for device in devices:
            if device.idVendor == self.vendor and device.idProduct == self.product:
                #sernum = usb.util.get_string(device, 64, device.iSerialNumber)
                #print "Found a Dionysus Device: Serial Number: %s" % sernum

                self.add_device_dict(device.serial_number, Dionysus(idVendor = self.vendor,
                                                      idProduct = self.product,
                                                      sernum = device.serial_number,
                                                      debug = False))
        return self.dev_dict

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
"""
  IRC Brana pro chat na Chatujme.cz
  Projekt vychazi z lidegw v46 ( http://sourceforge.net/projects/lidegw/ )

  @license MIT
  @author LuRy <lury@lury.cz>, <lury@chatujme.cz>
"""

import copy, os, re, socket, string, sys, threading, time, urllib, urllib2, random
import traceback

PORT = 1111
BIND = "0.0.0.0"
version = 1.001

class ircrfc:
  cmd_list = 322

class uzivatel:
  username = ""
  nick = ""
  password = ""
  rooms = []
  me = "chatujme.cz"

class Chatujme:
  def __init__ (self, mySocket, myAdress):
    self.socket = mySocket
    self.adress = myAdress
    self.user = copy.deepcopy(uzivatel())
    self.connection = True
    self.rfc = ircrfc()

  def parse(self, data, timestamp):
    if data == "":
      self.connection = False
      return 2
    if data.find("\r\n") != -1:
      irccmd = string.split(data, "\r\n")
    else:
      irccmd = string.split(data, "\n")
    for cmd_array in irccmd:
      # rozdelim jednotlivy pole na cmd[X]
      cmd = string.split(cmd_array.strip(), " ")
      log("%s" %(cmd))

      if cmd[0] == "NICK":
        self.user.nick = cmd[1]
      elif cmd[0] == "USER":
        self.user.username = cmd[1]
      elif cmd[0] == "PASS":
        self.user.passowrd = cmd[1]
      #elif cmd[0] == "JOIN":
      #elif cmd[0] == "PART":
      elif cmd[0] == "PING":
        if len(cmd) >= 2:
          self.send(":%s PONG :%s\n" % (self.user.me, cmd[1]))
        else :
          self.send(":%s PONG %s\n" % (self.user.me, self.user.me))
      elif cmd[0] == "LIST":
        self.send(self.rfc.cmd_list, "#123456 40 :Nazev mistnosti")
        #self.send(self.rfc.cmd_list, "#%s %s :%s")
        #self.send(":chatujme.cz 322 test #1111 100 :Tema mistnosti\n")
      #elif cmd[0] == "PRIVMSG":
      #elif cmd[0] == "NOTICE":
      #elif cmd[0] == "NOTICE":
      #else:
        #self.socket.send(":%s PONG :%s\n")

  def send(self, _id, msg):
    log("SENDING: %s" %(msg))
    self.socket.send(":%s %d %s %s\n"  %(self.user.me, _id, self.user.nick, msg)  )

class SocketHandler(threading.Thread):
  def __init__ (self, socket, address):
    threading.Thread.__init__(self)
    self.socket = socket
    self.address = address
    self.running = True
  def run (self):
    log("Prijato spojeni z %s" % (self.address[0]))

    timestamp = int(time.time())
    instance = Chatujme(self.socket, self.address[0]);

    while self.running:
      try:
        ircdata = instance.socket.recv(2**13)
        if (instance.parse(ircdata,timestamp) == 2):
          break
      except:
        if traceback:
          traceback.print_exc()
        try:
          instance.socket.send(instance.error())
        except:
          pass
        log("Spojeni z %s uzavreno." %(self.address[0]))
        self.socket.close()
        return False

def log(text):
  print "[%s] %s" % (time.strftime('%Y/%m/%d %H:%M:%S'), text)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((BIND, PORT))
s.listen(50)

log("ChatujmeGW %s, nasloucham na portu %s:%s" %(version, BIND, PORT))

while 1:
  try:
    connection, address = s.accept()
    handler = SocketHandler(connection,address)
    handler.run()

  except (KeyboardInterrupt, EOFError):
    s.close()
    log("Vypinam...", 1)
    break
<commit_msg>implemented /list function<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# encoding=utf8
"""
  IRC Brana pro chat na Chatujme.cz
  Projekt vychazi z lidegw v46 ( http://sourceforge.net/projects/lidegw/ )

  @license MIT
  @author LuRy <lury@lury.cz>, <lury@chatujme.cz>
"""

import copy, os, re, socket, string, sys, threading, time, urllib, urllib2, random, json
import traceback
reload(sys)
sys.setdefaultencoding('utf8')

PORT = 1111
BIND = "0.0.0.0"
version = 1.001

class ircrfc:
  cmd_list = 322

class uzivatel:
  username = ""
  nick = ""
  password = ""
  rooms = []
  me = "chatujme.cz"

class ChatujmeSystem:
  def __init__ (self):
    self.url = "http://api.chatujme.loc/irc"
  def getRooms(self):
    response = urllib2.urlopen( "%s/%s" %(self.url, "get-rooms") )
    data = json.loads(response.read())
    return data

class Chatujme:
  def __init__ (self, mySocket, myAdress):
    self.socket = mySocket
    self.adress = myAdress
    self.user = copy.deepcopy(uzivatel())
    self.system = ChatujmeSystem()
    self.connection = True
    self.rfc = ircrfc()

  def parse(self, data, timestamp):
    if data == "":
      self.connection = False
      return 2
    if data.find("\r\n") != -1:
      irccmd = string.split(data, "\r\n")
    else:
      irccmd = string.split(data, "\n")
    for cmd_array in irccmd:
      # rozdelim jednotlivy pole na cmd[X]
      cmd = string.split(cmd_array.strip(), " ")
      log("%s" %(cmd))

      if cmd[0] == "NICK":
        self.user.nick = cmd[1]
      elif cmd[0] == "USER":
        self.user.username = cmd[1]
      elif cmd[0] == "PASS":
        self.user.passowrd = cmd[1]
      #elif cmd[0] == "JOIN":
      #elif cmd[0] == "PART":
      elif cmd[0] == "PING":
        if len(cmd) >= 2:
          self.send(":%s PONG :%s\n" % (self.user.me, cmd[1]))
        else :
          self.send(":%s PONG %s\n" % (self.user.me, self.user.me))
      elif cmd[0] == "LIST":
        rooms = self.system.getRooms()
        for room in rooms:
          self.send(self.rfc.cmd_list, "#%d %d :%s" % ( room['id'], room['online'], room['nazev'].encode("utf8") ) )
      #elif cmd[0] == "PRIVMSG":
      #elif cmd[0] == "NOTICE":
      #elif cmd[0] == "NOTICE":
      #else:
        #self.socket.send(":%s PONG :%s\n")

  def send(self, _id, msg):
    log("SENDING: %s" %(msg))
    self.socket.send(":%s %d %s %s\n"  %(self.user.me, _id, self.user.nick, msg)  )

class SocketHandler(threading.Thread):
  def __init__ (self, socket, address):
    threading.Thread.__init__(self)
    self.socket = socket
    self.address = address
    self.running = True
  def run (self):
    log("Prijato spojeni z %s" % (self.address[0]))

    timestamp = int(time.time())
    instance = Chatujme(self.socket, self.address[0]);

    while self.running:
      try:
        ircdata = instance.socket.recv(2**13)
        if (instance.parse(ircdata,timestamp) == 2):
          break
      except:
        if traceback:
          traceback.print_exc()
        try:
          instance.socket.send(instance.error())
        except:
          pass
        log("Spojeni z %s uzavreno." %(self.address[0]))
        self.socket.close()
        return False

def log(text):
  print "[%s] %s" % (time.strftime('%Y/%m/%d %H:%M:%S'), text)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((BIND, PORT))
s.listen(50)

log("ChatujmeGW %s, nasloucham na portu %s:%s" %(version, BIND, PORT))

while 1:
  try:
    connection, address = s.accept()
    handler = SocketHandler(connection,address)
    handler.run()

  except (KeyboardInterrupt, EOFError):
    s.close()
    log("Vypinam...", 1)
    break
<|endoftext|>


<commit_before>from cStringIO import StringIO
import os
import urllib

from django.shortcuts import render, redirect
from django.template import Context
from django.http import HttpResponse, HttpResponseRedirect
from django.core.servers.basehttp import FileWrapper
from django.core.urlresolvers import reverse
from django.utils import simplejson

from models import ErrorReport, ErrorReportForm, JobForm
from utils import get_multi_molecule_warnings, get_molecule_info

from chemtools import gjfwriter
from chemtools.utils import write_job
from chemtools.constants import KEYWORDS
from chemtools.interface import get_multi_molecule, get_multi_job
import cluster.interface

def index(request):
    if request.GET.get("molecule"):

        func = molecule_detail
        if set(",{}$") & set(request.GET.get("molecule")):
            func = multi_molecule

        params = {"keywords": request.GET.get("keywords", None)}
        if params["keywords"] != KEYWORDS:
            url = "%s?%s" % (reverse(func,
                                    args=(request.GET.get("molecule"), )),
                urllib.urlencode(params))
            return HttpResponseRedirect(url)
        else:
            return redirect(func, request.GET.get("molecule"))
    return render(request, "chem/index.html")

###########################################################
###########################################################
# Generation Stuff
###########################################################
###########################################################

def multi_job(request):
    form = JobForm.get_form(request, "{{ name }}")

    c = Context({
        "form": form,
        })
    if not form.is_valid():
        return render(request, "chem/multi_job.html", c)

    d = dict(form.cleaned_data)
    if request.method == "GET":
        string = request.REQUEST.get('filenames', '').replace('\n', ',')

        ret_zip = get_multi_job(string, form)

        response = HttpResponse(ret_zip, mimetype="application/zip")
        response["Content-Disposition"] = "attachment; filename=output.zip"
        return response
    elif request.method == "POST":
        cred = d.pop("credential")
        files = request.FILES.getlist("files")
        strings = [''.join(f.readlines()) for f in files]
        names = [os.path.splitext(f.name)[0] for f in files]
        a = cluster.interface.run_jobs(cred, names, strings, **d)
        return HttpResponse(simplejson.dumps(a), mimetype="application/json")
    else:
        return render(request, "chem/multi_job.html", c)

def molecule_check(request, string):
    unique = request.REQUEST.get("unique", '')

    a = {
        "error": None,
    }
    try:
        molecules, warnings, errors = get_multi_molecule_warnings(string,
                                                                unique=unique)
        a["molecules"] = zip(molecules, warnings, errors)
    except ValueError as e:
        a["error"] = str(e)
        a["molecules"] = None
    return HttpResponse(simplejson.dumps(a), mimetype="application/json")

def molecule_detail(request, molecule):
    form = JobForm.get_form(request, molecule)
    keywords = request.REQUEST.get("keywords", '')
    add = "" if request.GET.get("view") else "attachment; "

    if form.is_valid():
        d = dict(form.cleaned_data)
        if request.method == "GET":
            response = HttpResponse(write_job(**d), content_type="text/plain")
            filename = '%s.job' % molecule
            response['Content-Disposition'] = add + 'filename=' + filename
            return response
        elif request.method == "POST":
            d["keywords"] = keywords
            cred = d.pop("credential")
            a = cluster.interface.run_standard_job(cred, molecule, **d)
            return HttpResponse(simplejson.dumps(a),
                                mimetype="application/json")

    keywords2 = request.REQUEST.get("keywords", KEYWORDS)
    a = get_molecule_info(molecule, keywords2)
    a["form"] = form
    c = Context(a)
    return render(request, "chem/molecule_detail.html", c)

def molecule_detail_json(request, molecule):
    keywords = request.REQUEST.get("keywords", KEYWORDS)
    a = get_molecule_info(request, keywords)
    return HttpResponse(simplejson.dumps(a), mimetype="application/json")

def multi_molecule(request, string):
    form = JobForm.get_form(request, "{{ name }}")
    add = "" if request.GET.get("view") else "attachment; "

    if form.is_valid():
        d = dict(form.cleaned_data)
        if request.method == "GET":
            molecule = request.REQUEST.get("molname", "")
            d = form.get_single_data(molecule)
            response = HttpResponse(write_job(**d), content_type="text/plain")
            filename = '%s.job' % molecule
            response['Content-Disposition'] = add + 'filename=' + filename
            return response

        elif request.method == "POST":
            d["keywords"] = request.REQUEST.get("keywords", None)
            cred = d.pop("credential")
            a = cluster.interface.run_standard_jobs(cred, string, **d)
            return HttpResponse(simplejson.dumps(a),
                                mimetype="application/json")

    keywords = request.REQUEST.get("keywords", "")
    unique = request.GET.get("unique", '')
    encoded_keywords = '?' + urllib.urlencode({"keywords": keywords})
    encoded_zip = '?' + urllib.urlencode({"keywords": keywords,
                                        "unique": unique})
    c = Context({
        "pagename": string,
        "form": form,
        "gjf": "checked",
        "encoded_keywords": encoded_keywords if keywords else '',
        "keywords": keywords,
        "unique": unique,
        "encoded_zip": encoded_zip,
        })
    return render(request, "chem/multi_molecule.html", c)

def multi_molecule_zip(request, string):
    keywords = request.GET.get("keywords")
    unique = request.GET.get("unique", '')

    try:
        molecules, warnings, errors = get_multi_molecule_warnings(string,
                                                                unique=unique)
    except ValueError as e:
        c = Context({
            "error": str(e)
            })
        return render(request, "chem/multi_molecule.html", c)

    if request.GET.get("job"):
        form = JobForm.get_form(request, "{{ name }}")
        if not form.is_valid():
            keywords = request.GET.get("keywords")
            f = lambda x: 'checked' if request.GET.get(x) else ''

            encoded_keywords = '?' + urllib.urlencode({"keywords": keywords})
            c = Context({
                "molecules": zip(molecules, errors, warnings),
                "pagename": string,
                "form": form,
                "gjf": f("gjf"),
                "mol2": f("mol2"),
                "image": f("image"),
                "job": f("job"),
                "encoded_keywords": encoded_keywords if keywords else '',
                })
            return render(request, "chem/multi_molecule.html", c)
    else:
        form = None

    selection = ("image", "mol2", "job", "gjf")
    options = [x for x in selection if request.GET.get(x)]
    ret_zip = get_multi_molecule(molecules, keywords, options, form)

    response = HttpResponse(ret_zip, mimetype="application/zip")
    response["Content-Disposition"] = "attachment; filename=molecules.zip"
    return response

def write_gjf(request, molecule):
    keywords = request.GET.get("keywords")
    add = "" if request.GET.get("view") else "attachment; "

    out = gjfwriter.GJFWriter(molecule, keywords)
    f = StringIO(out.get_gjf())
    response = HttpResponse(FileWrapper(f), content_type="text/plain")
    response['Content-Disposition'] = add + 'filename=%s.gjf' % molecule
    return response

def write_mol2(request, molecule):
    add = "" if request.GET.get("view") else "attachment; "

    out = gjfwriter.GJFWriter(molecule, '')
    f = StringIO(out.get_mol2())
    response = HttpResponse(FileWrapper(f), content_type="text/plain")
    response['Content-Disposition'] = add + 'filename=%s.mol2' % molecule
    return response

def write_png(request, molecule):
    scale = request.GET.get("scale", 10)

    out = gjfwriter.GJFWriter(molecule, '')
    response = HttpResponse(content_type="image/png")
    out.molecule.draw(int(scale)).save(response, "PNG")
    response['Content-Disposition'] = 'filename=%s.png' % molecule
    return response

def report(request, molecule):
    if request.user.is_authenticated():
        email = request.user.email
    else:
        email = ""

    if request.method == "POST":
        report = ErrorReport(molecule=molecule)
        form = ErrorReportForm(request.POST,
            instance=report,
            initial={"email": email})
        if form.is_valid():
            form.save()
            return redirect(molecule_detail, molecule)
    else:
        form = ErrorReportForm(initial={"email": email})

    c = Context({
        "form": form,
        "molecule": molecule
        })
    return render(request, "chem/report.html", c)
<commit_msg>Fix typo<commit_after>from cStringIO import StringIO
import os
import urllib

from django.shortcuts import render, redirect
from django.template import Context
from django.http import HttpResponse, HttpResponseRedirect
from django.core.servers.basehttp import FileWrapper
from django.core.urlresolvers import reverse
from django.utils import simplejson

from models import ErrorReport, ErrorReportForm, JobForm
from utils import get_multi_molecule_warnings, get_molecule_info

from chemtools import gjfwriter
from chemtools.utils import write_job
from chemtools.constants import KEYWORDS
from chemtools.interface import get_multi_molecule, get_multi_job
import cluster.interface

def index(request):
    if request.GET.get("molecule"):

        func = molecule_detail
        if set(",{}$") & set(request.GET.get("molecule")):
            func = multi_molecule

        params = {"keywords": request.GET.get("keywords", None)}
        if params["keywords"] != KEYWORDS:
            url = "%s?%s" % (reverse(func,
                                    args=(request.GET.get("molecule"), )),
                urllib.urlencode(params))
            return HttpResponseRedirect(url)
        else:
            return redirect(func, request.GET.get("molecule"))
    return render(request, "chem/index.html")

###########################################################
###########################################################
# Generation Stuff
###########################################################
###########################################################

def multi_job(request):
    form = JobForm.get_form(request, "{{ name }}")

    c = Context({
        "form": form,
        })
    if not form.is_valid():
        return render(request, "chem/multi_job.html", c)

    d = dict(form.cleaned_data)
    if request.method == "GET":
        string = request.REQUEST.get('filenames', '').replace('\n', ',')

        ret_zip = get_multi_job(string, form)

        response = HttpResponse(ret_zip, mimetype="application/zip")
        response["Content-Disposition"] = "attachment; filename=output.zip"
        return response
    elif request.method == "POST":
        cred = d.pop("credential")
        files = request.FILES.getlist("files")
        strings = [''.join(f.readlines()) for f in files]
        names = [os.path.splitext(f.name)[0] for f in files]
        a = cluster.interface.run_jobs(cred, names, strings, **d)
        return HttpResponse(simplejson.dumps(a), mimetype="application/json")
    else:
        return render(request, "chem/multi_job.html", c)

def molecule_check(request, string):
    unique = request.REQUEST.get("unique", '')

    a = {
        "error": None,
    }
    try:
        molecules, warnings, errors = get_multi_molecule_warnings(string,
                                                                unique=unique)
        a["molecules"] = zip(molecules, warnings, errors)
    except ValueError as e:
        a["error"] = str(e)
        a["molecules"] = None
    return HttpResponse(simplejson.dumps(a), mimetype="application/json")

def molecule_detail(request, molecule):
    form = JobForm.get_form(request, molecule)
    keywords = request.REQUEST.get("keywords", '')
    add = "" if request.GET.get("view") else "attachment; "

    if form.is_valid():
        d = dict(form.cleaned_data)
        if request.method == "GET":
            response = HttpResponse(write_job(**d), content_type="text/plain")
            filename = '%s.job' % molecule
            response['Content-Disposition'] = add + 'filename=' + filename
            return response
        elif request.method == "POST":
            d["keywords"] = keywords
            cred = d.pop("credential")
            a = cluster.interface.run_standard_job(cred, molecule, **d)
            return HttpResponse(simplejson.dumps(a),
                                mimetype="application/json")

    keywords2 = request.REQUEST.get("keywords", KEYWORDS)
    a = get_molecule_info(molecule, keywords2)
    a["form"] = form
    c = Context(a)
    return render(request, "chem/molecule_detail.html", c)

def molecule_detail_json(request, molecule):
    keywords = request.REQUEST.get("keywords", KEYWORDS)
    a = get_molecule_info(molecule, keywords)
    return HttpResponse(simplejson.dumps(a), mimetype="application/json")

def multi_molecule(request, string):
    form = JobForm.get_form(request, "{{ name }}")
    add = "" if request.GET.get("view") else "attachment; "

    if form.is_valid():
        d = dict(form.cleaned_data)
        if request.method == "GET":
            molecule = request.REQUEST.get("molname", "")
            d = form.get_single_data(molecule)
            response = HttpResponse(write_job(**d), content_type="text/plain")
            filename = '%s.job' % molecule
            response['Content-Disposition'] = add + 'filename=' + filename
            return response

        elif request.method == "POST":
            d["keywords"] = request.REQUEST.get("keywords", None)
            cred = d.pop("credential")
            a = cluster.interface.run_standard_jobs(cred, string, **d)
            return HttpResponse(simplejson.dumps(a),
                                mimetype="application/json")

    keywords = request.REQUEST.get("keywords", "")
    unique = request.GET.get("unique", '')
    encoded_keywords = '?' + urllib.urlencode({"keywords": keywords})
    encoded_zip = '?' + urllib.urlencode({"keywords": keywords,
                                        "unique": unique})
    c = Context({
        "pagename": string,
        "form": form,
        "gjf": "checked",
        "encoded_keywords": encoded_keywords if keywords else '',
        "keywords": keywords,
        "unique": unique,
        "encoded_zip": encoded_zip,
        })
    return render(request, "chem/multi_molecule.html", c)

def multi_molecule_zip(request, string):
    keywords = request.GET.get("keywords")
    unique = request.GET.get("unique", '')

    try:
        molecules, warnings, errors = get_multi_molecule_warnings(string,
                                                                unique=unique)
    except ValueError as e:
        c = Context({
            "error": str(e)
            })
        return render(request, "chem/multi_molecule.html", c)

    if request.GET.get("job"):
        form = JobForm.get_form(request, "{{ name }}")
        if not form.is_valid():
            keywords = request.GET.get("keywords")
            f = lambda x: 'checked' if request.GET.get(x) else ''

            encoded_keywords = '?' + urllib.urlencode({"keywords": keywords})
            c = Context({
                "molecules": zip(molecules, errors, warnings),
                "pagename": string,
                "form": form,
                "gjf": f("gjf"),
                "mol2": f("mol2"),
                "image": f("image"),
                "job": f("job"),
                "encoded_keywords": encoded_keywords if keywords else '',
                })
            return render(request, "chem/multi_molecule.html", c)
    else:
        form = None

    selection = ("image", "mol2", "job", "gjf")
    options = [x for x in selection if request.GET.get(x)]
    ret_zip = get_multi_molecule(molecules, keywords, options, form)

    response = HttpResponse(ret_zip, mimetype="application/zip")
    response["Content-Disposition"] = "attachment; filename=molecules.zip"
    return response

def write_gjf(request, molecule):
    keywords = request.GET.get("keywords")
    add = "" if request.GET.get("view") else "attachment; "

    out = gjfwriter.GJFWriter(molecule, keywords)
    f = StringIO(out.get_gjf())
    response = HttpResponse(FileWrapper(f), content_type="text/plain")
    response['Content-Disposition'] = add + 'filename=%s.gjf' % molecule
    return response

def write_mol2(request, molecule):
    add = "" if request.GET.get("view") else "attachment; "

    out = gjfwriter.GJFWriter(molecule, '')
    f = StringIO(out.get_mol2())
    response = HttpResponse(FileWrapper(f), content_type="text/plain")
    response['Content-Disposition'] = add + 'filename=%s.mol2' % molecule
    return response

def write_png(request, molecule):
    scale = request.GET.get("scale", 10)

    out = gjfwriter.GJFWriter(molecule, '')
    response = HttpResponse(content_type="image/png")
    out.molecule.draw(int(scale)).save(response, "PNG")
    response['Content-Disposition'] = 'filename=%s.png' % molecule
    return response

def report(request, molecule):
    if request.user.is_authenticated():
        email = request.user.email
    else:
        email = ""

    if request.method == "POST":
        report = ErrorReport(molecule=molecule)
        form = ErrorReportForm(request.POST,
            instance=report,
            initial={"email": email})
        if form.is_valid():
            form.save()
            return redirect(molecule_detail, molecule)
    else:
        form = ErrorReportForm(initial={"email": email})

    c = Context({
        "form": form,
        "molecule": molecule
        })
    return render(request, "chem/report.html", c)
<|endoftext|>


<commit_before>from django.contrib import admin

from easy_thumbnails.files import get_thumbnailer

from chet.models import Album, Photo

class AlbumAdmin(admin.ModelAdmin):
    date_hierarchy = 'date'
    list_display = ('title', 'date', 'is_active', 'is_public')
    list_editable = ('is_active', 'is_public')
    list_filter = ('is_active', 'is_public')
    prepopulated_fields = {'slug': ('title',)}
    search_fields = ('title',)

class PhotoAdmin(admin.ModelAdmin):
    date_hierarchy = 'shot_on'
    # TODO add thumb
    list_display = (
        'thumbnail', 'title', 'shot_on', 'is_active', 'is_public', 'is_dark')
    list_editable = ('is_active', 'is_public', 'is_dark')
    list_filter = ('is_active', 'is_public', 'is_dark', 'album')
    search_fields = ('title',)

    def thumbnail(self, photo):
        options = {'size': (100, 100), 'crop': True}
        thumb_url = get_thumbnailer(photo.file).get_thumbnail(options).url
        return ''.format(thumb_url)

    thumbnail.allow_tags = True
    thumbnail.short_description = 'thumb'

admin.site.register(Album, AlbumAdmin)
admin.site.register(Photo, PhotoAdmin)
<commit_msg>Show the photo count in the administration panel<commit_after>from django.contrib import admin
from django.utils.translation import ugettext_lazy as _

from easy_thumbnails.files import get_thumbnailer

from chet.models import Album, Photo

class AlbumAdmin(admin.ModelAdmin):
    date_hierarchy = 'date'
    list_display = ('title', 'date', 'is_active', 'is_public', 'photos')
    list_editable = ('is_active', 'is_public')
    list_filter = ('is_active', 'is_public')
    prepopulated_fields = {'slug': ('title',)}
    search_fields = ('title',)

    def photos(self, instance):
        return instance.photos.count()
    photos.short_description = _('photos')

class PhotoAdmin(admin.ModelAdmin):
    date_hierarchy = 'shot_on'
    # TODO add thumb
    list_display = (
        'thumbnail', 'title', 'shot_on', 'is_active', 'is_public', 'is_dark')
    list_editable = ('is_active', 'is_public', 'is_dark')
    list_filter = ('is_active', 'is_public', 'is_dark', 'album')
    search_fields = ('title',)

    def thumbnail(self, photo):
        options = {'size': (100, 100), 'crop': True}
        thumb_url = get_thumbnailer(photo.file).get_thumbnail(options).url
        return ''.format(thumb_url)

    thumbnail.allow_tags = True
    thumbnail.short_description = 'thumb'

admin.site.register(Album, AlbumAdmin)
admin.site.register(Photo, PhotoAdmin)
<|endoftext|>


<commit_before>
# Copyright 2016 Battelle Energy Alliance, 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
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""civet URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from __future__ import unicode_literals, absolute_import
from django.conf.urls import include, url
from django.contrib import admin

app_name = "ci"

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('ci.urls')),
]
<commit_msg>Fix debug_toolbar urls<commit_after>
# Copyright 2016 Battelle Energy Alliance, 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
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""civet URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from __future__ import unicode_literals, absolute_import
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings

app_name = "ci"

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('ci.urls')),
]

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += [ url(r'^__debug__/', include(debug_toolbar.urls)), ]
<|endoftext|>


<commit_before>from fuel.datasets.cifar10 import CIFAR10
from sklearn.cluster import KMeans
from collections import Counter
from scipy.stats.mstats import mode

import numpy as np

def data():
    train = CIFAR10(("train",), subset=slice(None, 40000))
    validation = CIFAR10(("train",), subset=slice(40000, None))
    test = CIFAR10(("test",))

    return train, validation, test

train, validation, test = data()

print "Training set size: %d" % (train.num_examples)
print "Validation set size: %d" % (validation.num_examples)
print "Test set size: %d" % (test.num_examples)

train_data = np.reshape(train.data_sources[0], (40000, 3072))
train_labels = train.data_sources[1].T.ravel()

validation_data = np.reshape(validation.data_sources[0], (10000, 3072))
validation_labels = validation.data_sources[1].T.ravel()

test_data = np.reshape(test.data_sources[0], (10000, 3072))
test_labels = test.data_sources[1].T.ravel()

def PerformKMeansAnalysis(train_data, train_labels, test_data, test_labels):
    naive_grouping = KMeans(n_clusters=10, n_init=5, n_jobs=8)
    naive_grouping.fit(train_data)
    group_labels = naive_grouping.labels_

    for label in set(group_labels):
        train_mask = group_labels == label
        real_labels = train_labels[train_mask]
        pos_stat = Counter(real_labels).values()
        pos_stat = np.array(pos_stat).astype(np.float)
        pos_stat /= real_labels.shape[0]

        representative = mode(real_labels)[0]
        gini_index = np.dot(pos_stat.T, np.ones(pos_stat.shape[0]) - pos_stat)
        print "For label %d: %s" % (label, gini_index)
        print "Representative: ", representative
        print "======"

<commit_msg>Tried to apply linear SVM classifier<commit_after>from fuel.datasets.cifar10 import CIFAR10
from sklearn.cluster import KMeans
from sklearn.linear_model import SGDClassifier
from collections import Counter
from scipy.stats.mstats import mode

import numpy as np

def data():
    train = CIFAR10(("train",), subset=slice(None, 40000))
    validation = CIFAR10(("train",), subset=slice(40000, None))
    test = CIFAR10(("test",))

    return train, validation, test

train, validation, test = data()

print "Training set size: %d" % (train.num_examples)
print "Validation set size: %d" % (validation.num_examples)
print "Test set size: %d" % (test.num_examples)

train_data = np.reshape(train.data_sources[0], (40000, 3072))
train_labels = train.data_sources[1].T.ravel()

validation_data = np.reshape(validation.data_sources[0], (10000, 3072))
validation_labels = validation.data_sources[1].T.ravel()

test_data = np.reshape(test.data_sources[0], (10000, 3072))
test_labels = test.data_sources[1].T.ravel()

def PerformKMeansAnalysis(train_data, train_labels, test_data, test_labels):
    naive_grouping = KMeans(n_clusters=10, n_init=5, n_jobs=8)
    naive_grouping.fit(train_data)
    group_labels = naive_grouping.labels_

    for label in set(group_labels):
        train_mask = group_labels == label
        real_labels = train_labels[train_mask]
        pos_stat = Counter(real_labels).values()
        pos_stat = np.array(pos_stat).astype(np.float)
        pos_stat /= real_labels.shape[0]

        representative = mode(real_labels)[0]
        gini_index = np.dot(pos_stat.T, np.ones(pos_stat.shape[0]) - pos_stat)
        print "For label %d: %s" % (label, gini_index)
        print "Representative: ", representative
        print "======"

svc = SGDClassifier(loss='squared_hinge', verbose=1, n_jobs=8, n_iter=100)

svc.fit(train_data, train_labels)

predictions = svc.predict(validation_data)

wrong = np.nonzero(validation_labels - predictions)[0].astype(np.float).shape[0]

print (float(wrong) / predictions.shape[0])
<|endoftext|>


<commit_before>#!/usr/bin/env python3
"""実験用コード。"""
import argparse
import pathlib

import numpy as np

import pytoolkit as tk

def _main():
    tk.better_exceptions()
    parser = argparse.ArgumentParser()
    parser.add_argument('--result-dir', default=pathlib.Path('results_classifier'), type=pathlib.Path)
    parser.add_argument('--dataset', default='cifar100', choices=('cifar10', 'cifar100'))
    parser.add_argument('--epochs', default=300, type=int)
    parser.add_argument('--batch-size', default=64, type=int)
    args = parser.parse_args()
    args.result_dir.mkdir(parents=True, exist_ok=True)
    with tk.dl.session(use_horovod=True):
        tk.log.init(args.result_dir / 'train.log')
        _run(args)

@tk.log.trace()
def _run(args):
    import keras

    if args.dataset == 'cifar10':
        (X_train, y_train), (X_val, y_val) = keras.datasets.cifar10.load_data()
    elif args.dataset == 'cifar100':
        (X_train, y_train), (X_val, y_val) = keras.datasets.cifar100.load_data()
    else:
        assert False
    y_train = np.squeeze(y_train)
    y_val = np.squeeze(y_val)
    input_shape = X_train.shape[1:]
    num_classes = len(np.unique(y_train))

    with tk.log.trace_scope('create network'):
        builder = tk.dl.networks.Builder()
        x = inp = keras.layers.Input(input_shape)
        x = builder.conv2d(128, use_act=False, name=f'start')(x)
        for stage, filters in enumerate([128, 256, 512]):
            name1 = f'stage{stage + 1}'
            x = builder.conv2d(filters, strides=1 if stage == 0 else 2, use_act=False, name=f'{name1}_ds')(x)
            for block in range(8):
                name2 = f'stage{stage + 1}_block{block + 1}'
                sc = x
                x = builder.conv2d(filters // 4, name=f'{name2}_c1')(x)
                for d in range(7):
                    t = builder.conv2d(filters // 4, name=f'{name2}_d{d}')(x)
                    x = keras.layers.concatenate([x, t], name=f'{name2}_d{d}_cat')
                x = builder.conv2d(filters, 1, use_act=False, name=f'{name2}_c2')(x)
                x = keras.layers.add([sc, x], name=f'{name2}_add')
            x = builder.bn_act(name=f'{name1}')(x)
        x = keras.layers.Dropout(0.5, name='dropout')(x)
        x = keras.layers.GlobalAveragePooling2D(name='pooling')(x)
        x = builder.dense(num_classes, activation='softmax', name='predictions')(x)
        model = keras.models.Model(inputs=inp, outputs=x)

    gen = tk.image.ImageDataGenerator()
    gen.add(tk.image.Padding(probability=1))
    gen.add(tk.image.RandomRotate(probability=0.25))
    gen.add(tk.image.RandomCrop(probability=1))
    gen.add(tk.image.Resize(input_shape[:2]))
    gen.add(tk.image.RandomFlipLR(probability=0.5))
    gen.add(tk.image.RandomColorAugmentors())
    gen.add(tk.image.RandomErasing(probability=0.5))
    gen.add(tk.image.Preprocess(mode='tf'))
    gen.add(tk.generator.ProcessOutput(tk.ml.to_categorical(num_classes), batch_axis=True))

    model = tk.dl.models.Model(model, gen, args.batch_size)
    model.compile(sgd_lr=0.5 / 256, loss='categorical_crossentropy', metrics=['acc'])
    model.summary()

    model.fit(X_train, y_train, validation_data=(X_val, y_val),
              epochs=args.epochs, tsv_log_path=args.result_dir / 'history.tsv',
              mixup=True, cosine_annealing=True)
    model.save(args.result_dir / 'model.h5')
    if tk.dl.hvd.is_master():
        proba_val = model.predict(X_val)
        tk.ml.print_classification_metrics(y_val, proba_val)

if __name__ == '__main__':
    _main()
<commit_msg>1e-3<commit_after>#!/usr/bin/env python3
"""実験用コード。"""
import argparse
import pathlib

import numpy as np

import pytoolkit as tk

def _main():
    tk.better_exceptions()
    parser = argparse.ArgumentParser()
    parser.add_argument('--result-dir', default=pathlib.Path('results_classifier'), type=pathlib.Path)
    parser.add_argument('--dataset', default='cifar100', choices=('cifar10', 'cifar100'))
    parser.add_argument('--epochs', default=300, type=int)
    parser.add_argument('--batch-size', default=64, type=int)
    args = parser.parse_args()
    args.result_dir.mkdir(parents=True, exist_ok=True)
    with tk.dl.session(use_horovod=True):
        tk.log.init(args.result_dir / 'train.log')
        _run(args)

@tk.log.trace()
def _run(args):
    import keras

    if args.dataset == 'cifar10':
        (X_train, y_train), (X_val, y_val) = keras.datasets.cifar10.load_data()
    elif args.dataset == 'cifar100':
        (X_train, y_train), (X_val, y_val) = keras.datasets.cifar100.load_data()
    else:
        assert False
    y_train = np.squeeze(y_train)
    y_val = np.squeeze(y_val)
    input_shape = X_train.shape[1:]
    num_classes = len(np.unique(y_train))

    with tk.log.trace_scope('create network'):
        builder = tk.dl.networks.Builder()
        x = inp = keras.layers.Input(input_shape)
        x = builder.conv2d(128, use_act=False, name=f'start')(x)
        for stage, filters in enumerate([128, 256, 512]):
            name1 = f'stage{stage + 1}'
            x = builder.conv2d(filters, strides=1 if stage == 0 else 2, use_act=False, name=f'{name1}_ds')(x)
            for block in range(8):
                name2 = f'stage{stage + 1}_block{block + 1}'
                sc = x
                x = builder.conv2d(filters // 4, name=f'{name2}_c1')(x)
                for d in range(7):
                    t = builder.conv2d(filters // 4, name=f'{name2}_d{d}')(x)
                    x = keras.layers.concatenate([x, t], name=f'{name2}_d{d}_cat')
                x = builder.conv2d(filters, 1, use_act=False, name=f'{name2}_c2')(x)
                x = keras.layers.add([sc, x], name=f'{name2}_add')
            x = builder.bn_act(name=f'{name1}')(x)
        x = keras.layers.Dropout(0.5, name='dropout')(x)
        x = keras.layers.GlobalAveragePooling2D(name='pooling')(x)
        x = builder.dense(num_classes, activation='softmax', name='predictions')(x)
        model = keras.models.Model(inputs=inp, outputs=x)

    gen = tk.image.ImageDataGenerator()
    gen.add(tk.image.Padding(probability=1))
    gen.add(tk.image.RandomRotate(probability=0.25))
    gen.add(tk.image.RandomCrop(probability=1))
    gen.add(tk.image.Resize(input_shape[:2]))
    gen.add(tk.image.RandomFlipLR(probability=0.5))
    gen.add(tk.image.RandomColorAugmentors())
    gen.add(tk.image.RandomErasing(probability=0.5))
    gen.add(tk.image.Preprocess(mode='tf'))
    gen.add(tk.generator.ProcessOutput(tk.ml.to_categorical(num_classes), batch_axis=True))

    model = tk.dl.models.Model(model, gen, args.batch_size)
    model.compile(sgd_lr=1e-3, loss='categorical_crossentropy', metrics=['acc'])
    model.summary()

    model.fit(X_train, y_train, validation_data=(X_val, y_val),
              epochs=args.epochs, tsv_log_path=args.result_dir / 'history.tsv',
              mixup=True, cosine_annealing=True)
    model.save(args.result_dir / 'model.h5')
    if tk.dl.hvd.is_master():
        proba_val = model.predict(X_val)
        tk.ml.print_classification_metrics(y_val, proba_val)

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