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

"""This module contains classes relating to Sonos Alarms."""

from __future__ import unicode_literals

import logging
import re
import weakref
from datetime import datetime

from . import discovery
from .core import PLAY_MODES
from .xml import XML

log = logging.getLogger(__name__)  # pylint: disable=C0103
TIME_FORMAT = "%H:%M:%S"

def is_valid_recurrence(text):
    """Check that ``text`` is a valid recurrence string.

    A valid recurrence string is  ``DAILY``, ``ONCE``, ``WEEKDAYS``,
    ``WEEKENDS`` or of the form ``ON_DDDDDD`` where ``D`` is a number from 0-7
    representing a day of the week (Sunday is 0), e.g. ``ON_034`` meaning
    Sunday, Wednesday and Thursday

    Args:
        text (str): the recurrence string to check.

    Returns:
        bool: `True` if the recurrence string is valid, else `False`.

    Examples:

        >>> from soco.alarms import is_valid_recurrence
        >>> is_valid_recurrence('WEEKENDS')
        True
        >>> is_valid_recurrence('')
        False
        >>> is_valid_recurrence('ON_132')  # Mon, Tue, Wed
        True
        >>> is_valid_recurrence('ON_777')  # Sat
        True
        >>> is_valid_recurrence('ON_3421') # Mon, Tue, Wed, Thur
        True
        >>> is_valid_recurrence('ON_123456789') # Too many digits
        False
    """
    if text in ("DAILY", "ONCE", "WEEKDAYS", "WEEKENDS"):
        return True
    return re.search(r'^ON_[0-7]{1,7}$', text) is not None

class Alarm(object):

    """A class representing a Sonos Alarm.

    Alarms may be created or updated and saved to, or removed from the Sonos
    system. An alarm is not automatically saved. Call `save()` to do that.

    Example:

        >>> device = discovery.any_soco()
        >>> # create an alarm with default properties
        >>> alarm = Alarm(device)
        >>> print alarm.volume
        20
        >>> print get_alarms()
        set([])
        >>> # save the alarm to the Sonos system
        >>> alarm.save()
        >>> print get_alarms()
        set([<Alarm id:88@15:26:15 at 0x107abb090>])
        >>> # update the alarm
        >>> alarm.recurrence = "ONCE"
        >>> # Save it again for the change to take effect
        >>> alarm.save()
        >>> # Remove it
        >>> alarm.remove()
        >>> print get_alarms()
        set([])
    """
    # pylint: disable=too-many-instance-attributes

    _all_alarms = weakref.WeakValueDictionary()

    # pylint: disable=too-many-arguments
    def __init__(
            self, zone, start_time=None, duration=None,
            recurrence='DAILY', enabled=True,
            program_uri=None, program_metadata='',
            play_mode='NORMAL', volume=20, include_linked_zones=False):
        """
        Args:
            zone (`SoCo`): The soco instance which will play the alarm.
            start_time (`datetime.time`, optional): The alarm's start time.
                Specify hours, minutes and seconds only. Defaults to the
                current time.
            duration (`datetime.time`, optional): The alarm's duration. Specify
                hours, minutes and seconds only. May be `None` for unlimited
                duration. Defaults to `None`.
            recurrence (str, optional): A string representing how
                often the alarm should be triggered. Can be ``DAILY``,
                ``ONCE``, ``WEEKDAYS``, ``WEEKENDS`` or of the form
                ``ON_DDDDDD`` where ``D`` is a number from 0-7 representing a
                day of the week (Sunday is 0), e.g. ``ON_034`` meaning Sunday,
                Wednesday and Thursday. Defaults to ``DAILY``.
            enabled (bool, optional): `True` if alarm is enabled, `False`
                otherwise. Defaults to `True`.
            program_uri(str, optional): The uri to play. If `None`, the
                built-in Sonos chime sound will be used. Defaults to `None`.
            program_metadata (str, optional): The metadata associated with
                `program_uri`. Defaults to ''.
            play_mode(str, optional): The play mode for the alarm. Can be one
                of ``NORMAL``, ``SHUFFLE_NOREPEAT``, ``SHUFFLE``,
                ``REPEAT_ALL``, ``REPEAT_ONE``, ``SHUFFLE_REPEAT_ONE``.
                Defaults to ``NORMAL``.
            volume (int, optional): The alarm's volume (0-100). Defaults to 20.
            include_linked_zones (bool, optional): `True` if the alarm should
                be played on the other speakers in the same group, `False`
                otherwise. Defaults to `False`.
        """

        super(Alarm, self).__init__()
        self.zone = zone
        if start_time is None:
            start_time = datetime.now().time()
        #: `datetime.time`: The alarm's start time.
        self.start_time = start_time
        #: `datetime.time`: The alarm's duration.
        self.duration = duration
        self._recurrence = recurrence
        #: `bool`: `True` if the alarm is enabled, else `False`.
        self.enabled = enabled
        #:
        self.program_uri = program_uri
        #: `str`: The uri to play.
        self.program_metadata = program_metadata
        self._play_mode = play_mode
        self._volume = volume
        #: `bool`: `True` if the alarm should be played on the other speakers
        #: in the same group, `False` otherwise.
        self.include_linked_zones = include_linked_zones
        self._alarm_id = None

    def __repr__(self):
        middle = str(self.start_time.strftime(TIME_FORMAT))
        return "<{0} id:{1}@{2} at {3}>".format(
            self.__class__.__name__, self._alarm_id, middle, hex(id(self)))

    @property
    def play_mode(self):
        """
        `str`: The play mode for the alarm.

            Can be one of ``NORMAL``, ``SHUFFLE_NOREPEAT``, ``SHUFFLE``,
            ``REPEAT_ALL``, ``REPEAT_ONE``, ``SHUFFLE_REPEAT_ONE``.
        """
        return self._play_mode

    @play_mode.setter
    def play_mode(self, play_mode):
        """See `playmode`."""
        play_mode = play_mode.upper()
        if play_mode not in PLAY_MODES:
            raise KeyError("'%s' is not a valid play mode" % play_mode)
        self._play_mode = play_mode

    @property
    def volume(self):
        """`int`: The alarm's volume (0-100)."""
        return self._volume

    @volume.setter
    def volume(self, volume):
        """See `volume`."""
        # max 100
        volume = int(volume)
        self._volume = max(0, min(volume, 100))  # Coerce in range

    @property
    def recurrence(self):
        """`str`: How often the alarm should be triggered.

        Can be ``DAILY``, ``ONCE``, ``WEEKDAYS``, ``WEEKENDS`` or of the form
        ``ON_DDDDDDD`` where ``D`` is a number from 0-7 representing a day of
        the week (Sunday is 0), e.g. ``ON_034`` meaning Sunday, Wednesday and
        Thursday.
        """
        return self._recurrence

    @recurrence.setter
    def recurrence(self, recurrence):
        """See `recurrence`."""
        if not is_valid_recurrence(recurrence):
            raise KeyError("'%s' is not a valid recurrence value" % recurrence)

        self._recurrence = recurrence

    def save(self):
        """Save the alarm to the Sonos system.

        Raises:
            ~soco.exceptions.SoCoUPnPException: if the alarm cannot be created
                because there
                is already an alarm for this room at the specified time.
        """
        # pylint: disable=bad-continuation
        args = [
            ('StartLocalTime', self.start_time.strftime(TIME_FORMAT)),
            ('Duration', '' if self.duration is None else
                self.duration.strftime(TIME_FORMAT)),
            ('Recurrence', self.recurrence),
            ('Enabled', '1' if self.enabled else '0'),
            ('RoomUUID', self.zone.uid),
            ('ProgramURI', "x-rincon-buzzer:0" if self.program_uri is None
                else self.program_uri),
            ('ProgramMetaData', self.program_metadata),
            ('PlayMode', self.play_mode),
            ('Volume', self.volume),
            ('IncludeLinkedZones', '1' if self.include_linked_zones else '0')
        ]
        if self._alarm_id is None:
            response = self.zone.alarmClock.CreateAlarm(args)
            self._alarm_id = response['AssignedID']
            Alarm._all_alarms[self._alarm_id] = self
        else:
            # The alarm has been saved before. Update it instead.
            args.insert(0, ('ID', self._alarm_id))
            self.zone.alarmClock.UpdateAlarm(args)

    def remove(self):
        """Remove the alarm from the Sonos system.

        There is no need to call `save`. The Python instance is not deleted,
        and can be saved back to Sonos again if desired.
        """
        self.zone.alarmClock.DestroyAlarm([
            ('ID', self._alarm_id)
        ])
        alarm_id = self._alarm_id
        try:
            del Alarm._all_alarms[alarm_id]
        except KeyError:
            pass
        self._alarm_id = None

def get_alarms(zone=None):
    """Get a set of all alarms known to the Sonos system.

    Args:
        zone (`SoCo`, optional): a SoCo instance to query. If None, a random
            instance is used. Defaults to `None`.

    Returns:
        set: A set of `Alarm` instances

    Note:
        Any existing `Alarm` instance will have its attributes updated to those
        currently stored on the Sonos system.
    """
    # Get a soco instance to query. It doesn't matter which.
    if zone is None:
        zone = discovery.any_soco()
    response = zone.alarmClock.ListAlarms()
    alarm_list = response['CurrentAlarmList']
    tree = XML.fromstring(alarm_list.encode('utf-8'))

    # An alarm list looks like this:
    # <Alarms>
    #     <Alarm ID="14" StartTime="07:00:00"
    #         Duration="02:00:00" Recurrence="DAILY" Enabled="1"
    #         RoomUUID="RINCON_000ZZZZZZ1400"
    #         ProgramURI="x-rincon-buzzer:0" ProgramMetaData=""
    #         PlayMode="SHUFFLE_NOREPEAT" Volume="25"
    #         IncludeLinkedZones="0"/>
    #     <Alarm ID="15" StartTime="07:00:00"
    #         Duration="02:00:00" Recurrence="DAILY" Enabled="1"
    #         RoomUUID="RINCON_000ZZZZZZ01400"
    #         ProgramURI="x-rincon-buzzer:0" ProgramMetaData=""
    #         PlayMode="SHUFFLE_NOREPEAT" Volume="25"
    #          IncludeLinkedZones="0"/>
    # </Alarms>

    # pylint: disable=protected-access
    alarms = tree.findall('Alarm')
    result = set()
    for alarm in alarms:
        values = alarm.attrib
        alarm_id = values['ID']
        # If an instance already exists for this ID, update and return it.
        # Otherwise, create a new one and populate its values
        if Alarm._all_alarms.get(alarm_id):
            instance = Alarm._all_alarms.get(alarm_id)
        else:
            instance = Alarm(None)
            instance._alarm_id = alarm_id
            Alarm._all_alarms[instance._alarm_id] = instance

        instance.start_time = datetime.strptime(
            values['StartTime'], "%H:%M:%S").time()  # NB StartTime, not
        # StartLocalTime, which is used by CreateAlarm
        instance.duration = None if values['Duration'] == '' else\
            datetime.strptime(values['Duration'], "%H:%M:%S").time()
        instance.recurrence = values['Recurrence']
        instance.enabled = values['Enabled'] == '1'
        instance.zone = [z for z in zone.all_zones
                         if z.uid == values['RoomUUID']][0]
        instance.program_uri = None if values['ProgramURI'] ==\
            "x-rincon-buzzer:0" else values['ProgramURI']
        instance.program_metadata = values['ProgramMetaData']
        instance.play_mode = values['PlayMode']
        instance.volume = values['Volume']
        instance.include_linked_zones = values['IncludeLinkedZones'] == '1'

        result.add(instance)
    return result
<commit_msg>don't throw exception if alarm is not associated to any room<commit_after># -*- coding: utf-8 -*-

"""This module contains classes relating to Sonos Alarms."""

from __future__ import unicode_literals

import logging
import re
import weakref
from datetime import datetime

from . import discovery
from .core import PLAY_MODES
from .xml import XML

log = logging.getLogger(__name__)  # pylint: disable=C0103
TIME_FORMAT = "%H:%M:%S"

def is_valid_recurrence(text):
    """Check that ``text`` is a valid recurrence string.

    A valid recurrence string is  ``DAILY``, ``ONCE``, ``WEEKDAYS``,
    ``WEEKENDS`` or of the form ``ON_DDDDDD`` where ``D`` is a number from 0-7
    representing a day of the week (Sunday is 0), e.g. ``ON_034`` meaning
    Sunday, Wednesday and Thursday

    Args:
        text (str): the recurrence string to check.

    Returns:
        bool: `True` if the recurrence string is valid, else `False`.

    Examples:

        >>> from soco.alarms import is_valid_recurrence
        >>> is_valid_recurrence('WEEKENDS')
        True
        >>> is_valid_recurrence('')
        False
        >>> is_valid_recurrence('ON_132')  # Mon, Tue, Wed
        True
        >>> is_valid_recurrence('ON_777')  # Sat
        True
        >>> is_valid_recurrence('ON_3421') # Mon, Tue, Wed, Thur
        True
        >>> is_valid_recurrence('ON_123456789') # Too many digits
        False
    """
    if text in ("DAILY", "ONCE", "WEEKDAYS", "WEEKENDS"):
        return True
    return re.search(r'^ON_[0-7]{1,7}$', text) is not None

class Alarm(object):

    """A class representing a Sonos Alarm.

    Alarms may be created or updated and saved to, or removed from the Sonos
    system. An alarm is not automatically saved. Call `save()` to do that.

    Example:

        >>> device = discovery.any_soco()
        >>> # create an alarm with default properties
        >>> alarm = Alarm(device)
        >>> print alarm.volume
        20
        >>> print get_alarms()
        set([])
        >>> # save the alarm to the Sonos system
        >>> alarm.save()
        >>> print get_alarms()
        set([<Alarm id:88@15:26:15 at 0x107abb090>])
        >>> # update the alarm
        >>> alarm.recurrence = "ONCE"
        >>> # Save it again for the change to take effect
        >>> alarm.save()
        >>> # Remove it
        >>> alarm.remove()
        >>> print get_alarms()
        set([])
    """
    # pylint: disable=too-many-instance-attributes

    _all_alarms = weakref.WeakValueDictionary()

    # pylint: disable=too-many-arguments
    def __init__(
            self, zone, start_time=None, duration=None,
            recurrence='DAILY', enabled=True,
            program_uri=None, program_metadata='',
            play_mode='NORMAL', volume=20, include_linked_zones=False):
        """
        Args:
            zone (`SoCo`): The soco instance which will play the alarm.
            start_time (`datetime.time`, optional): The alarm's start time.
                Specify hours, minutes and seconds only. Defaults to the
                current time.
            duration (`datetime.time`, optional): The alarm's duration. Specify
                hours, minutes and seconds only. May be `None` for unlimited
                duration. Defaults to `None`.
            recurrence (str, optional): A string representing how
                often the alarm should be triggered. Can be ``DAILY``,
                ``ONCE``, ``WEEKDAYS``, ``WEEKENDS`` or of the form
                ``ON_DDDDDD`` where ``D`` is a number from 0-7 representing a
                day of the week (Sunday is 0), e.g. ``ON_034`` meaning Sunday,
                Wednesday and Thursday. Defaults to ``DAILY``.
            enabled (bool, optional): `True` if alarm is enabled, `False`
                otherwise. Defaults to `True`.
            program_uri(str, optional): The uri to play. If `None`, the
                built-in Sonos chime sound will be used. Defaults to `None`.
            program_metadata (str, optional): The metadata associated with
                `program_uri`. Defaults to ''.
            play_mode(str, optional): The play mode for the alarm. Can be one
                of ``NORMAL``, ``SHUFFLE_NOREPEAT``, ``SHUFFLE``,
                ``REPEAT_ALL``, ``REPEAT_ONE``, ``SHUFFLE_REPEAT_ONE``.
                Defaults to ``NORMAL``.
            volume (int, optional): The alarm's volume (0-100). Defaults to 20.
            include_linked_zones (bool, optional): `True` if the alarm should
                be played on the other speakers in the same group, `False`
                otherwise. Defaults to `False`.
        """

        super(Alarm, self).__init__()
        self.zone = zone
        if start_time is None:
            start_time = datetime.now().time()
        #: `datetime.time`: The alarm's start time.
        self.start_time = start_time
        #: `datetime.time`: The alarm's duration.
        self.duration = duration
        self._recurrence = recurrence
        #: `bool`: `True` if the alarm is enabled, else `False`.
        self.enabled = enabled
        #:
        self.program_uri = program_uri
        #: `str`: The uri to play.
        self.program_metadata = program_metadata
        self._play_mode = play_mode
        self._volume = volume
        #: `bool`: `True` if the alarm should be played on the other speakers
        #: in the same group, `False` otherwise.
        self.include_linked_zones = include_linked_zones
        self._alarm_id = None

    def __repr__(self):
        middle = str(self.start_time.strftime(TIME_FORMAT))
        return "<{0} id:{1}@{2} at {3}>".format(
            self.__class__.__name__, self._alarm_id, middle, hex(id(self)))

    @property
    def play_mode(self):
        """
        `str`: The play mode for the alarm.

            Can be one of ``NORMAL``, ``SHUFFLE_NOREPEAT``, ``SHUFFLE``,
            ``REPEAT_ALL``, ``REPEAT_ONE``, ``SHUFFLE_REPEAT_ONE``.
        """
        return self._play_mode

    @play_mode.setter
    def play_mode(self, play_mode):
        """See `playmode`."""
        play_mode = play_mode.upper()
        if play_mode not in PLAY_MODES:
            raise KeyError("'%s' is not a valid play mode" % play_mode)
        self._play_mode = play_mode

    @property
    def volume(self):
        """`int`: The alarm's volume (0-100)."""
        return self._volume

    @volume.setter
    def volume(self, volume):
        """See `volume`."""
        # max 100
        volume = int(volume)
        self._volume = max(0, min(volume, 100))  # Coerce in range

    @property
    def recurrence(self):
        """`str`: How often the alarm should be triggered.

        Can be ``DAILY``, ``ONCE``, ``WEEKDAYS``, ``WEEKENDS`` or of the form
        ``ON_DDDDDDD`` where ``D`` is a number from 0-7 representing a day of
        the week (Sunday is 0), e.g. ``ON_034`` meaning Sunday, Wednesday and
        Thursday.
        """
        return self._recurrence

    @recurrence.setter
    def recurrence(self, recurrence):
        """See `recurrence`."""
        if not is_valid_recurrence(recurrence):
            raise KeyError("'%s' is not a valid recurrence value" % recurrence)

        self._recurrence = recurrence

    def save(self):
        """Save the alarm to the Sonos system.

        Raises:
            ~soco.exceptions.SoCoUPnPException: if the alarm cannot be created
                because there
                is already an alarm for this room at the specified time.
        """
        # pylint: disable=bad-continuation
        args = [
            ('StartLocalTime', self.start_time.strftime(TIME_FORMAT)),
            ('Duration', '' if self.duration is None else
                self.duration.strftime(TIME_FORMAT)),
            ('Recurrence', self.recurrence),
            ('Enabled', '1' if self.enabled else '0'),
            ('RoomUUID', self.zone.uid),
            ('ProgramURI', "x-rincon-buzzer:0" if self.program_uri is None
                else self.program_uri),
            ('ProgramMetaData', self.program_metadata),
            ('PlayMode', self.play_mode),
            ('Volume', self.volume),
            ('IncludeLinkedZones', '1' if self.include_linked_zones else '0')
        ]
        if self._alarm_id is None:
            response = self.zone.alarmClock.CreateAlarm(args)
            self._alarm_id = response['AssignedID']
            Alarm._all_alarms[self._alarm_id] = self
        else:
            # The alarm has been saved before. Update it instead.
            args.insert(0, ('ID', self._alarm_id))
            self.zone.alarmClock.UpdateAlarm(args)

    def remove(self):
        """Remove the alarm from the Sonos system.

        There is no need to call `save`. The Python instance is not deleted,
        and can be saved back to Sonos again if desired.
        """
        self.zone.alarmClock.DestroyAlarm([
            ('ID', self._alarm_id)
        ])
        alarm_id = self._alarm_id
        try:
            del Alarm._all_alarms[alarm_id]
        except KeyError:
            pass
        self._alarm_id = None

def get_alarms(zone=None):
    """Get a set of all alarms known to the Sonos system.

    Args:
        zone (`SoCo`, optional): a SoCo instance to query. If None, a random
            instance is used. Defaults to `None`.

    Returns:
        set: A set of `Alarm` instances

    Note:
        Any existing `Alarm` instance will have its attributes updated to those
        currently stored on the Sonos system.
    """
    # Get a soco instance to query. It doesn't matter which.
    if zone is None:
        zone = discovery.any_soco()
    response = zone.alarmClock.ListAlarms()
    alarm_list = response['CurrentAlarmList']
    tree = XML.fromstring(alarm_list.encode('utf-8'))

    # An alarm list looks like this:
    # <Alarms>
    #     <Alarm ID="14" StartTime="07:00:00"
    #         Duration="02:00:00" Recurrence="DAILY" Enabled="1"
    #         RoomUUID="RINCON_000ZZZZZZ1400"
    #         ProgramURI="x-rincon-buzzer:0" ProgramMetaData=""
    #         PlayMode="SHUFFLE_NOREPEAT" Volume="25"
    #         IncludeLinkedZones="0"/>
    #     <Alarm ID="15" StartTime="07:00:00"
    #         Duration="02:00:00" Recurrence="DAILY" Enabled="1"
    #         RoomUUID="RINCON_000ZZZZZZ01400"
    #         ProgramURI="x-rincon-buzzer:0" ProgramMetaData=""
    #         PlayMode="SHUFFLE_NOREPEAT" Volume="25"
    #          IncludeLinkedZones="0"/>
    # </Alarms>

    # pylint: disable=protected-access
    alarms = tree.findall('Alarm')
    result = set()
    for alarm in alarms:
        values = alarm.attrib
        alarm_id = values['ID']
        # If an instance already exists for this ID, update and return it.
        # Otherwise, create a new one and populate its values
        if Alarm._all_alarms.get(alarm_id):
            instance = Alarm._all_alarms.get(alarm_id)
        else:
            instance = Alarm(None)
            instance._alarm_id = alarm_id
            Alarm._all_alarms[instance._alarm_id] = instance

        instance.start_time = datetime.strptime(
            values['StartTime'], "%H:%M:%S").time()  # NB StartTime, not
        # StartLocalTime, which is used by CreateAlarm
        instance.duration = None if values['Duration'] == '' else\
            datetime.strptime(values['Duration'], "%H:%M:%S").time()
        instance.recurrence = values['Recurrence']
        instance.enabled = values['Enabled'] == '1'
        instance.zone = next((z for z in zone.all_zones
                         if z.uid == values['RoomUUID']), None)
        # some alarms are not associated to zones -> filter these out
        if instance.zone is None:
            continue
        instance.program_uri = None if values['ProgramURI'] ==\
            "x-rincon-buzzer:0" else values['ProgramURI']
        instance.program_metadata = values['ProgramMetaData']
        instance.play_mode = values['PlayMode']
        instance.volume = values['Volume']
        instance.include_linked_zones = values['IncludeLinkedZones'] == '1'

        result.add(instance)
    return result
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

class ZoneGroup(object):
    """docstring for Group"""
    def __init__(self, uid, coordinator, members = None):
        self.uid = uid
        self.coordinator = coordinator
        if members is not None:
            self.members = set(members)
        else:
            self.members = set()

    def __iter__(self):
        return self.members.__iter__()

    def __contains__(self, member):
        return member in self.members

    def __repr__(self):
        return "{}(uid='{}', coordinator='{!r}', members={!r})".format(
            self.__class__.__name__, self.uid, self.coordinator, self.members)

<commit_msg>Remove quotes from __repr__<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

class ZoneGroup(object):
    """docstring for Group"""
    def __init__(self, uid, coordinator, members = None):
        self.uid = uid
        self.coordinator = coordinator
        if members is not None:
            self.members = set(members)
        else:
            self.members = set()

    def __iter__(self):
        return self.members.__iter__()

    def __contains__(self, member):
        return member in self.members

    def __repr__(self):
        return "{}(uid='{}', coordinator={!r}, members={!r})".format(
            self.__class__.__name__, self.uid, self.coordinator, self.members)

<|endoftext|>


<commit_before>#!/usr/bin/python

from sys import argv, stderr

BLOCK, FREE, GOAL, MAN, WALL = range(5)

class Cell(object):
    def __init__(self, cell_type):
        self.cell_type = cell_type
        self.in_use    = cell_type == GOAL

    def __str__(self):
        if   self.cell_type == BLOCK: return "$"
        elif self.cell_type == FREE : return " "
        elif self.cell_type == GOAL : return "."
        elif self.cell_type == MAN  : return "@"
        elif self.cell_type == WALL : return "#"

    def get_type(self):
        return self.cell_type

    def get_clean_type(self):
        return (FREE if self.cell_type == GOAL else self.cell_type)

    def get_use(self):
        return self.in_use

    def set_use(self, value):
        self.in_use = value

    def is_goal(self):
        return self.cell_type == GOAL

class Screen(object):
    def __init__(self):
        self.screen = [[]]

    def __str__(self):
        screen = ""

        for l in self.screen:
            for p in l:
                screen += str(p)

            screen += "\n"

        return screen

    def append_column(self, row, cell):
        for i in range(len(self.screen), row + 1):
            self.screen.append([])

        self.screen[row].append(cell)

    def used_iteration(self):
        screen  = self.screen
        changed = False

        for i in range(len(self.screen)):
            for j in range(len(screen[i])):
                if screen[i][j].get_use() or screen[i][j].get_type() == WALL:
                    continue

                if j - 1 >= 0 \
                        and screen[i][j - 1].get_use():
                    screen[i][j].set_use(True)
                    changed = True
                elif j + 1 < len(screen[i]) \
                        and screen[i][j + 1].get_use():
                    screen[i][j].set_use(True)
                    changed = True
                elif i - 1 >= 0 and j < len(screen[i - 1]) \
                        and screen[i - 1][j].get_use():
                    screen[i][j].set_use(True)
                    changed = True
                elif i + 1 < len(screen) and j < len(screen[i + 1]) \
                        and screen[i + 1][j].get_use():
                    screen[i][j].set_use(True)
                    changed = True

        return changed

    def mark_used(self):
        changed = True

        while changed:
            changed = self.used_iteration()

    def print_state(self):
        print "begin state"

        screen = self.screen
        string = ""

        for i in range(len(screen)):
            for j in range(len(screen[i])):
                if screen[i][j].get_use():
                    string += "field_" + str(i) + "_" + str(j)
                    string += ":state_type "

        print string[:len(string) - 1]
        print "end state"

    def print_edge(self):
        print "begin edge"
        print "action:action_type"
        print "end edge"

    def print_init(self):
        print "begin init"

        screen = self.screen
        string = ""

        for i in range(len(screen)):
            for j in range(len(screen[i])):
                if screen[i][j].get_use():
                    string += str(screen[i][j].get_clean_type()) + " "

        print string[:len(string) - 1]
        print "end init"

    def print_move(self, i_man, j_man, i_free, j_free):
        string = ""

        for k in range(len(self.screen)):
            for l in range(len(self.screen[k])):
                if not self.screen[k][l].get_use():
                    continue

                if k == i_man and l == j_man:
                    string += str(MAN) + "/" + str(FREE) + " "
                elif k == i_free and l == j_free:
                    string += str(FREE) + "/" + str(MAN) + " "
                else:
                    string += "* "

        string += "0"
        print string

    def print_moves(self, i, j):
        screen = self.screen

        if j - 1 >= 0 \
                and screen[i][j - 1].get_use():
            print "begin trans"
            self.print_move(i, j, i, j - 1)
            print "end trans"

        if j + 1 < len(screen[i]) \
                and screen[i][j + 1].get_use():
            print "begin trans"
            self.print_move(i, j, i, j + 1)
            print "end trans"

        if i - 1 >= 0 and j < len(screen[i - 1]) \
                and screen[i - 1][j].get_use():
            print "begin trans"
            self.print_move(i, j, i - 1, j)
            print "end trans"

        if i + 1 < len(screen) and j < len(screen[i + 1]) \
                and screen[i + 1][j].get_use():
            print "begin trans"
            self.print_move(i, j, i + 1, j)
            print "end trans"

    def print_push(self, i_man, j_man, i_block, j_block, i_free, j_free):
        string = ""

        for k in range(len(self.screen)):
            for l in range(len(self.screen[k])):
                if not self.screen[k][l].get_use():
                    continue

                if k == i_man and l == j_man:
                    string += str(MAN) + "/" + str(FREE) + " "
                elif k == i_block and l == j_block:
                    string += str(BLOCK) + "/" + str(MAN) + " "
                elif k == i_free and l == j_free:
                    string += str(FREE) + "/" + str(BLOCK) + " "
                else:
                    string += "* "

        string += "0"
        print string

    def print_pushes(self, i, j):
        screen = self.screen

        if j - 2 >= 0 and j - 1 >= 0 \
                and screen[i][j - 2].get_use() and screen[i][j - 1].get_use():
            print "begin trans"
            self.print_push(i, j, i, j - 1, i, j - 2)
            print "end trans"

        if j + 1 < len(screen[i]) and j + 2 < len(screen[i]) \
                and screen[i][j + 1].get_use() and screen[i][j + 2].get_use():
            print "begin trans"
            self.print_push(i, j, i, j + 1, i, j + 2)
            print "end trans"

        if i - 1 >= 0 and i - 2 >= 0 \
                and j < len(screen[i - 1]) and j < len(screen[i - 2]) \
                and screen[i - 1][j].get_use() and screen[i - 2][j].get_use():
            print "begin trans"
            self.print_push(i, j, i - 1, j, i - 2, j)
            print "end trans"

        if i + 1 < len(screen) and i + 2 < len(screen) \
                and j < len(screen[i + 1]) and j < len(screen[i + 2]) \
                and screen[i + 1][j].get_use() and screen[i + 2][j].get_use():
            print "begin trans"
            self.print_push(i, j, i + 1, j, i + 2, j)
            print "end trans"

    def print_finished(self):
        print "begin trans"

        string = ""

        for i in range(len(self.screen)):
            for j in range(len(self.screen[i])):
                if self.screen[i][j].get_use():
                    if self.screen[i][j].is_goal():
                        string += str(BLOCK) + "/" + str(BLOCK) + " "
                    else:
                        string += "* "

        string += "1"
        print string
        print "end trans"

    def print_trans(self):
        for i in range(len(self.screen)):
            for j in range(len(self.screen[i])):
                if self.screen[i][j].get_use():
                    self.print_moves(i, j)
                    self.print_pushes(i, j)

        self.print_finished()

    def print_sorts(self):
        print "begin sort state_type"
        print "\"block\""
        print "\"free\""
        print "\"goal\""
        print "\"man\""
        print "\"wall\""
        print "end sort"

        print "begin sort action_type"
        print "\"step\""
        print "\"finished\""
        print "end sort"

def parse_screen(file_name):
    f = open(argv[1], 'rb')
    d = f.read()
    f.close()

    row = 0

    screen = Screen()

    for c in d:
        if c == '\n':
            row += 1
        elif c == '\r':
            continue
        else:
            if   c == '$': cell = Cell(BLOCK)
            elif c == ' ': cell = Cell(FREE)
            elif c == '.': cell = Cell(GOAL)
            elif c == '@': cell = Cell(MAN)
            elif c == '#': cell = Cell(WALL)
            else:
                stderr.write("Invalid symbol '" + c + "' encountered\n")
                exit(1)
            screen.append_column(row, cell)

    return screen

def usage():
    stderr.write("Usage: " + argv[0] + " <sokoban screen>\n")
    exit(1)

def main():
    if len(argv) != 2:
        usage()

    screen = parse_screen(argv[1])
    screen.mark_used()

    screen.print_state()
    screen.print_edge()
    screen.print_init()
    screen.print_trans()
    screen.print_sorts()

main()
<commit_msg>Add copyright<commit_after>#!/usr/bin/python
#
# Copyright (c) 2011, Jeroen Ketema, University of Twente
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  * Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
#  * Neither the name of the University of Twente nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from sys import argv, stderr

BLOCK, FREE, GOAL, MAN, WALL = range(5)

class Cell(object):
    def __init__(self, cell_type):
        self.cell_type = cell_type
        self.in_use    = cell_type == GOAL

    def __str__(self):
        if   self.cell_type == BLOCK: return "$"
        elif self.cell_type == FREE : return " "
        elif self.cell_type == GOAL : return "."
        elif self.cell_type == MAN  : return "@"
        elif self.cell_type == WALL : return "#"

    def get_type(self):
        return self.cell_type

    def get_clean_type(self):
        return (FREE if self.cell_type == GOAL else self.cell_type)

    def get_use(self):
        return self.in_use

    def set_use(self, value):
        self.in_use = value

    def is_goal(self):
        return self.cell_type == GOAL

class Screen(object):
    def __init__(self):
        self.screen = [[]]

    def __str__(self):
        screen = ""

        for l in self.screen:
            for p in l:
                screen += str(p)

            screen += "\n"

        return screen

    def append_column(self, row, cell):
        for i in range(len(self.screen), row + 1):
            self.screen.append([])

        self.screen[row].append(cell)

    def used_iteration(self):
        screen  = self.screen
        changed = False

        for i in range(len(self.screen)):
            for j in range(len(screen[i])):
                if screen[i][j].get_use() or screen[i][j].get_type() == WALL:
                    continue

                if j - 1 >= 0 \
                        and screen[i][j - 1].get_use():
                    screen[i][j].set_use(True)
                    changed = True
                elif j + 1 < len(screen[i]) \
                        and screen[i][j + 1].get_use():
                    screen[i][j].set_use(True)
                    changed = True
                elif i - 1 >= 0 and j < len(screen[i - 1]) \
                        and screen[i - 1][j].get_use():
                    screen[i][j].set_use(True)
                    changed = True
                elif i + 1 < len(screen) and j < len(screen[i + 1]) \
                        and screen[i + 1][j].get_use():
                    screen[i][j].set_use(True)
                    changed = True

        return changed

    def mark_used(self):
        changed = True

        while changed:
            changed = self.used_iteration()

    def print_state(self):
        print "begin state"

        screen = self.screen
        string = ""

        for i in range(len(screen)):
            for j in range(len(screen[i])):
                if screen[i][j].get_use():
                    string += "field_" + str(i) + "_" + str(j)
                    string += ":state_type "

        print string[:len(string) - 1]
        print "end state"

    def print_edge(self):
        print "begin edge"
        print "action:action_type"
        print "end edge"

    def print_init(self):
        print "begin init"

        screen = self.screen
        string = ""

        for i in range(len(screen)):
            for j in range(len(screen[i])):
                if screen[i][j].get_use():
                    string += str(screen[i][j].get_clean_type()) + " "

        print string[:len(string) - 1]
        print "end init"

    def print_move(self, i_man, j_man, i_free, j_free):
        string = ""

        for k in range(len(self.screen)):
            for l in range(len(self.screen[k])):
                if not self.screen[k][l].get_use():
                    continue

                if k == i_man and l == j_man:
                    string += str(MAN) + "/" + str(FREE) + " "
                elif k == i_free and l == j_free:
                    string += str(FREE) + "/" + str(MAN) + " "
                else:
                    string += "* "

        string += "0"
        print string

    def print_moves(self, i, j):
        screen = self.screen

        if j - 1 >= 0 \
                and screen[i][j - 1].get_use():
            print "begin trans"
            self.print_move(i, j, i, j - 1)
            print "end trans"

        if j + 1 < len(screen[i]) \
                and screen[i][j + 1].get_use():
            print "begin trans"
            self.print_move(i, j, i, j + 1)
            print "end trans"

        if i - 1 >= 0 and j < len(screen[i - 1]) \
                and screen[i - 1][j].get_use():
            print "begin trans"
            self.print_move(i, j, i - 1, j)
            print "end trans"

        if i + 1 < len(screen) and j < len(screen[i + 1]) \
                and screen[i + 1][j].get_use():
            print "begin trans"
            self.print_move(i, j, i + 1, j)
            print "end trans"

    def print_push(self, i_man, j_man, i_block, j_block, i_free, j_free):
        string = ""

        for k in range(len(self.screen)):
            for l in range(len(self.screen[k])):
                if not self.screen[k][l].get_use():
                    continue

                if k == i_man and l == j_man:
                    string += str(MAN) + "/" + str(FREE) + " "
                elif k == i_block and l == j_block:
                    string += str(BLOCK) + "/" + str(MAN) + " "
                elif k == i_free and l == j_free:
                    string += str(FREE) + "/" + str(BLOCK) + " "
                else:
                    string += "* "

        string += "0"
        print string

    def print_pushes(self, i, j):
        screen = self.screen

        if j - 2 >= 0 and j - 1 >= 0 \
                and screen[i][j - 2].get_use() and screen[i][j - 1].get_use():
            print "begin trans"
            self.print_push(i, j, i, j - 1, i, j - 2)
            print "end trans"

        if j + 1 < len(screen[i]) and j + 2 < len(screen[i]) \
                and screen[i][j + 1].get_use() and screen[i][j + 2].get_use():
            print "begin trans"
            self.print_push(i, j, i, j + 1, i, j + 2)
            print "end trans"

        if i - 1 >= 0 and i - 2 >= 0 \
                and j < len(screen[i - 1]) and j < len(screen[i - 2]) \
                and screen[i - 1][j].get_use() and screen[i - 2][j].get_use():
            print "begin trans"
            self.print_push(i, j, i - 1, j, i - 2, j)
            print "end trans"

        if i + 1 < len(screen) and i + 2 < len(screen) \
                and j < len(screen[i + 1]) and j < len(screen[i + 2]) \
                and screen[i + 1][j].get_use() and screen[i + 2][j].get_use():
            print "begin trans"
            self.print_push(i, j, i + 1, j, i + 2, j)
            print "end trans"

    def print_finished(self):
        print "begin trans"

        string = ""

        for i in range(len(self.screen)):
            for j in range(len(self.screen[i])):
                if self.screen[i][j].get_use():
                    if self.screen[i][j].is_goal():
                        string += str(BLOCK) + "/" + str(BLOCK) + " "
                    else:
                        string += "* "

        string += "1"
        print string
        print "end trans"

    def print_trans(self):
        for i in range(len(self.screen)):
            for j in range(len(self.screen[i])):
                if self.screen[i][j].get_use():
                    self.print_moves(i, j)
                    self.print_pushes(i, j)

        self.print_finished()

    def print_sorts(self):
        print "begin sort state_type"
        print "\"block\""
        print "\"free\""
        print "\"goal\""
        print "\"man\""
        print "\"wall\""
        print "end sort"

        print "begin sort action_type"
        print "\"step\""
        print "\"finished\""
        print "end sort"

def parse_screen(file_name):
    f = open(argv[1], 'rb')
    d = f.read()
    f.close()

    row = 0

    screen = Screen()

    for c in d:
        if c == '\n':
            row += 1
        elif c == '\r':
            continue
        else:
            if   c == '$': cell = Cell(BLOCK)
            elif c == ' ': cell = Cell(FREE)
            elif c == '.': cell = Cell(GOAL)
            elif c == '@': cell = Cell(MAN)
            elif c == '#': cell = Cell(WALL)
            else:
                stderr.write("Invalid symbol '" + c + "' encountered\n")
                exit(1)
            screen.append_column(row, cell)

    return screen

def usage():
    stderr.write("Usage: " + argv[0] + " <sokoban screen>\n")
    exit(1)

def main():
    if len(argv) != 2:
        usage()

    screen = parse_screen(argv[1])
    screen.mark_used()

    screen.print_state()
    screen.print_edge()
    screen.print_init()
    screen.print_trans()
    screen.print_sorts()

main()
<|endoftext|>


<commit_before>#!/usr/bin/python

###########################################################################################################
#
# This script downloads images and other media files from 4chan threads.
# You only need to have python installed in your machine
# The command line takes two mandatory arguments : channel name & thread (in that order)
# Optional arguments are --ftype (yes or no) that appends the file type to file name (not recommended)
# and --limit (integer) that limits the number of downloaded files to save space or bandwidth
#
# Author : Shantanu S. Bhattacharyya
# Date : Nov 27, 2015
#
############################################################################################################

import re
import urllib
import urllib2
import sys
import os

import optparse
parser = optparse.OptionParser()

parser.add_option('--ftype', action="store_true", default=False)
parser.add_option('--limit', action="store", dest="limit", type="int", default=100)
options, args = parser.parse_args()

if len(sys.argv) < 3:
	print "Not enough arguments \nUsage : python 4chan_getthread.py channel threadnumber\nExample : python 4chan_getthread.py hr 2463159"
	exit()
idtype = ["jpg" , "jpg ", "png" , "png ", "gif", "gif ", "webm", "webm "]
count = 1
k = ""
empty = 1

path = "./"+ sys.argv[1] + str(sys.argv[2])
if not os.path.exists(path):
	os.makedirs(path)
os.chdir(path)

f1 = urllib2.urlopen('http://boards.4chan.org/' + sys.argv[1] + "/thread/" + str(sys.argv[2])  )
words = f1.read().split("\"")
fout = open("temp.txt" , "w")
for k in words:
	fout.write(k)
f1.close()
fout.close()

f2 = open("temp.txt", "r")
for i in words:

	if re.search("^//i.4cdn.+", i) :
		img = i.split("/")

        	if img[2] == "i.4cdn.org":
			if img[4].split()[0] != sys.argv[1]:
				idx = img[4].split(".")
				ext = idx[1][0:3]
                	if len(idx) == 2 and ext in idtype :
				name = idx[0] + "." + ext
				name2 = idx[0][0:-1] + "." + ext

				if os.path.isfile(name) or os.path.isfile(name2) or os.path.isfile(idx[0]) or os.path.isfile(idx[0][0:-1]):
                                        print name, "exists"
					empty = 0
				else:
					command = "wget https://i.4cdn.org/" + sys.argv[1] + "/" + idx[0] + "." + ext
					os.system(command)
					if options.ftype == False:
						os.system("mv "+ name + " " + idx[0])
					count += 1
					if count > options.limit :
						break
if(count > 1):
	print "\nAll Images Downloaded \n"
        os.chdir("../")
else:
        print "\nNo Image to Download \n"
        os.chdir("../")
	if empty == 1:
        	os.rmdir(sys.argv[1]+str(sys.argv[2]))
<commit_msg>Raised default limit<commit_after>#!/usr/bin/python

###########################################################################################################
#
# This script downloads images and other media files from 4chan threads.
# You only need to have python installed in your machine
# The command line takes two mandatory arguments : channel name & thread (in that order)
# Optional arguments are --ftype (yes or no) that appends the file type to file name (not recommended)
# and --limit (integer) that limits the number of downloaded files to save space or bandwidth
#
# Author : Shantanu S. Bhattacharyya
# Date : Nov 27, 2015
#
############################################################################################################

import re
import urllib
import urllib2
import sys
import os

import optparse
parser = optparse.OptionParser()

parser.add_option('--ftype', action="store_true", default=False)
parser.add_option('--limit', action="store", dest="limit", type="int", default=200)
options, args = parser.parse_args()

if len(sys.argv) < 3:
	print "Not enough arguments \nUsage : python 4chan_getthread.py channel threadnumber\nExample : python 4chan_getthread.py hr 2463159"
	exit()
idtype = ["jpg" , "jpg ", "png" , "png ", "gif", "gif ", "webm", "webm "]
count = 1
k = ""
empty = 1

path = "./"+ sys.argv[1] + str(sys.argv[2])
if not os.path.exists(path):
	os.makedirs(path)
os.chdir(path)

f1 = urllib2.urlopen('http://boards.4chan.org/' + sys.argv[1] + "/thread/" + str(sys.argv[2])  )
words = f1.read().split("\"")
fout = open("temp.txt" , "w")
for k in words:
	fout.write(k)
f1.close()
fout.close()

f2 = open("temp.txt", "r")
for i in words:

	if re.search("^//i.4cdn.+", i) :
		img = i.split("/")

        	if img[2] == "i.4cdn.org":
			if img[4].split()[0] != sys.argv[1]:
				idx = img[4].split(".")
				ext = idx[1][0:3]
                	if len(idx) == 2 and ext in idtype :
				name = idx[0] + "." + ext
				name2 = idx[0][0:-1] + "." + ext

				if os.path.isfile(name) or os.path.isfile(name2) or os.path.isfile(idx[0]) or os.path.isfile(idx[0][0:-1]):
                                        print name, "exists"
					empty = 0
				else:
					command = "wget https://i.4cdn.org/" + sys.argv[1] + "/" + idx[0] + "." + ext
					os.system(command)
					if options.ftype == False:
						os.system("mv "+ name + " " + idx[0])
					count += 1
					if count > options.limit :
						break
if(count > 1):
	print "\nAll Images Downloaded \n"
	os.remove("temp.txt")
        os.chdir("../")
else:
        print "\nNo Image to Download \n"
	os.remove("temp.txt")
        os.chdir("../")
	if empty == 1:
        	os.rmdir(sys.argv[1]+str(sys.argv[2]))
<|endoftext|>


<commit_before>#!/usr/bin/env python
import argparse
from collections import OrderedDict
import itertools
import sys
errors=[]
try:
    from palettable.colorbrewer.qualitative import Set3_12
except ImportError as ie:
    errors.append("No module named palettable")
try:
    import matplotlib as mpl
    from mpl_toolkits.mplot3d import Axes3D
except ImportError as ie:
    errors.append(ie)
if len(errors) != 0:
    for item in errors:
        print "Import Error:", item
    sys.exit()

from pylab import *
from phylotoast import util, graph_util as gu

def handle_program_options():
    parser = argparse.ArgumentParser(description="Create a 2D or 3D PCoA plot.\
                                     By default, this script opens a window\
                                     with the plot displayed if you want to\
                                     change certain aspects of the plot (such\
                                     as rotate the view in 3D mode). If the -o\
                                     option is specified, the plot will be\
                                     saved directly to an image without\
                                     the initial display window.")
    parser.add_argument("-i", "--coord_fp", required=True,
                        help="Input principal coordinates filepath (i.e.,\
                        resulting file from principal_coordinates.py)\
                        [REQUIRED].")
    parser.add_argument("-m", "--map_fp", required=True,
                        help="Input metadata mapping filepath [REQUIRED].")
    parser.add_argument("-b", "--colorby", required=True,
                        help="Any mapping categories, such as treatment type, \
                              that will be used to group the data in the \
                              output iTol table. For example, one category \
                              with three types will result in three data \
                              columns in the final output. Two categories with\
                              three types each will result in six data \
                              columns. Default is no categories and all the \
                              data will be treated as a single group.")
    parser.add_argument("-d", "--dimensions", default=2, type=int,
                        choices=[2, 3],
                        help="Choose whether to plot 2D or 3D.")
    parser.add_argument("-c", "--colors", default=None,
                        help="A column name in the mapping file containing\
                              hexadecimal (#FF0000) color values that will\
                              be used to color the groups. Each sample ID must\
                              have a color entry.")
    parser.add_argument("-s", "--point_size", default=100, type=int,
                        help="Specify the size of the circles representing each\
                        of the samples in the plot")
    parser.add_argument("--pc_order", default=[1,2], type=int, nargs=2,
                        help="Choose which Principle Coordinates are displayed\
                              and in which order, for example: 1 2. This option\
                              is only used when a 2D plot is specified.")
    parser.add_argument("--x_limits", type=float, nargs=2,
                        help="Specify limits for the x-axis instead of\
                        automatic setting based on the data range. Should\
                        take the form: --x_limits -0.5 0.5")
    parser.add_argument("--y_limits", type=float, nargs=2,
                        help="Specify limits for the y-axis instead of\
                        automatic setting based on the data range. Should\
                        take the form: --y_limits -0.5 0.5")
    parser.add_argument("--z_limits", type=float, nargs=2,
                        help="Specify limits for the z-axis instead of\
                        automatic setting based on the data range. Should\
                        take the form: --z_limits -0.5 0.5")
    parser.add_argument("--z_angles", type=float, nargs=2, default=[-134.5, 23.],
                        help="Specify the azimuth and elevation angles for a 3D plot.")
    parser.add_argument("-t", "--title", default="", help="Title of the plot.")
    parser.add_argument("--figsize", default=[14, 8], type=int, nargs=2,
                        help="Set plot quality in Dots Per Inch (DPI). Larger\
                              DPI will result in larger file size.")
    parser.add_argument("--font_size", default=12, type=int,
                        help="Sets the font size for text elements in the plot.")
    parser.add_argument("--label_padding", default=15, type=int,
                        help="Sets the spacing in points between the each axis\
                              and its label.")
    parser.add_argument("--annotate_points", action="store_true",
                        help="If specified, each graphed point will be\
                              labeled with its sample ID.")
    parser.add_argument("--ggplot2_style", action="store_true",
                        help="Apply ggplot2 styling to the figure.")
    parser.add_argument("-o", "--out_fp", default=None,
                        help="The path and file name to save the plot under.\
                              If specified, the figure will be saved directly\
                              instead of opening a window in which the plot can\
                              be viewed before saving.")

    return parser.parse_args()

def main():
    args = handle_program_options()

    try:
        with open(args.coord_fp):
            pass
    except IOError as ioe:
        err_msg = "\nError in input principal coordinates filepath (-i): {}\n"
        sys.exit(err_msg.format(ioe))

    try:
        with open(args.map_fp):
            pass
    except IOError as ioe:
        err_msg = "\nError in input metadata mapping filepath (-m): {}\n"
        sys.exit(err_msg.format(ioe))

    with open(args.coord_fp) as F:
        pcd = F.readlines()
    pcd = [line.split("\t") for line in pcd]

    map_header, imap = util.parse_map_file(args.map_fp)

    data_gather = util.gather_categories(imap, map_header,
                                         args.colorby.split(","))
    categories = OrderedDict([(condition, {"pc1": [], "pc2": [], "pc3": []})
                  for condition in data_gather.keys()])

    bcolors = itertools.cycle(Set3_12.hex_colors)
    if not args.colors:
        colors = [bcolors.next() for _ in categories]
    else:
        colors = util.color_mapping(imap, map_header,
                                    args.colorby, args.colors)
        colors = colors.values()

    parsed_unifrac = util.parse_unifrac(args.coord_fp)

    pco = [dim - 1 for dim in args.pc_order]
    if args.dimensions == 3:
      pco.append(2)

    pc1v = parsed_unifrac["varexp"][pco[0]]
    pc2v = parsed_unifrac["varexp"][pco[1]]
    if args.dimensions == 3:
        pc3v = parsed_unifrac["varexp"][pco[2]]

    for sid, points in parsed_unifrac["pcd"].iteritems():
        for condition, dc in data_gather.iteritems():
            if sid in dc.sids:
                cat = condition
                break
        categories[cat]["pc1"].append((sid, points[pco[0]]))
        categories[cat]["pc2"].append((sid, points[pco[1]]))

        if args.dimensions == 3:
            categories[cat]["pc3"].append((sid, points[pco[2]]))

    axis_str = "PC{} - Percent variation explained {:.2f}%"
    # initialize plot
    fig = plt.figure(figsize=args.figsize)
    if args.dimensions == 3:
        ax = fig.add_subplot(111, projection="3d")
        ax.view_init(elev=args.z_angles[1], azim=args.z_angles[0])
        ax.set_zlabel(axis_str.format(3, pc3v), labelpad=args.label_padding)
        if args.z_limits:
            ax.set_zlim(args.z_limits)
    else:
        ax = fig.add_subplot(111)

    # plot data
    for i, cat in enumerate(categories):
        if args.dimensions == 3:
            ax.scatter(xs=[e[1] for e in categories[cat]["pc1"]],
                       ys=[e[1] for e in categories[cat]["pc2"]],
                       zs=[e[1] for e in categories[cat]["pc3"]],
                       zdir="z",
                       c=colors[i],
                       s=args.point_size)
        else:
            ax.scatter([e[1] for e in categories[cat]["pc1"]],
                       [e[1] for e in categories[cat]["pc2"]],
                       c=colors[i], s=args.point_size)

        # Script to annotate PCoA sample points.
        if args.annotate_points:
            for x, y in zip(categories[cat]["pc1"], categories[cat]["pc2"]):
                ax.annotate(
                    x[0], xy=(x[1], y[1]), xytext=(-10, -15),
                    textcoords="offset points", ha="center", va="center",
                    )

    # customize plot options
    if args.x_limits:
        ax.set_xlim(args.x_limits)
    if args.y_limits:
        ax.set_ylim(args.y_limits)

    ax.set_xlabel(axis_str.format(1, float(pc1v)), labelpad=args.label_padding)
    ax.set_ylabel(axis_str.format(2, float(pc2v)), labelpad=args.label_padding)

    ax.legend([Rectangle((0, 0), 1, 1, fc=colors[i])
              for i in range(len(categories))], categories.keys(), loc="best")

    # Set the font characteristics
    font = {"family": "normal", "weight": "bold", "size": args.font_size}

    mpl.rc("font", **font)

    if args.title:
        title(args.title)

    if args.ggplot2_style and not args.dimensions == 3:
        gu.ggplot2_style(ax)

    # save or display result
    if args.out_fp:
        fig.savefig(args.out_fp, facecolor="white",
                    edgecolor="none", bbox_inches="tight",
                    pad_inches=0.2)
    else:
        plt.show()

if __name__ == "__main__":
    sys.exit(main())
<commit_msg>Updated PCoA.py. Updated  help description.<commit_after>#!/usr/bin/env python
import argparse
from collections import OrderedDict
import itertools
import sys
errors=[]
try:
    from palettable.colorbrewer.qualitative import Set3_12
except ImportError as ie:
    errors.append("No module named palettable")
try:
    import matplotlib as mpl
    from mpl_toolkits.mplot3d import Axes3D
except ImportError as ie:
    errors.append(ie)
if len(errors) != 0:
    for item in errors:
        print "Import Error:", item
    sys.exit()

from pylab import *
from phylotoast import util, graph_util as gu

def handle_program_options():
    parser = argparse.ArgumentParser(description="Create a 2D or 3D PCoA plot.\
                                     By default, this script opens a window\
                                     with the plot displayed if you want to\
                                     change certain aspects of the plot (such\
                                     as rotate the view in 3D mode). If the -o\
                                     option is specified, the plot will be\
                                     saved directly to an image without\
                                     the initial display window.")
    parser.add_argument("-i", "--coord_fp", required=True,
                        help="Input principal coordinates filepath (i.e.,\
                        resulting file from principal_coordinates.py)\
                        [REQUIRED].")
    parser.add_argument("-m", "--map_fp", required=True,
                        help="Input metadata mapping filepath [REQUIRED].")
    parser.add_argument("-b", "--colorby", required=True,
                        help="Any mapping categories, such as treatment type, \
                              that will be used to group the data in the \
                              output iTol table. For example, one category \
                              with three types will result in three data \
                              columns in the final output. Two categories with\
                              three types each will result in six data \
                              columns. Default is no categories and all the \
                              data will be treated as a single group.")
    parser.add_argument("-d", "--dimensions", default=2, type=int,
                        choices=[2, 3],
                        help="Choose whether to plot 2D or 3D.")
    parser.add_argument("-c", "--colors", default=None,
                        help="A column name in the mapping file containing\
                              hexadecimal (#FF0000) color values that will\
                              be used to color the groups. Each sample ID must\
                              have a color entry.")
    parser.add_argument("-s", "--point_size", default=100, type=int,
                        help="Specify the size of the circles representing each\
                        of the samples in the plot")
    parser.add_argument("--pc_order", default=[1,2], type=int, nargs=2,
                        help="Choose which Principle Coordinates are displayed\
                              and in which order, for example: 1 2. This option\
                              is only used when a 2D plot is specified.")
    parser.add_argument("--x_limits", type=float, nargs=2,
                        help="Specify limits for the x-axis instead of\
                        automatic setting based on the data range. Should\
                        take the form: --x_limits -0.5 0.5")
    parser.add_argument("--y_limits", type=float, nargs=2,
                        help="Specify limits for the y-axis instead of\
                        automatic setting based on the data range. Should\
                        take the form: --y_limits -0.5 0.5")
    parser.add_argument("--z_limits", type=float, nargs=2,
                        help="Specify limits for the z-axis instead of\
                        automatic setting based on the data range. Should\
                        take the form: --z_limits -0.5 0.5")
    parser.add_argument("--z_angles", type=float, nargs=2, default=[-134.5, 23.],
                        help="Specify the azimuth and elevation angles for a 3D plot.")
    parser.add_argument("-t", "--title", default="", help="Title of the plot.")
    parser.add_argument("--figsize", default=[14, 8], type=int, nargs=2,
                        help="Specify the 'width height' in inches for PCoA plots."
                             "By default, figure size is 14x8 inches")
    parser.add_argument("--font_size", default=12, type=int,
                        help="Sets the font size for text elements in the plot.")
    parser.add_argument("--label_padding", default=15, type=int,
                        help="Sets the spacing in points between the each axis\
                              and its label.")
    parser.add_argument("--annotate_points", action="store_true",
                        help="If specified, each graphed point will be\
                              labeled with its sample ID.")
    parser.add_argument("--ggplot2_style", action="store_true",
                        help="Apply ggplot2 styling to the figure.")
    parser.add_argument("-o", "--out_fp", default=None,
                        help="The path and file name to save the plot under.\
                              If specified, the figure will be saved directly\
                              instead of opening a window in which the plot can\
                              be viewed before saving.")

    return parser.parse_args()

def main():
    args = handle_program_options()

    try:
        with open(args.coord_fp):
            pass
    except IOError as ioe:
        err_msg = "\nError in input principal coordinates filepath (-i): {}\n"
        sys.exit(err_msg.format(ioe))

    try:
        with open(args.map_fp):
            pass
    except IOError as ioe:
        err_msg = "\nError in input metadata mapping filepath (-m): {}\n"
        sys.exit(err_msg.format(ioe))

    with open(args.coord_fp) as F:
        pcd = F.readlines()
    pcd = [line.split("\t") for line in pcd]

    map_header, imap = util.parse_map_file(args.map_fp)

    data_gather = util.gather_categories(imap, map_header,
                                         args.colorby.split(","))
    categories = OrderedDict([(condition, {"pc1": [], "pc2": [], "pc3": []})
                  for condition in data_gather.keys()])

    bcolors = itertools.cycle(Set3_12.hex_colors)
    if not args.colors:
        colors = [bcolors.next() for _ in categories]
    else:
        colors = util.color_mapping(imap, map_header,
                                    args.colorby, args.colors)
        colors = colors.values()

    parsed_unifrac = util.parse_unifrac(args.coord_fp)

    pco = [dim - 1 for dim in args.pc_order]
    if args.dimensions == 3:
      pco.append(2)

    pc1v = parsed_unifrac["varexp"][pco[0]]
    pc2v = parsed_unifrac["varexp"][pco[1]]
    if args.dimensions == 3:
        pc3v = parsed_unifrac["varexp"][pco[2]]

    for sid, points in parsed_unifrac["pcd"].iteritems():
        for condition, dc in data_gather.iteritems():
            if sid in dc.sids:
                cat = condition
                break
        categories[cat]["pc1"].append((sid, points[pco[0]]))
        categories[cat]["pc2"].append((sid, points[pco[1]]))

        if args.dimensions == 3:
            categories[cat]["pc3"].append((sid, points[pco[2]]))

    axis_str = "PC{} - Percent variation explained {:.2f}%"
    # initialize plot
    fig = plt.figure(figsize=args.figsize)
    if args.dimensions == 3:
        ax = fig.add_subplot(111, projection="3d")
        ax.view_init(elev=args.z_angles[1], azim=args.z_angles[0])
        ax.set_zlabel(axis_str.format(3, pc3v), labelpad=args.label_padding)
        if args.z_limits:
            ax.set_zlim(args.z_limits)
    else:
        ax = fig.add_subplot(111)

    # plot data
    for i, cat in enumerate(categories):
        if args.dimensions == 3:
            ax.scatter(xs=[e[1] for e in categories[cat]["pc1"]],
                       ys=[e[1] for e in categories[cat]["pc2"]],
                       zs=[e[1] for e in categories[cat]["pc3"]],
                       zdir="z",
                       c=colors[i],
                       s=args.point_size)
        else:
            ax.scatter([e[1] for e in categories[cat]["pc1"]],
                       [e[1] for e in categories[cat]["pc2"]],
                       c=colors[i], s=args.point_size)

        # Script to annotate PCoA sample points.
        if args.annotate_points:
            for x, y in zip(categories[cat]["pc1"], categories[cat]["pc2"]):
                ax.annotate(
                    x[0], xy=(x[1], y[1]), xytext=(-10, -15),
                    textcoords="offset points", ha="center", va="center",
                    )

    # customize plot options
    if args.x_limits:
        ax.set_xlim(args.x_limits)
    if args.y_limits:
        ax.set_ylim(args.y_limits)

    ax.set_xlabel(axis_str.format(1, float(pc1v)), labelpad=args.label_padding)
    ax.set_ylabel(axis_str.format(2, float(pc2v)), labelpad=args.label_padding)

    ax.legend([Rectangle((0, 0), 1, 1, fc=colors[i])
              for i in range(len(categories))], categories.keys(), loc="best")

    # Set the font characteristics
    font = {"family": "normal", "weight": "bold", "size": args.font_size}

    mpl.rc("font", **font)

    if args.title:
        title(args.title)

    if args.ggplot2_style and not args.dimensions == 3:
        gu.ggplot2_style(ax)

    # save or display result
    if args.out_fp:
        fig.savefig(args.out_fp, facecolor="white",
                    edgecolor="none", bbox_inches="tight",
                    pad_inches=0.2)
    else:
        plt.show()

if __name__ == "__main__":
    sys.exit(main())
<|endoftext|>


<commit_before>import json
import datetime

from django.http import HttpResponse, HttpResponseNotFound, HttpResponseBadRequest, HttpResponseServerError
from django.core import serializers
from django.contrib.postgres.search import TrigramSimilarity
from django.utils import timezone

from .models import Song, Tag, SongUpdateToken

def index(request):
    data = {'help': 'See API documentation here: ' +
            'https://github.com/zaneswafford/songaday_searcher/blob/master/API.md'}
    return HttpResponse(json.dumps(data), content_type='application/json')

def search(request, text=None):
    try:
        similarities = TrigramSimilarity(
            'title', text) + TrigramSimilarity('description', text)
        songs = Song.objects.annotate(
            similarity=similarities,
        ).filter(similarity__gte=0.1).order_by('-similarity')
        assert(len(songs) > 0)
    except AssertionError:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", songs, use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def tags(request, text=None):
    if not text:
        tags = Tag.objects.all()
        data = serializers.serialize("json", tags)
        return HttpResponse(data, content_type='application/json')

    try:
        songs = Song.objects.filter(tags__text__in=[text])
        assert(len(songs) > 0)
    except AssertionError:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", songs, use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def today(request):
    try:
        song = Song.objects.get(release_date=timezone.now().date())
    except Song.DoesNotExist:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def from_date(request, month=None, day=None, year=None):
    try:
        song_date = datetime.date(int(year), int(month), int(day))
        song = Song.objects.get(release_date=song_date)
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
    except Song.DoesNotExist:
        return HttpResponseNotFound(content_type='application/json')
    except Exception as e:
        return HttpResponseBadRequest(content_type='application/json')
    else:
        return HttpResponse(data, content_type='application/json')

def songs(request, number=None):
    if not number:
        songs = Song.objects.all()
        data = serializers.serialize("json", songs, fields=[
                                     'title', 'song_number', 'release_date'])
        return HttpResponse(data, content_type='application/json')

    try:
        song = Song.objects.get(song_number=number)
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
    except Song.DoesNotExist:
        return HttpResponseNotFound(content_type='application/json')
    else:
        return HttpResponse(data, content_type='application/json')

def last_updated(request):
    try:
        update_token = SongUpdateToken.objects.last()
        update_token_dict = {'started': str(update_token.started),
                             'finished': str(update_token.finished),
                             'songs_updated': update_token.song_count}
        data = json.dumps(update_token_dict)
    except Exception as e:
        return HttpResponseServerError(content_type='application/json')
    else:
        return HttpResponse(data, content_type='application/json')
<commit_msg>Added latest view<commit_after>import json
import datetime

from django.http import HttpResponse, HttpResponseNotFound, HttpResponseBadRequest, HttpResponseServerError
from django.core import serializers
from django.contrib.postgres.search import TrigramSimilarity
from django.utils import timezone

from .models import Song, Tag, SongUpdateToken

def index(request):
    data = {'help': 'See API documentation here: ' +
            'https://github.com/zaneswafford/songaday_searcher/blob/master/API.md'}
    return HttpResponse(json.dumps(data), content_type='application/json')

def search(request, text=None):
    try:
        similarities = TrigramSimilarity(
            'title', text) + TrigramSimilarity('description', text)
        songs = Song.objects.annotate(
            similarity=similarities,
        ).filter(similarity__gte=0.1).order_by('-similarity')
        assert(len(songs) > 0)
    except AssertionError:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", songs, use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def tags(request, text=None):
    if not text:
        tags = Tag.objects.all()
        data = serializers.serialize("json", tags)
        return HttpResponse(data, content_type='application/json')

    try:
        songs = Song.objects.filter(tags__text__in=[text])
        assert(len(songs) > 0)
    except AssertionError:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", songs, use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def today(request):
    try:
        song = Song.objects.get(release_date=timezone.now().date())
    except Song.DoesNotExist:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def latest(request):
    try:
        song = Song.objects.order_by('-release_date')[0]
    except IndexError:
        return HttpResponseNotFound(content_type='application/json')
    else:
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
        return HttpResponse(data, content_type='application/json')

def from_date(request, month=None, day=None, year=None):
    try:
        song_date = datetime.date(int(year), int(month), int(day))
        song = Song.objects.get(release_date=song_date)
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
    except Song.DoesNotExist:
        return HttpResponseNotFound(content_type='application/json')
    except Exception as e:
        return HttpResponseBadRequest(content_type='application/json')
    else:
        return HttpResponse(data, content_type='application/json')

def songs(request, number=None):
    if not number:
        songs = Song.objects.all()
        data = serializers.serialize("json", songs, fields=[
                                     'title', 'song_number', 'release_date'])
        return HttpResponse(data, content_type='application/json')

    try:
        song = Song.objects.get(song_number=number)
        data = serializers.serialize(
            "json", [song], use_natural_foreign_keys=True)
    except Song.DoesNotExist:
        return HttpResponseNotFound(content_type='application/json')
    else:
        return HttpResponse(data, content_type='application/json')

def last_updated(request):
    try:
        update_token = SongUpdateToken.objects.last()
        update_token_dict = {'started': str(update_token.started),
                             'finished': str(update_token.finished),
                             'songs_updated': update_token.song_count}
        data = json.dumps(update_token_dict)
    except Exception as e:
        return HttpResponseServerError(content_type='application/json')
    else:
        return HttpResponse(data, content_type='application/json')
<|endoftext|>


<commit_before>from __future__ import absolute_import

import logging
import select
import signal
import ctypes
import sys
import os

import vanilla.exception

log = logging.getLogger(__name__)

# TODO: investigate the equivalent for BSD and OSX
# TODO: should move this and poll into some kind of compat module
#
# Attempt to define a function  to ensure out children are sent a SIGTERM when
# our process dies, to avoid orphaned children.

def set_pdeathsig():
    pass

if hasattr(select, 'epoll'):
    try:
        PR_SET_PDEATHSIG = 1
        libc = ctypes.CDLL('libc.so.6')

        def set_pdeathsig():
            rc = libc.prctl(PR_SET_PDEATHSIG, signal.SIGTERM)
            assert not rc, 'PR_SET_PDEATHSIG failed: %s' % rc
    except:
        log.warn('unable to load libc: needed to set PR_SET_PDEATHSIG')

class __plugin__(object):
    def __init__(self, hub):
        self.hub = hub
        self.children = []
        self.sigchld = None

    class Child(object):
        def __init__(self, hub, pid):
            self.hub = hub
            self.pid = pid
            self.done = self.hub.state()

        def check_liveness(self):
            try:
                pid, code = os.waitpid(self.pid, os.WNOHANG)
            except OSError:
                return False

            if (pid, code) == (0, 0):
                return True

            self.exitcode = code >> 8
            self.exitsignal = code & (2**8-1)
            self.done.send(self)
            return False

        def terminate(self):
            self.signal(signal.SIGTERM)

        def signal(self, signum):
            os.kill(self.pid, signum)

    def watch(self):
        while self.children:
            try:
                self.sigchld.recv()
            except vanilla.exception.Stop:
                for child in self.children:
                    child.terminate()
                continue
            self.children = [
                child for child in self.children if child.check_liveness()]
        self.sigchld.close()

    def bootstrap(self, f, *a, **kw):
        import marshal
        import cPickle as pickle

        pipe_r, pipe_w = os.pipe()
        os.write(pipe_w, pickle.dumps((marshal.dumps(f.func_code), a, kw)))
        os.close(pipe_w)

        bootstrap = '\n'.join(x.strip() for x in ("""
            import cPickle as pickle
            import marshal
            import types
            import sys
            import os

            code, a, kw = pickle.loads(os.read(%(pipe_r)s, 4096))
            os.close(%(pipe_r)s)

            f = types.FunctionType(marshal.loads(code), globals(), 'f')
            f(*a, **kw)
        """ % {'pipe_r': pipe_r}).split('\n') if x)

        argv = [sys.executable, '-c', bootstrap]
        os.execv(argv[0], argv)

    def launch(self, f, *a, **kw):
        stderrtoout = kw.pop('stderrtoout', False)

        if not self.sigchld:
            self.sigchld = self.hub.signal.subscribe(signal.SIGCHLD)
            self.hub.spawn(self.watch)

        inpipe_r, inpipe_w = os.pipe()
        outpipe_r, outpipe_w = os.pipe()

        if not stderrtoout:
            errpipe_r, errpipe_w = os.pipe()

        pid = os.fork()

        if pid == 0:
            # child process
            set_pdeathsig()

            os.close(inpipe_w)
            os.dup2(inpipe_r, 0)
            os.close(inpipe_r)

            os.close(outpipe_r)
            os.dup2(outpipe_w, 1)

            if stderrtoout:
                os.dup2(outpipe_w, 2)

            else:
                os.close(errpipe_r)
                os.dup2(errpipe_w, 2)
                os.close(errpipe_w)

            os.close(outpipe_w)

            f(*a, **kw)
            return

        # parent continues
        os.close(inpipe_r)
        os.close(outpipe_w)

        child = self.Child(self.hub, pid)
        child.stdin = self.hub.io.fd_out(inpipe_w)
        child.stdout = self.hub.io.fd_in(outpipe_r)

        if not stderrtoout:
            os.close(errpipe_w)
            child.stderr = self.hub.io.fd_in(errpipe_r)

        self.children.append(child)
        return child

    def spawn(self, f, *a, **kw):
        return self.launch(self.bootstrap, f, *a, **kw)

    def execv(self, args, stderrtoout=False):
        return self.launch(os.execv, args[0], args, stderrtoout=stderrtoout)
<commit_msg>white space<commit_after>from __future__ import absolute_import

import logging
import select
import signal
import ctypes
import sys
import os

import vanilla.exception

log = logging.getLogger(__name__)

# TODO: investigate the equivalent for BSD and OSX
# TODO: should move this and poll into some kind of compat module
#
# Attempt to define a function  to ensure out children are sent a SIGTERM when
# our process dies, to avoid orphaned children.

def set_pdeathsig():
    pass

if hasattr(select, 'epoll'):
    try:
        PR_SET_PDEATHSIG = 1
        libc = ctypes.CDLL('libc.so.6')

        def set_pdeathsig():
            rc = libc.prctl(PR_SET_PDEATHSIG, signal.SIGTERM)
            assert not rc, 'PR_SET_PDEATHSIG failed: %s' % rc
    except:
        log.warn('unable to load libc: needed to set PR_SET_PDEATHSIG')

class __plugin__(object):
    def __init__(self, hub):
        self.hub = hub
        self.children = []
        self.sigchld = None

    class Child(object):
        def __init__(self, hub, pid):
            self.hub = hub
            self.pid = pid
            self.done = self.hub.state()

        def check_liveness(self):
            try:
                pid, code = os.waitpid(self.pid, os.WNOHANG)
            except OSError:
                return False

            if (pid, code) == (0, 0):
                return True

            self.exitcode = code >> 8
            self.exitsignal = code & (2**8-1)
            self.done.send(self)
            return False

        def terminate(self):
            self.signal(signal.SIGTERM)

        def signal(self, signum):
            os.kill(self.pid, signum)

    def watch(self):
        while self.children:
            try:
                self.sigchld.recv()
            except vanilla.exception.Stop:
                for child in self.children:
                    child.terminate()
                continue
            self.children = [
                child for child in self.children if child.check_liveness()]
        self.sigchld.close()

    def bootstrap(self, f, *a, **kw):
        import marshal
        import cPickle as pickle

        pipe_r, pipe_w = os.pipe()
        os.write(pipe_w, pickle.dumps((marshal.dumps(f.func_code), a, kw)))
        os.close(pipe_w)

        bootstrap = '\n'.join(x.strip() for x in ("""
            import cPickle as pickle
            import marshal
            import types
            import sys
            import os

            code, a, kw = pickle.loads(os.read(%(pipe_r)s, 4096))
            os.close(%(pipe_r)s)

            f = types.FunctionType(marshal.loads(code), globals(), 'f')
            f(*a, **kw)
        """ % {'pipe_r': pipe_r}).split('\n') if x)

        argv = [sys.executable, '-c', bootstrap]
        os.execv(argv[0], argv)

    def launch(self, f, *a, **kw):
        stderrtoout = kw.pop('stderrtoout', False)

        if not self.sigchld:
            self.sigchld = self.hub.signal.subscribe(signal.SIGCHLD)
            self.hub.spawn(self.watch)

        inpipe_r, inpipe_w = os.pipe()
        outpipe_r, outpipe_w = os.pipe()

        if not stderrtoout:
            errpipe_r, errpipe_w = os.pipe()

        pid = os.fork()

        if pid == 0:
            # child process
            set_pdeathsig()

            os.close(inpipe_w)
            os.dup2(inpipe_r, 0)
            os.close(inpipe_r)

            os.close(outpipe_r)
            os.dup2(outpipe_w, 1)

            if stderrtoout:
                os.dup2(outpipe_w, 2)
            else:
                os.close(errpipe_r)
                os.dup2(errpipe_w, 2)
                os.close(errpipe_w)

            os.close(outpipe_w)

            f(*a, **kw)
            return

        # parent continues
        os.close(inpipe_r)
        os.close(outpipe_w)

        child = self.Child(self.hub, pid)
        child.stdin = self.hub.io.fd_out(inpipe_w)
        child.stdout = self.hub.io.fd_in(outpipe_r)

        if not stderrtoout:
            os.close(errpipe_w)
            child.stderr = self.hub.io.fd_in(errpipe_r)

        self.children.append(child)
        return child

    def spawn(self, f, *a, **kw):
        return self.launch(self.bootstrap, f, *a, **kw)

    def execv(self, args, stderrtoout=False):
        return self.launch(os.execv, args[0], args, stderrtoout=stderrtoout)
<|endoftext|>


<commit_before>__version__ = '0.4.0.8'
<commit_msg>Bumped version number to 0.4.0.9<commit_after>__version__ = '0.4.0.9'
<|endoftext|>


<commit_before># -*- coding:utf-8 -*-
#functions used in atomco

def str2list(rawstr):
    import string
    rawlist = rawstr.strip(string.whitespace).split(' ')
    #remove space elements in list
    cleanlist = [x for x in rawlist if x != ' ' and x != '']
    return cleanlist

def array2str(raw_array):
    """
    convert 2d array -> string
    """
    array_str = ''
    for array_1d in raw_array:
        array_str += '(%-20.16f, %-20.16f, %-20.16f)\n' % (tuple(array_1d))

    return array_str

def combine_atomco_dict(dict_1, dict_2):
    """
    Combine 2 dict of atomco_dict.
    Return a new combined dict.
    >>> a.atomco_dict
    >>> {'C': [['2.01115823704755', '2.33265069974919', '10.54948252493041']],
         'Co': [['0.28355818414485', '2.31976779057375', '2.34330019781397'],
                ['2.76900337448991', '0.88479534087197', '2.34330019781397']]}
    """
    new_atomco_dict = {}
    for atom_type_str in dict_1:
        if atom_type_str in dict_2:
            new_atomco_dict[atom_type_str] = dict_1[atom_type_str] + \
                                             dict_2[atom_type_str]
        else:
            new_atomco_dict[atom_type_str] = dict_1[atom_type_str]
    for atom_type_str in dict_2:
        if atom_type_str in dict_1:
            pass
        else:
            new_atomco_dict[atom_type_str] = dict_2[atom_type_str]

    return new_atomco_dict

def atomdict2str(atomco_dict, keys):
    """
    Convert atomco_dict to content_str.
    from
    {'C' : [['2.01115823704755', '2.33265069974919', '10.54948252493041']],
     'Co': [['0.28355818414485', '2.31976779057375', '2.34330019781397'],
            ['2.76900337448991', '0.88479534087197', '2.34330019781397']]}
    to
    'C   2.01115823704755   2.33265069974919   10.54948252493041\n
     Co  0.28355818414485   2.31976779057375   2.34330019781397 \n
     Co  2.76900337448991   0.88479534087197   2.34330019781397 \n'
    """
    content_str = ''
    for atom in keys:
        n = len(atomco_dict[atom])
        for i in xrange(n):
            line_tuple = tuple([atom] + atomco_dict[atom][i])
            content_str += '%5s%20s%20s%20s\n' % line_tuple

    return content_str
<commit_msg>Modify string format<commit_after># -*- coding:utf-8 -*-
#functions used in atomco

def str2list(rawstr):
    import string
    rawlist = rawstr.strip(string.whitespace).split(' ')
    #remove space elements in list
    cleanlist = [x for x in rawlist if x != ' ' and x != '']
    return cleanlist

def array2str(raw_array):
    """
    convert 2d array -> string
    """
    array_str = ''
    for array_1d in raw_array:
        array_str += '(%-20.16f, %-20.16f, %-20.16f)\n' % (tuple(array_1d))

    return array_str

def combine_atomco_dict(dict_1, dict_2):
    """
    Combine 2 dict of atomco_dict.
    Return a new combined dict.
    >>> a.atomco_dict
    >>> {'C': [['2.01115823704755', '2.33265069974919', '10.54948252493041']],
         'Co': [['0.28355818414485', '2.31976779057375', '2.34330019781397'],
                ['2.76900337448991', '0.88479534087197', '2.34330019781397']]}
    """
    new_atomco_dict = {}
    for atom_type_str in dict_1:
        if atom_type_str in dict_2:
            new_atomco_dict[atom_type_str] = dict_1[atom_type_str] + \
                                             dict_2[atom_type_str]
        else:
            new_atomco_dict[atom_type_str] = dict_1[atom_type_str]
    for atom_type_str in dict_2:
        if atom_type_str in dict_1:
            pass
        else:
            new_atomco_dict[atom_type_str] = dict_2[atom_type_str]

    return new_atomco_dict

def atomdict2str(atomco_dict, keys):
    """
    Convert atomco_dict to content_str.
    from
    {'C' : [['2.01115823704755', '2.33265069974919', '10.54948252493041']],
     'Co': [['0.28355818414485', '2.31976779057375', '2.34330019781397'],
            ['2.76900337448991', '0.88479534087197', '2.34330019781397']]}
    to
    'C   2.01115823704755   2.33265069974919   10.54948252493041\n
     Co  0.28355818414485   2.31976779057375   2.34330019781397 \n
     Co  2.76900337448991   0.88479534087197   2.34330019781397 \n'
    """
    content_str = ''
    for atom in keys:
        n = len(atomco_dict[atom])
        for i in xrange(n):
            line_tuple = tuple([atom] + atomco_dict[atom][i])
            content_str += '%-3s%16s%16s%16s\n' % line_tuple

    return content_str
<|endoftext|>