<commit_before>#------------------------------------------------------------------------------
#  Copyright (c) 2013, Enthought, Inc.
#  All rights reserved.
#------------------------------------------------------------------------------

# traits imports
from traits.api import Bool, Callable, Dict, Either, Instance, List, \
    Property, Str

# local imports
from container import Container
from coordinate_box import get_from_constraints_namespace
from layout.debug_constraints import DebugConstraintsOverlay
from layout.layout_helpers import expand_constraints
from layout.layout_manager import LayoutManager
from layout.utils import add_symbolic_contents_constraints

class ConstraintsContainer(Container):
    """ A Container which lays out its child components using a
    constraints-based layout solver.

    """
    # A read-only symbolic object that represents the left boundary of
    # the component
    contents_left = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the right boundary
    # of the component
    contents_right = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the bottom boundary
    # of the component
    contents_bottom = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the top boundary of
    # the component
    contents_top = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the width of the
    # component
    contents_width = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the height of the
    # component
    contents_height = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the vertical center
    # of the component
    contents_v_center = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the horizontal
    # center of the component
    contents_h_center = Property(fget=get_from_constraints_namespace)

    # The layout constraints for this container.
    # This can either be a list or a callable. If it is a callable, it will be
    # called with a single argument, the ConstraintsContainer, and be expected
    # to return a list of constraints.
    layout_constraints = Either(List, Callable)

    # A copy of the layout constraints used when the constraints change
    _layout_constraints = List

    # A dictionary of components added to this container
    _component_map = Dict

    # All the hard constraints for child components
    _child_hard_constraints_map = Dict(Str, List)
    _child_hard_constraints = List

    # The size constraints for child components
    _child_size_constraints_map = Dict(Str, List)
    _child_size_constraints = List

    # The casuarius solver
    _layout_manager = Instance(LayoutManager)

    #------------------------------------------------------------------------
    # Debugging bits
    #------------------------------------------------------------------------

    # Whether or not debugging info should be shown.
    debug = Bool(False)

    # The overlay that draws the debugging info
    _debug_overlay = Instance(DebugConstraintsOverlay)

    def __init__(self, **traits):
        super(ConstraintsContainer, self).__init__(**traits)

        if self.debug:
            dbg = DebugConstraintsOverlay()
            self.overlays.append(dbg)
            self._debug_overlay = dbg

    #------------------------------------------------------------------------
    # Public methods
    #------------------------------------------------------------------------

    def refresh_layout_constraints(self):
        """ Explicitly regenerate the container's constraints and refresh the
        layout.
        """
        self._layout_constraints_changed()

    def relayout(self):
        """ Re-run the constraints solver in response to a resize or
        constraints modification.
        """
        mgr_layout = self._layout_manager.layout
        width_var = self.layout_width
        height_var = self.layout_height
        width, height = self.bounds
        def layout():
            for component in self._component_map.itervalues():
                component.position = (component.left.value,
                                      component.bottom.value)
                component.bounds = (component.layout_width.value,
                                    component.layout_height.value)
            if self._debug_overlay:
                layout_mgr = self._layout_manager
                self._debug_overlay.update_from_constraints(layout_mgr)
        mgr_layout(layout, width_var, height_var, (width, height))

        self.invalidate_draw()

    #------------------------------------------------------------------------
    # Traits methods
    #------------------------------------------------------------------------
    def _bounds_changed(self, old, new):
        """ Run the solver when the container's bounds change.
        """
        super(ConstraintsContainer, self)._bounds_changed(old, new)
        self.relayout()

    def _layout_constraints_changed(self):
        """ React to changes of the user controlled constraints.
        """
        if self.layout_constraints is None:
            return

        if callable(self.layout_constraints):
            new = self.layout_constraints(self)
        else:
            new = self.layout_constraints

        # Update the private constraints list. This will trigger the relayout.
        expand = expand_constraints
        self._layout_constraints = [cns for cns in expand(self, new)]

    def __layout_constraints_changed(self, name, old, new):
        """ Invalidate the layout when the private constraints list changes.
        """
        self._layout_manager.replace_constraints(old, new)
        self.relayout()

    def __components_items_changed(self, event):
        """ Make sure components that are added can be used with constraints.
        """
        # Remove stale components from the map
        for item in event.removed:
            key = item.id
            del self._child_hard_constraints_map[key]
            del self._child_size_constraints_map[key]
            del self._component_map[key]

        # Check the added components
        self._check_and_add_components(event.added)

    def __components_changed(self, new):
        """ Make sure components that are added can be used with constraints.
        """
        # Clear the component maps
        self._component_map = {}
        self._child_hard_constraints_map = {}
        self._child_size_constraints_map = {}

        # Check the new components
        self._check_and_add_components(new)

    def __layout_manager_default(self):
        """ Create the layout manager.
        """
        lm = LayoutManager(debug=self.debug)

        constraints = self._hard_constraints + self._content_box_constraints()
        lm.initialize(constraints)
        return lm

    #------------------------------------------------------------------------
    # Protected methods
    #------------------------------------------------------------------------

    def _check_and_add_components(self, components):
        """ Make sure components can be used with constraints.
        """
        for item in components:
            key = item.id
            if len(key) == 0:
                msg = "Components added to a {0} must have a valid 'id' trait."
                name = type(self).__name__
                raise ValueError(msg.format(name))
            elif key in self._component_map:
                msg = "A Component with id '{0}' has already been added."
                raise ValueError(msg.format(key))
            elif key == self.id:
                msg = "Can't add a Component with the same id as its parent."
                raise ValueError(msg)

            self._child_hard_constraints_map[key] = item._hard_constraints
            self._child_size_constraints_map[key] = item._size_constraints
            self._component_map[key] = item

        # Update the fixed constraints
        self._update_fixed_constraints()

    def _content_box_constraints(self):
        """ Return the constraints which define the content box of this
        container.

        """
        add_symbolic_contents_constraints(self._constraints_vars)

        contents_left = self.contents_left
        contents_right = self.contents_right
        contents_top = self.contents_top
        contents_bottom = self.contents_bottom

        return [contents_left == self.left,
                contents_bottom == self.bottom,
                contents_right == self.left + self.layout_width,
                contents_top == self.bottom + self.layout_height,
            ]

    def _update_fixed_constraints(self):
        """ Resolve the differences between the list of constraints and the
        map of child component constraints for both types of fixed constraints.
        """
        old_cns, all_new_cns = [], []
        for name in ('hard', 'size'):
            map_attr = getattr(self, '_child_{0}_constraints_map'.format(name))
            list_name = '_child_{0}_constraints'.format(name)
            old_cns.extend(getattr(self, list_name))
            new_cns = []
            for item in map_attr.itervalues():
                new_cns.extend(item)
            all_new_cns.extend(new_cns)
            setattr(self, list_name, new_cns)

        self._layout_manager.replace_constraints(old_cns, all_new_cns)
        # Possibly regenerate the user-specified constraints
        self.refresh_layout_constraints()
<commit_msg>Fix a bug where do_layout() was not being called on children.<commit_after>#------------------------------------------------------------------------------
#  Copyright (c) 2013, Enthought, Inc.
#  All rights reserved.
#------------------------------------------------------------------------------

# traits imports
from traits.api import Bool, Callable, Dict, Either, Instance, List, \
    Property, Str

# local imports
from container import Container
from coordinate_box import get_from_constraints_namespace
from layout.debug_constraints import DebugConstraintsOverlay
from layout.layout_helpers import expand_constraints
from layout.layout_manager import LayoutManager
from layout.utils import add_symbolic_contents_constraints

class ConstraintsContainer(Container):
    """ A Container which lays out its child components using a
    constraints-based layout solver.

    """
    # A read-only symbolic object that represents the left boundary of
    # the component
    contents_left = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the right boundary
    # of the component
    contents_right = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the bottom boundary
    # of the component
    contents_bottom = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the top boundary of
    # the component
    contents_top = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the width of the
    # component
    contents_width = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the height of the
    # component
    contents_height = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the vertical center
    # of the component
    contents_v_center = Property(fget=get_from_constraints_namespace)

    # A read-only symbolic object that represents the horizontal
    # center of the component
    contents_h_center = Property(fget=get_from_constraints_namespace)

    # The layout constraints for this container.
    # This can either be a list or a callable. If it is a callable, it will be
    # called with a single argument, the ConstraintsContainer, and be expected
    # to return a list of constraints.
    layout_constraints = Either(List, Callable)

    # A copy of the layout constraints used when the constraints change
    _layout_constraints = List

    # A dictionary of components added to this container
    _component_map = Dict

    # All the hard constraints for child components
    _child_hard_constraints_map = Dict(Str, List)
    _child_hard_constraints = List

    # The size constraints for child components
    _child_size_constraints_map = Dict(Str, List)
    _child_size_constraints = List

    # The casuarius solver
    _layout_manager = Instance(LayoutManager)

    #------------------------------------------------------------------------
    # Debugging bits
    #------------------------------------------------------------------------

    # Whether or not debugging info should be shown.
    debug = Bool(False)

    # The overlay that draws the debugging info
    _debug_overlay = Instance(DebugConstraintsOverlay)

    def __init__(self, **traits):
        super(ConstraintsContainer, self).__init__(**traits)

        if self.debug:
            dbg = DebugConstraintsOverlay()
            self.overlays.append(dbg)
            self._debug_overlay = dbg

    #------------------------------------------------------------------------
    # Public methods
    #------------------------------------------------------------------------

    def do_layout(self, size=None, force=False):
        """ Make sure child components get a chance to refresh their layout.
        """
        for component in self.components:
            component.do_layout(size=size, force=force)
        return

    def refresh_layout_constraints(self):
        """ Explicitly regenerate the container's constraints and refresh the
        layout.
        """
        self._layout_constraints_changed()

    def relayout(self):
        """ Re-run the constraints solver in response to a resize or
        constraints modification.
        """
        mgr_layout = self._layout_manager.layout
        width_var = self.layout_width
        height_var = self.layout_height
        width, height = self.bounds
        def layout():
            for component in self._component_map.itervalues():
                component.position = (component.left.value,
                                      component.bottom.value)
                component.bounds = (component.layout_width.value,
                                    component.layout_height.value)
            if self._debug_overlay:
                layout_mgr = self._layout_manager
                self._debug_overlay.update_from_constraints(layout_mgr)
        mgr_layout(layout, width_var, height_var, (width, height))

        self.invalidate_draw()

    #------------------------------------------------------------------------
    # Traits methods
    #------------------------------------------------------------------------
    def _bounds_changed(self, old, new):
        """ Run the solver when the container's bounds change.
        """
        super(ConstraintsContainer, self)._bounds_changed(old, new)
        self.relayout()

    def _layout_constraints_changed(self):
        """ React to changes of the user controlled constraints.
        """
        if self.layout_constraints is None:
            return

        if callable(self.layout_constraints):
            new = self.layout_constraints(self)
        else:
            new = self.layout_constraints

        # Update the private constraints list. This will trigger the relayout.
        expand = expand_constraints
        self._layout_constraints = [cns for cns in expand(self, new)]

    def __layout_constraints_changed(self, name, old, new):
        """ Invalidate the layout when the private constraints list changes.
        """
        self._layout_manager.replace_constraints(old, new)
        self.relayout()

    def __components_items_changed(self, event):
        """ Make sure components that are added can be used with constraints.
        """
        # Remove stale components from the map
        for item in event.removed:
            key = item.id
            del self._child_hard_constraints_map[key]
            del self._child_size_constraints_map[key]
            del self._component_map[key]

        # Check the added components
        self._check_and_add_components(event.added)

    def __components_changed(self, new):
        """ Make sure components that are added can be used with constraints.
        """
        # Clear the component maps
        self._component_map = {}
        self._child_hard_constraints_map = {}
        self._child_size_constraints_map = {}

        # Check the new components
        self._check_and_add_components(new)

    def __layout_manager_default(self):
        """ Create the layout manager.
        """
        lm = LayoutManager(debug=self.debug)

        constraints = self._hard_constraints + self._content_box_constraints()
        lm.initialize(constraints)
        return lm

    #------------------------------------------------------------------------
    # Protected methods
    #------------------------------------------------------------------------

    def _check_and_add_components(self, components):
        """ Make sure components can be used with constraints.
        """
        for item in components:
            key = item.id
            if len(key) == 0:
                msg = "Components added to a {0} must have a valid 'id' trait."
                name = type(self).__name__
                raise ValueError(msg.format(name))
            elif key in self._component_map:
                msg = "A Component with id '{0}' has already been added."
                raise ValueError(msg.format(key))
            elif key == self.id:
                msg = "Can't add a Component with the same id as its parent."
                raise ValueError(msg)

            self._child_hard_constraints_map[key] = item._hard_constraints
            self._child_size_constraints_map[key] = item._size_constraints
            self._component_map[key] = item

        # Update the fixed constraints
        self._update_fixed_constraints()

    def _content_box_constraints(self):
        """ Return the constraints which define the content box of this
        container.

        """
        add_symbolic_contents_constraints(self._constraints_vars)

        contents_left = self.contents_left
        contents_right = self.contents_right
        contents_top = self.contents_top
        contents_bottom = self.contents_bottom

        return [contents_left == self.left,
                contents_bottom == self.bottom,
                contents_right == self.left + self.layout_width,
                contents_top == self.bottom + self.layout_height,
            ]

    def _update_fixed_constraints(self):
        """ Resolve the differences between the list of constraints and the
        map of child component constraints for both types of fixed constraints.
        """
        old_cns, all_new_cns = [], []
        for name in ('hard', 'size'):
            map_attr = getattr(self, '_child_{0}_constraints_map'.format(name))
            list_name = '_child_{0}_constraints'.format(name)
            old_cns.extend(getattr(self, list_name))
            new_cns = []
            for item in map_attr.itervalues():
                new_cns.extend(item)
            all_new_cns.extend(new_cns)
            setattr(self, list_name, new_cns)

        self._layout_manager.replace_constraints(old_cns, all_new_cns)
        # Possibly regenerate the user-specified constraints
        self.refresh_layout_constraints()
<|endoftext|>


<commit_before>#!/usr/bin/env pypy
"""SignalFD: Recive signal notifcations over a file descriptor

Normmaly used with poll/select to handle signal notifcation in the main loop
instead of in callback functions
"""
from ctypes import c_ubyte, c_int, c_uint, c_ulong, c_ulonglong, c_void_p
from ctypes.util import find_library
import errors
import ctypes
import signal
import sys
import os

class signalfd_siginfo(ctypes.Structure):
	"""A signalfd_siginfo block as defined by the signalfd man page ("man 2 signalfd")

	This is a 128 byte structure read from the file descriptor opened with signalfd
	"""
	_fields_ = (("ssi_signo", c_uint),
				("ssi_errno", c_int),
				("ssi_code", c_int),
				("ssi_pid", c_uint),
				("ssi_uid", c_uint),
				("ssi_fd", c_int),
				("ssi_tid", c_uint),
				("ssi_band", c_uint),
				("ssi_overrun", c_uint),
				("ssi_trapno", c_uint),
				("ssi_status", c_int),
				("ssi_int", c_int),
				("ssi_ptr", c_ulonglong),
				("ssi_utime", c_ulonglong),
				("ssi_stime", c_ulonglong),
				("ssi_addr", c_ulonglong),
				# pad is used to pad the structure out to 128 bytes for future expansion
				("pad", c_ubyte * (128-80)))

	def __repr__(self):
		return "<signalfd_siginfo signal={0}, pid={1}, uid={2}>".format(self.ssi_signo, self.ssi_pid, self.ssi_uid)

	def __str__(self):
		signal_names = [x for x in signal.__dict__ if x.startswith("SIG")]
		signal_name = [x for x in signal_names if getattr(signal, x) == self.ssi_signo][0]
		return signal_name

class sigset_t(ctypes.Structure):
	"""A sigset_t structure for masking signals and marking them as blocked"""
	## 32 chosen by calculating by hand the code in
	## /usr/include/bits/sigset.h
	## unsigned long int assumed to be 64 bits
	_fields_ = (("__val", c_ulong * 32),)

libc = ctypes.CDLL(find_library("c"))

_signalfd = ctypes.CFUNCTYPE(c_int, c_int, ctypes.POINTER(sigset_t), c_int)
__param_flags = ((0, "fd"), (0, "mask"), (0, "flags", 0))
_signalfd = _signalfd(("signalfd", libc), __param_flags)
_signalfd.restype = c_int

# Taken from /usr/include/sys/signalfd.h
SFD_CLOEXEC = 0x2000000
SFD_NONBLOCK = 0x4000

SIG_BLOCK = 0
SIG_UNBLOCK = 1
SIG_SETMASK = 2

def signalfd_error(val, func, args):
	"""Error wrapper for signalfd"""
	errors.check_error(val)
_signalfd.errcheck = signalfd_error

def signalfd(fd, signals, flags=0):
	"""A wrapper for signalfd that handles pretty error printing

	Note: it is recomended to use the SignalFD object instead of this
	function
	"""
	# Make signals "Blocked"
	sigset = make_sigset_t(signals)
	libc.sigprocmask(SIG_BLOCK, sigset, None)

	fd = _signalfd(fd, sigset, flags)
	return fd

def make_sigset_t(signals):
	"""Add Signals to a sigset_t structure and return the new structure"""
	sigset = sigset_t()
	libc.sigemptyset(sigset)

	for sig in signals:
		libc.sigaddset(sigset, sig)

	return sigset

sigprocmask = libc.sigprocmask
sigprocmask.argtypes = [c_int, ctypes.POINTER(sigset_t), c_void_p]
sigprocmask.restype = c_int

sigemptyset = libc.sigemptyset
sigemptyset.argtypes = [ctypes.POINTER(sigset_t)]
sigemptyset.restype = c_int

sigaddset = libc.sigaddset
sigaddset.argtypes = [ctypes.POINTER(sigset_t), c_int]
sigaddset.restype = c_int

######################
# Event-like objects #
######################
class SignalFDError(errors.CError):
	"""Represents the return value from signalfd is val < 0

	see "man 2 signalfd" for a more detailed version of error messages
	"""
	def __repr__(self):
		return "<SignalFDException err_num={0}>".format(self.name)

class SignalFD(file):
	"""An Event like object that represents a file like object"""
	closed = False
	def __init__(self, mask, flags=0):
		fd = self.fdopen(1, mask=mask, flags=flags)
		self._fileno = fd
		self.mask = mask

	def fileno(self):
		return self._fileno

	def close(self):
		self.closed = True

	def read(self, n=-1):
		if n == -1:
			n = 128
		return os.read(self.fileno(), n)

	def readline(self, size=-1):
		return self.read()

	def readlines(self, n=0):
		raise NotImplemented()

	def getevent(self):
		return self.getevents()[0]

	def getevents(self, count=1):
		"""Retrive multiple events

		the maximum ammount of events returned at once is given by ```count```

		returns a list of signalfd_siginfo objects
		"""
		data = self.read(count * 128)

		l = []
		for i in range(len(data) / 128):
			i *= 128
			buf = ctypes.create_string_buffer(data[i:i+128], 128)
			event = signalfd_siginfo.from_address(ctypes.addressof(buf))
			l.append(event)

		return l

	def write(self):
		raise NotImplemented()

	def writelines(self):
		raise NotImplemented()

	@staticmethod
	def fdopen(fd, mode="r", buffering=-1, mask=0, flags=0):
		"""All args except fd are ignored"""
		fd = signalfd(fd, mask, flags)
		return fd

	def isatty(self):
		return False

	def tell(self):
		return 0

	def seek(self, offset, wence=0):
		pass

if __name__ == "__main__":
	sigmask = (signal.SIGUSR1, signal.SIGUSR2)

	signal.signal(signal.SIGUSR1, signal.SIG_IGN)
	signal.signal(signal.SIGUSR2, signal.SIG_IGN)

	s = SignalFD(sigmask)

	print "-------"
	# test if we actually wait on fd or if signal module kicks in
	for sig in (signal.SIGUSR1, signal.SIGUSR2):
		os.kill(os.getpid(), sig)
		print("Waiting on event:")
		sig = s.getevent()
		print("Event Recived: " + str(sig))
		print(repr(sig))
		print "-------"
<commit_msg>Added struct definition locations<commit_after>#!/usr/bin/env pypy
"""SignalFD: Recive signal notifcations over a file descriptor

Normmaly used with poll/select to handle signal notifcation in the main loop
instead of in callback functions
"""
from ctypes import c_ubyte, c_int, c_uint, c_ulong, c_ulonglong, c_void_p
from ctypes.util import find_library
import errors
import ctypes
import signal
import sys
import os

class signalfd_siginfo(ctypes.Structure):
	"""A signalfd_siginfo block as defined by the signalfd man page ("man 2 signalfd")

	This is a 128 byte structure read from the file descriptor opened with signalfd
	"""
	_defined = "/usr/include/sys/signalfd.h"
	_fields_ = (("ssi_signo", c_uint),
				("ssi_errno", c_int),
				("ssi_code", c_int),
				("ssi_pid", c_uint),
				("ssi_uid", c_uint),
				("ssi_fd", c_int),
				("ssi_tid", c_uint),
				("ssi_band", c_uint),
				("ssi_overrun", c_uint),
				("ssi_trapno", c_uint),
				("ssi_status", c_int),
				("ssi_int", c_int),
				("ssi_ptr", c_ulonglong),
				("ssi_utime", c_ulonglong),
				("ssi_stime", c_ulonglong),
				("ssi_addr", c_ulonglong),
				# pad is used to pad the structure out to 128 bytes for future expansion
				("pad", c_ubyte * (128-80)))

	def __repr__(self):
		return "<signalfd_siginfo signal={0}, pid={1}, uid={2}>".format(self.ssi_signo, self.ssi_pid, self.ssi_uid)

	def __str__(self):
		signal_names = [x for x in signal.__dict__ if x.startswith("SIG")]
		signal_name = [x for x in signal_names if getattr(signal, x) == self.ssi_signo][0]
		return signal_name

class sigset_t(ctypes.Structure):
	"""A sigset_t structure for masking signals and marking them as blocked"""
	_defined = "/usr/include/bits/sigset.h"
	## 32 chosen by calculating by hand the code in
	## /usr/include/bits/sigset.h
	## unsigned long int assumed to be 64 bits
	_fields_ = (("__val", c_ulong * 32),)

libc = ctypes.CDLL(find_library("c"))

_signalfd = ctypes.CFUNCTYPE(c_int, c_int, ctypes.POINTER(sigset_t), c_int)
__param_flags = ((0, "fd"), (0, "mask"), (0, "flags", 0))
_signalfd = _signalfd(("signalfd", libc), __param_flags)
_signalfd.restype = c_int

# Taken from /usr/include/sys/signalfd.h
SFD_CLOEXEC = 0x2000000
SFD_NONBLOCK = 0x4000

SIG_BLOCK = 0
SIG_UNBLOCK = 1
SIG_SETMASK = 2

def signalfd_error(val, func, args):
	"""Error wrapper for signalfd"""
	errors.check_error(val)
_signalfd.errcheck = signalfd_error

def signalfd(fd, signals, flags=0):
	"""A wrapper for signalfd that handles pretty error printing

	Note: it is recomended to use the SignalFD object instead of this
	function
	"""
	# Make signals "Blocked"
	sigset = make_sigset_t(signals)
	libc.sigprocmask(SIG_BLOCK, sigset, None)

	fd = _signalfd(fd, sigset, flags)
	return fd

def make_sigset_t(signals):
	"""Add Signals to a sigset_t structure and return the new structure"""
	sigset = sigset_t()
	libc.sigemptyset(sigset)

	for sig in signals:
		libc.sigaddset(sigset, sig)

	return sigset

sigprocmask = libc.sigprocmask
sigprocmask.argtypes = [c_int, ctypes.POINTER(sigset_t), c_void_p]
sigprocmask.restype = c_int

sigemptyset = libc.sigemptyset
sigemptyset.argtypes = [ctypes.POINTER(sigset_t)]
sigemptyset.restype = c_int

sigaddset = libc.sigaddset
sigaddset.argtypes = [ctypes.POINTER(sigset_t), c_int]
sigaddset.restype = c_int

######################
# Event-like objects #
######################
class SignalFDError(errors.CError):
	"""Represents the return value from signalfd is val < 0

	see "man 2 signalfd" for a more detailed version of error messages
	"""
	def __repr__(self):
		return "<SignalFDException err_num={0}>".format(self.name)

class SignalFD(file):
	"""An Event like object that represents a file like object"""
	closed = False
	def __init__(self, mask, flags=0):
		fd = self.fdopen(1, mask=mask, flags=flags)
		self._fileno = fd
		self.mask = mask

	def fileno(self):
		return self._fileno

	def close(self):
		self.closed = True

	def read(self, n=-1):
		if n == -1:
			n = 128
		return os.read(self.fileno(), n)

	def readline(self, size=-1):
		return self.read()

	def readlines(self, n=0):
		raise NotImplemented()

	def getevent(self):
		return self.getevents()[0]

	def getevents(self, count=1):
		"""Retrive multiple events

		the maximum ammount of events returned at once is given by ```count```

		returns a list of signalfd_siginfo objects
		"""
		data = self.read(count * 128)

		l = []
		for i in range(len(data) / 128):
			i *= 128
			buf = ctypes.create_string_buffer(data[i:i+128], 128)
			event = signalfd_siginfo.from_address(ctypes.addressof(buf))
			l.append(event)

		return l

	def write(self):
		raise NotImplemented()

	def writelines(self):
		raise NotImplemented()

	@staticmethod
	def fdopen(fd, mode="r", buffering=-1, mask=0, flags=0):
		"""All args except fd are ignored"""
		fd = signalfd(fd, mask, flags)
		return fd

	def isatty(self):
		return False

	def tell(self):
		return 0

	def seek(self, offset, wence=0):
		pass

if __name__ == "__main__":
	sigmask = (signal.SIGUSR1, signal.SIGUSR2)

	signal.signal(signal.SIGUSR1, signal.SIG_IGN)
	signal.signal(signal.SIGUSR2, signal.SIG_IGN)

	s = SignalFD(sigmask)

	print "-------"
	# test if we actually wait on fd or if signal module kicks in
	for sig in (signal.SIGUSR1, signal.SIGUSR2):
		os.kill(os.getpid(), sig)
		print("Waiting on event:")
		sig = s.getevent()
		print("Event Recived: " + str(sig))
		print(repr(sig))
		print "-------"
<|endoftext|>


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

# for getting the hostname of the underlying system
import socket

###### AD converter stuff
from MCP3008 import MCP3008
adc = MCP3008()
voltage = 0
voltageThreadRunning = True

###### motor stuff
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor
import time
import atexit

###### LCD stuff
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
# Raspberry Pi pin configuration:
RST = 24

# create a 128x32 display with hardware I2C
disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST)

# showing hostname
hostname = socket.gethostname()
print("Running on host " + hostname + ".")

# run some parts only on the real robot
if hostname == 'minibot':
    # create a default motor object, no changes to I2C address or frequency
    mh = Adafruit_MotorHAT(addr=0x60)

    # recommended for auto-disabling motors on shutdown!
    def turnOffMotors():
        mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
        mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)

    # what to do at program exit
    atexit.register(turnOffMotors)

    # user motor 1 and 2 on RasPi hat
    myMotor1 = mh.getMotor(1)
    myMotor2 = mh.getMotor(2)

    # turn off motors
    myMotor1.run(Adafruit_MotorHAT.RELEASE);
    myMotor2.run(Adafruit_MotorHAT.RELEASE);

    # set the speed (from 0 (off) to 255 (max speed))
    startSpeed = 100
    myMotor1.setSpeed(startSpeed)
    myMotor2.setSpeed(startSpeed)

################## LCD
# Initialize library.
disp.begin()

# Clear display.
disp.clear()
disp.display()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width    # 128
height = disp.height  #  64
image = Image.new('1', (width, height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0)

# load my favorite TTF font
fontText   = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 20)
fontSymbol = ImageFont.truetype('Digital Camera Symbols.ttf', 36)

# Display image.
disp.image(image)
disp.display()

######
###### Threads
######
def voltageThread():
 # Thread zum Auslesen der Sensoren
 global voltageThreadRunning, voltage, dhtSensorTyp, dhtSensorTemperatur, dhtSensorLuftfeuchtigkeit
 print "Voltage sensor thread started."
 while voltageThreadRunning:
    # read AD converter (battery voltage)
    # use channel 0 on IC
    voltage = adc.read(channel = 0)
    print("Voltage: %.2f" % (voltage / 1023.0 * 3.3))
    # displaySensorwertAusgabe()
    time.sleep(1)

# start thread
voltageCheckThread = threading.Thread(target=voltageThread)
voltageCheckThread.start()

######
###### forever - or until ctrl+c  :)
######
while (True):
    # clear LCD
    draw.rectangle((0,0, width, height), outline=0, fill=0)
    # LCD battery symbol
    draw.text(( 0, 0), "d", font=fontSymbol, fill=255)
    # draw.text((55, 4), "11.0 V", font=fontText, fill=255)
    # LCD voltage
    draw.text((55, 4), str("%.2f V" % (voltage / 1023.0 * 3.3)), font=fontText, fill=255)
    # go
    disp.image(image)
    disp.display()

    # test test test "empty battery" (clear part of battery symbol)
    time.sleep(1)
    rectw = 18
    recth = 22

    draw.rectangle((8, 10, rectw, recth), outline=0, fill=0)
    time.sleep(1)
    disp.image(image)
    disp.display()

    draw.rectangle((8+1*rectw, 10, rectw, recth), outline=0, fill=0)
    time.sleep(1)
    disp.image(image)
    disp.display()

    draw.rectangle((8+2*rectw, 10, rectw, recth), outline=0, fill=0)
    time.sleep(1)
    disp.image(image)
    disp.display()

    ### drive
    # run some parts only on the real robot
    if hostname == 'minibot':
        # drive
        print("Forward! ")
        myMotor1.run(Adafruit_MotorHAT.FORWARD)
        myMotor2.run(Adafruit_MotorHAT.FORWARD)

        print("\tSpeed up...")
        for i in range(startSpeed, 255):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("\tSlow down...")
        for i in range(255, startSpeed, -1):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("Backward! ")
        myMotor1.run(Adafruit_MotorHAT.BACKWARD)
        myMotor2.run(Adafruit_MotorHAT.BACKWARD)

        print("\tSpeed up...")
        for i in range(startSpeed, 255):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("\tSlow down...")
        for i in range(255, startSpeed, -1):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("Release")
        myMotor1.run(Adafruit_MotorHAT.RELEASE)
        myMotor2.run(Adafruit_MotorHAT.RELEASE)

    # sleep
    #time.sleep(1.0)
<commit_msg>added exitMinibot - does not work so far. Let's check it with a signal handler for keyboard interrupt<commit_after>#!/usr/bin/python
# coding=utf-8

# for getting the hostname of the underlying system
import socket
# for using sensor checks in a thread
import threading

###### AD converter stuff
from MCP3008 import MCP3008
adc = MCP3008()
voltage = 0
voltageThreadRunning = True

###### motor stuff
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor
import time
import atexit

###### LCD stuff
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
# Raspberry Pi pin configuration:
RST = 24

# create a 128x32 display with hardware I2C
disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST)

# showing hostname
hostname = socket.gethostname()
print("Running on host " + hostname + ".")

# run some parts only on the real robot
if hostname == 'minibot':
    # create a default motor object, no changes to I2C address or frequency
    mh = Adafruit_MotorHAT(addr=0x60)

    # recommended for auto-disabling motors on shutdown!
    def turnOffMotors():
        mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
        mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)

    # user motor 1 and 2 on RasPi hat
    myMotor1 = mh.getMotor(1)
    myMotor2 = mh.getMotor(2)

    # turn off motors
    myMotor1.run(Adafruit_MotorHAT.RELEASE);
    myMotor2.run(Adafruit_MotorHAT.RELEASE);

    # set the speed (from 0 (off) to 255 (max speed))
    startSpeed = 100
    myMotor1.setSpeed(startSpeed)
    myMotor2.setSpeed(startSpeed)

##
## what to do on exit pgm
##
def exitMinibot():
  # run some parts only on the real robot
  if hostname == 'minibot':
    turnOffMotors();
  # stop threads
  voltageCheckThread.stop()

##
## what to do at program exit
##
atexit.register(exitMinibot)

################## LCD
# Initialize library.
disp.begin()

# Clear display.
disp.clear()
disp.display()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width    # 128
height = disp.height  #  64
image = Image.new('1', (width, height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0)

# load my favorite TTF font
fontText   = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 20)
fontSymbol = ImageFont.truetype('Digital Camera Symbols.ttf', 36)

# Display image.
disp.image(image)
disp.display()

######
###### Threads
######
def voltageThread():
    # Thread zum Auslesen der Sensoren
    global voltageThreadRunning, voltage
    print "Voltage sensor thread started."
    while voltageThreadRunning:
        # read AD converter (battery voltage)
        # use channel 0 on IC
        voltage = adc.read(channel = 0)
        print("Voltage: %.2f" % (voltage / 1023.0 * 3.3))
        # displaySensorwertAusgabe()
        time.sleep(1)

# start thread
voltageCheckThread = threading.Thread(target=voltageThread)
voltageCheckThread.start()

######
###### forever - or until ctrl+c  :)
######
while (True):
    # clear LCD
    draw.rectangle((0,0, width, height), outline=0, fill=0)
    # LCD battery symbol
    draw.text(( 0, 0), "d", font=fontSymbol, fill=255)
    # draw.text((55, 4), "11.0 V", font=fontText, fill=255)
    # LCD voltage
    draw.text((55, 4), str("%.2f V" % (voltage / 1023.0 * 3.3)), font=fontText, fill=255)
    # go
    disp.image(image)
    disp.display()

    # test test test "empty battery" (clear part of battery symbol)
    time.sleep(1)
    rectw = 18
    recth = 22

    draw.rectangle((8, 10, rectw, recth), outline=0, fill=0)
    time.sleep(1)
    disp.image(image)
    disp.display()

    draw.rectangle((8+1*rectw, 10, rectw, recth), outline=0, fill=0)
    time.sleep(1)
    disp.image(image)
    disp.display()

    draw.rectangle((8+2*rectw, 10, rectw, recth), outline=0, fill=0)
    time.sleep(1)
    disp.image(image)
    disp.display()

    ### drive
    # run some parts only on the real robot
    if hostname == 'minibot':
        # drive
        print("Forward! ")
        myMotor1.run(Adafruit_MotorHAT.FORWARD)
        myMotor2.run(Adafruit_MotorHAT.FORWARD)

        print("\tSpeed up...")
        for i in range(startSpeed, 255):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("\tSlow down...")
        for i in range(255, startSpeed, -1):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("Backward! ")
        myMotor1.run(Adafruit_MotorHAT.BACKWARD)
        myMotor2.run(Adafruit_MotorHAT.BACKWARD)

        print("\tSpeed up...")
        for i in range(startSpeed, 255):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("\tSlow down...")
        for i in range(255, startSpeed, -1):
            myMotor1.setSpeed(i)
            myMotor2.setSpeed(i)
            time.sleep(0.01)

        print("Release")
        myMotor1.run(Adafruit_MotorHAT.RELEASE)
        myMotor2.run(Adafruit_MotorHAT.RELEASE)

    # sleep
    #time.sleep(1.0)
<|endoftext|>


<commit_before>import math
from GPy.util.linalg import mdot
import nlopt
from numpy.ma import concatenate
from scipy.linalg import inv
from scipy.optimize import fmin_l_bfgs_b, minimize, fmin_cg
import numpy as np
import time
from savigp import Configuration

__author__ = 'AT'

class Optimizer:
    def __init__(self):
        pass

    @staticmethod
    def SGD(model, alpha, start, max_iter, ftol=0.0001, xtol=0.0001, verbose=True,
            factor=1.0, opt_indices=None, adaptive_alpha=True, show_alpha= False):
        if opt_indices is None:
            opt_indices = range(0, len(start))
        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, start, opt_indices, verbose=verbose)
        iter = 0
        x = start
        last_f = float('Inf')
        delta_LR = 0.1
        avg_ftol = 100.
        while iter < max_iter:
            update(x)
            new_f = f()
            grad = f_grad()

            if adaptive_alpha and alpha > 1. / max(abs(grad)) / 10:
                alpha = 1. / max(abs(grad)) / 100
            if adaptive_alpha and new_f < last_f and alpha < 1. / max(abs(grad)) / 1000:
                alpha = min(1. / max(abs(grad)) / 500, 0.001)
            if show_alpha:
                print 'alpha', alpha,
            x -= grad * alpha
            if avg_ftol < ftol:
                return x, new_f
            if iter > 1 and new_f < last_f:
                avg_ftol = (1 - delta_LR) * avg_ftol + delta_LR * math.fabs(last_f - new_f)
            last_f = new_f
            iter += 1
        d = {}
        d['funcalls'] = iter
        return d

    @staticmethod
    def get_f_f_grad_from_model(model, x0, opt_indices, verbose=False):
        last_x = np.empty((1, x0.shape[0]))

        def update(x):
            if np.array_equal(x, last_x[0]):
                return
            last_x[0] = x
            p = x0.copy()
            p[opt_indices] = x[opt_indices]
            model.set_params(x)

        def f(X=None):
            if X is not None:
                update(X)
            return model.objective_function()

        def f_grad(X=None):
            if X is not None:
                update(X)

            g = np.zeros(len(x0))
            g[opt_indices] = model.objective_function_gradients().copy()[opt_indices]
            if verbose:
                # print 'grad:', Optimizer.print_short(g)
                print 'objective:', "%.4f" % model.objective_function()
            return g

        update(x0)
        return f, f_grad, update

    @staticmethod
    def BFGS(model, opt_indices=None, max_fun=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)
        x, f, d = fmin_l_bfgs_b(f, start, f_grad, factr=5, epsilon=1e-3, maxfun=max_fun,
                      callback=lambda x: update(x))
        return d

    @staticmethod
    def CG(model, opt_indices=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)
        fmin_cg(f, start, f_grad, epsilon=1e-6,
                callback=lambda x: update(x))

    @staticmethod
    def NLOPT(model, algorithm, opt_indices=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)

        def myfunc(x, grad):
            update(x)
            if grad.size > 0:
                grad[:] = f_grad()
            return f()

        opt = nlopt.opt(algorithm, len(model.get_params()))
        opt.set_min_objective(myfunc)
        opt.set_ftol_rel(1e-3)
        opt_x = opt.optimize(model.get_params())
        d = {'opt_params': opt_x, 'funcalls': 1}
        return d

    @staticmethod
    def general(model, opt_indices=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)
        minimize(f, start, jac=f_grad, method='Newton-CG',
                 callback=lambda x: update(x))

        return {'funcalls': 1}

    @staticmethod
    def print_short(a):
        return ["%.2f" % a[j] for j in range(len(a))]

    @staticmethod
    def optimize_model(model, max_fun, verbose, method=None, epsilon=1e-4, opt_iter=200):
        if not method:
            method=['hyp', 'mog']
        converged=False
        start=time.time()
        total_evals = 0
        last_param = None
        try:
            while not converged:
                if 'mog' in method:
                    print 'mog params'
                    model.set_configuration([
                        Configuration.MoG,
                        Configuration.ENTROPY,
                        Configuration.CROSS,
                        Configuration.ELL,
                    ])
                    d = Optimizer.BFGS(model, max_fun=min(max_fun, opt_iter), verbose=verbose)
                    # d = Optimizer.NLOPT(model, algorithm=nlopt.LD_LBFGS, verbose=verbose)
                    # d = Optimizer.SGD(model, alpha=1e-6, start=model.get_params(), max_iter=10, adaptive_alpha=False)
                    # d = Optimizer.general(model, verbose=verbose)
                    total_evals += d['funcalls']

                # check for convergence
                new_params = model.get_params()
                if last_param is not None:
                    if np.mean(np.absolute(new_params - last_param)) < epsilon:
                        break
                    print 'diff:', np.mean(np.absolute(new_params - last_param))
                last_param = new_params

                if 'hyp' in method:
                    print 'hyp params'
                    model.set_configuration([
                        Configuration.ENTROPY,
                        Configuration.CROSS,
                        Configuration.ELL,
                        Configuration.HYPER
                    ])
                    d = Optimizer.BFGS(model, max_fun=min(max_fun, opt_iter), verbose=verbose)
                    total_evals += d['funcalls']

                if 'll' in method:
                    print 'll params'
                    model.set_configuration([
                        Configuration.ELL,
                        Configuration.LL
                    ])
                    d = Optimizer.BFGS(model, max_fun=min(max_fun, opt_iter), verbose=verbose)
                    total_evals += d['funcalls']

                if total_evals > max_fun:
                    break

        except KeyboardInterrupt:
            print 'interrupted by the user'
            if total_evals == 0:
                total_evals = float('Nan')
        end=time.time()
        return model, (end - start) / total_evals, (end - start)
<commit_msg>no max iter in opt<commit_after>import math
from GPy.util.linalg import mdot
import nlopt
from numpy.ma import concatenate
from scipy.linalg import inv
from scipy.optimize import fmin_l_bfgs_b, minimize, fmin_cg
import numpy as np
import time
from savigp import Configuration

__author__ = 'AT'

class Optimizer:
    def __init__(self):
        pass

    @staticmethod
    def SGD(model, alpha, start, max_iter, ftol=0.0001, xtol=0.0001, verbose=True,
            factor=1.0, opt_indices=None, adaptive_alpha=True, show_alpha= False):
        if opt_indices is None:
            opt_indices = range(0, len(start))
        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, start, opt_indices, verbose=verbose)
        iter = 0
        x = start
        last_f = float('Inf')
        delta_LR = 0.1
        avg_ftol = 100.
        while iter < max_iter:
            update(x)
            new_f = f()
            grad = f_grad()

            if adaptive_alpha and alpha > 1. / max(abs(grad)) / 10:
                alpha = 1. / max(abs(grad)) / 100
            if adaptive_alpha and new_f < last_f and alpha < 1. / max(abs(grad)) / 1000:
                alpha = min(1. / max(abs(grad)) / 500, 0.001)
            if show_alpha:
                print 'alpha', alpha,
            x -= grad * alpha
            if avg_ftol < ftol:
                return x, new_f
            if iter > 1 and new_f < last_f:
                avg_ftol = (1 - delta_LR) * avg_ftol + delta_LR * math.fabs(last_f - new_f)
            last_f = new_f
            iter += 1
        d = {}
        d['funcalls'] = iter
        return d

    @staticmethod
    def get_f_f_grad_from_model(model, x0, opt_indices, verbose=False):
        last_x = np.empty((1, x0.shape[0]))

        def update(x):
            if np.array_equal(x, last_x[0]):
                return
            last_x[0] = x
            p = x0.copy()
            p[opt_indices] = x[opt_indices]
            model.set_params(x)

        def f(X=None):
            if X is not None:
                update(X)
            return model.objective_function()

        def f_grad(X=None):
            if X is not None:
                update(X)

            g = np.zeros(len(x0))
            g[opt_indices] = model.objective_function_gradients().copy()[opt_indices]
            if verbose:
                # print 'grad:', Optimizer.print_short(g)
                print 'objective:', "%.4f" % model.objective_function()
            return g

        update(x0)
        return f, f_grad, update

    @staticmethod
    def BFGS(model, opt_indices=None, max_fun=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)
        x, f, d = fmin_l_bfgs_b(f, start, f_grad, factr=5, epsilon=1e-3, maxfun=max_fun,
                      callback=lambda x: update(x))
        return d

    @staticmethod
    def CG(model, opt_indices=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)
        fmin_cg(f, start, f_grad, epsilon=1e-6,
                callback=lambda x: update(x))

    @staticmethod
    def NLOPT(model, algorithm, opt_indices=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)

        def myfunc(x, grad):
            update(x)
            if grad.size > 0:
                grad[:] = f_grad()
            return f()

        opt = nlopt.opt(algorithm, len(model.get_params()))
        opt.set_min_objective(myfunc)
        opt.set_ftol_rel(1e-3)
        opt_x = opt.optimize(model.get_params())
        d = {'opt_params': opt_x, 'funcalls': 1}
        return d

    @staticmethod
    def general(model, opt_indices=None, verbose=False):
        start = model.get_params()
        if opt_indices is None:
            opt_indices = range(0, len(start))

        f, f_grad, update = Optimizer.get_f_f_grad_from_model(model, model.get_params(), opt_indices, verbose=verbose)
        minimize(f, start, jac=f_grad, method='Newton-CG',
                 callback=lambda x: update(x))

        return {'funcalls': 1}

    @staticmethod
    def print_short(a):
        return ["%.2f" % a[j] for j in range(len(a))]

    @staticmethod
    def optimize_model(model, max_fun, verbose, method=None, epsilon=1e-4, opt_iter=200):
        if not method:
            method=['hyp', 'mog']
        converged=False
        start=time.time()
        total_evals = 0
        last_param = None
        try:
            while not converged:
                if 'mog' in method:
                    print 'mog params'
                    model.set_configuration([
                        Configuration.MoG,
                        Configuration.ENTROPY,
                        Configuration.CROSS,
                        Configuration.ELL,
                    ])
                    d = Optimizer.BFGS(model, max_fun=min(max_fun, opt_iter), verbose=verbose)
                    # d = Optimizer.NLOPT(model, algorithm=nlopt.LD_LBFGS, verbose=verbose)
                    # d = Optimizer.SGD(model, alpha=1e-6, start=model.get_params(), max_iter=10, adaptive_alpha=False)
                    # d = Optimizer.general(model, verbose=verbose)
                    total_evals += d['funcalls']

                # check for convergence
                new_params = model.get_params()
                if last_param is not None:
                    if np.mean(np.absolute(new_params - last_param)) < epsilon:
                        break
                    print 'diff:', np.mean(np.absolute(new_params - last_param))
                last_param = new_params

                if 'hyp' in method:
                    print 'hyp params'
                    model.set_configuration([
                        Configuration.ENTROPY,
                        Configuration.CROSS,
                        Configuration.ELL,
                        Configuration.HYPER
                    ])
                    d = Optimizer.BFGS(model, max_fun=min(max_fun, opt_iter), verbose=verbose)
                    total_evals += d['funcalls']

                if 'll' in method:
                    print 'll params'
                    model.set_configuration([
                        Configuration.ELL,
                        Configuration.LL
                    ])
                    d = Optimizer.BFGS(model, max_fun=min(max_fun, opt_iter), verbose=verbose)
                    total_evals += d['funcalls']

                if (total_evals is not None) and total_evals > max_fun:
                    break

        except KeyboardInterrupt:
            print 'interrupted by the user'
            if total_evals == 0:
                total_evals = float('Nan')
        end=time.time()
        return model, (end - start) / total_evals, (end - start)
<|endoftext|>


<commit_before>import logging
import random

#from logika_igre import IGRALEC_1, IGRALEC_2, NI_KONEC, nasprotnik
from logika_igre import *

######################################################################
## Algoritem minimax

class Minimax:
    # Algoritem minimax predstavimo z objektom, ki hrani stanje igre in
    # algoritma, nima pa dostopa do GUI (ker ga ne sme uporabljati, saj deluje
    # v drugem vlaknu kot tkinter).

    def __init__(self, globina):
        self.globina = globina  # do katere globine iščemo
        self.prekinitev = False # ali moramo končati
        self.igra = None # objekt, ki opisuje igro (ga dobimo kasneje)
        self.jaz = None  # katerega igralca igramo (podatek dobimo kasneje)
        self.poteza = None # sem napišemo potezo, ko jo najdemo

    def prekini(self):
        """Metoda, ki jo pokliče GUI, če je treba nehati razmišljati, ker
           je uporabnik zaprl okno ali izbral novo igro."""
        self.prekinitev = True

    def izracunaj_potezo(self, igra):
        """Izračunaj potezo za trenutno stanje dane igre."""
        # To metodo pokličemo iz vzporednega vlakna
        self.igra = igra
        self.prekinitev = False # Glavno vlakno bo to nastvilo na True, če moramo nehati
        self.jaz = self.igra.na_potezi
        self.poteza = None # Sem napišemo potezo, ko jo najdemo
        # Poženemo minimax
        (poteza, vrednost) = self.minimax(self.globina, True)
        self.jaz = None
        self.igra = None
        if not self.prekinitev:
            # Potezo izvedemo v primeru, da nismo bili prekinjeni
            logging.debug("minimax: poteza {0}, vrednost {1}".format(poteza, vrednost))
            self.poteza = poteza

    # Vrednosti igre
    ZMAGA = 100000
    NESKONCNO = ZMAGA + 1 # Več kot zmaga

    def vrednost_pozicije(self):
        """Ocena vrednosti pozicije na plošči."""
        # Nastavimo vrednost na 0 in definiramo, kar bomo potrebovali.
        vrednost = 0
        plosca = self.igra.plosca
        izpodrinjeni = self.igra.izpodrinjeni
        moja_barva = self.igra.pripadajoca_barva(self.jaz)
        nasprotnikova_barva = self.igra.pripadajoca_barva(nasprotnik(self.jaz))
        prazno = self.igra.barva_praznih
        # Najprej preštejemo svoje in nasprotnikove izpodrinjene krogce (s tem spodbujamo agresivno igro - glej navodila)
        moji_izpodrinjeni = izpodrinjeni.count(moja_barva)
        nasprotnikovi_izpodrinjeni = izpodrinjeni.count(nasprotnikova_barva)
        vrednost += (1000 * moji_izpodrinjeni - 900 * nasprotnikovi_izpodrinjeni)
        # Naredimo seznam "smeri", v katerem bodo vse vrstice, stolpci in diagonale.
        smeri = []
        glavna_diagonala = []
        for i in range(11):
            x = []
            y = []
            if plosca[i][i] is not None:
                glavna_diagonala.append(plosca[i][i])
            for j in range(11):
                if plosca[i][j] is not None:
                    y.append(plosca[i][j])
                if plosca[j][i] is not None:
                    x.append(plosca[j][i])
            if len(x) != 0:
                smeri.append([None] + x + [None])
            if len(y) != 0:
                smeri.append([None] + y + [None])
        smeri.append([None] + glavna_diagonala + [None])
        zacetki_diagonal = [(1,2),(1,3),(1,4),(1,5)]
        for (i,j) in zacetki_diagonal:
            spodnja_diagonala = []
            zgornja_diagonala = []
            while plosca[i][j] is not None:
                spodnja_diagonala.append(plosca[i][j])
                zgornja_diagonala.append(plosca[j][i])
                i += 1
                j += 1
            smeri.append([None] + spodnja_diagonala + [None])
            smeri.append([None] + zgornja_diagonala + [None])

        pozicije = {
            # Pozicije, kjer smo nasprotnika izrinili s plošče - zelo zelo dobro.
            (None, nasprotnikova_barva, moja_barva, moja_barva) : 3700,
            (None, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 3700,
            (None, nasprotnikova_barva, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 3900,
            # Pozicije, kjer lahko v naslednji potezi mi izrinemo s plošče - zelo dobro.
            (None, nasprotnikova_barva, moja_barva, moja_barva) : 1700,
            (None, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1700,
            (None, nasprotnikova_barva, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1900,
            # Pozicije, kjer lahko čez 2 potezi izrinemo nasprotnika s plošče - dobro.
            (None, prazno, nasprotnikova_barva, moja_barva, moja_barva) : 1400,
            (None, prazno, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1400,
            (None, prazno, nasprotnikova_barva, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1500,
            (None, nasprotnikova_barva, prazno, moja_barva, moja_barva) : 1400,
            (None, nasprotnikova_barva, prazno, moja_barva, moja_barva, moja_barva) : 1400,
            (None, nasprotnikova_barva, prazno, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1500,
            # Pozicije, kjer so nas izrinili s plošče - zelo zelo slabo.
            (None, moja_barva, nasprotnikova_barva, nasprotnikova_barva) : -3600,
            (None, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -3600,
            (None, moja_barva, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -3800,
           # Pozicije, kjer nas lahko v naslednji potezi izrinejo s plošče - zelo slabo.
            (None, moja_barva, nasprotnikova_barva, nasprotnikova_barva) : -1600,
            (None, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1600,
            (None, moja_barva, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1800,
            # Pozicije, kjer nas lahko čez 2 potezi izrinejo s plošče - slabo.
            (None, prazno, moja_barva, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (None, prazno, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (None, prazno, moja_barva, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1400,
            (None, moja_barva, prazno, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (None, moja_barva, prazno, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (None, moja_barva, prazno, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1400}
        for smer in smeri:
            #Mislim, da zaradi tega sploh ne pride do nekaterih potez v "pozicije". Drugi krogec je namreč prazen in zato vrednosti prišteje 10, ne gre pa v else!!
##            #Nočemo biti na robu
##            if smer[1] == prazno:
##                vrednost += 10
##            if smer[-2] == prazno:
##                vrednost += 10
            if moja_barva not in smer or nasprotnikova_barva not in smer:
                continue
            else:
                for pozicija in pozicije:
                    # Pozicija se lahko pojavi na koncu ali pa na začetku smeri.
                    na_zacetku = len(pozicija)
                    na_koncu = len(pozicija)
                    for i in range(len(pozicija)):
                        if len(pozicija) > len(smer):
                            break
                        if smer[i] == pozicija[i] or smer[-1-i] == pozicija[i]:
                            if smer[i] == pozicija[i]:
                                na_zacetku -= 1
                            elif smer[-1-i] == pozicija[i]:
                                na_koncu -= 1
                        else:
                            break
                    if na_zacetku == 0 and na_koncu == 0:
                        vrednost += 2 * pozicije[pozicija]
                    elif na_zacetku == 0 or na_koncu == 0:
                        vrednost += pozicije[pozicija]
        return vrednost

    def minimax(self, globina, maksimiziramo):
        """Glavna metoda minimax."""
        if self.prekinitev:
            # Sporočili so nam, da moramo prekiniti
            logging.debug ("Minimax prekinja, globina = {0}".format(globina))
            return (None, 0)
        zmagovalec = self.igra.stanje_igre()
        if zmagovalec in (IGRALEC_1, IGRALEC_2):
            # Igre je konec, vrnemo njeno vrednost
            if zmagovalec == self.jaz:
                return (None, Minimax.ZMAGA)
            elif zmagovalec == nasprotnik(self.jaz):
                return (None, -Minimax.ZMAGA)
            else:
                return (None, 0)
        elif zmagovalec == NI_KONEC:
            # Igre ni konec
            if globina == 0:
                return (None, self.vrednost_pozicije())
            else:
                # Naredimo eno stopnjo minimax
                if maksimiziramo:
                    print('MAX')
                    # Maksimiziramo
                    najboljsa_poteza = None
                    vrednost_najboljse = -Minimax.NESKONCNO
                    najboljse_poteze = []
                    s = 0
                    for poteza in self.igra.veljavne_poteze():
                        s += 1
                        [izbrani, p] = poteza
                        if type(izbrani[0]) == int:
                                (x,y) = izbrani
                                self.igra.izbrani.append((x,y))
                        else:
                            for (x,y) in izbrani:
                                self.igra.izbrani.append((x,y))
                        #self.igra.shrani_pozicijo()
                        self.igra.povleci_potezo(p)
                        vrednost = self.minimax(globina-1, not maksimiziramo)[1]
                        #if self.igra.povleci_potezo(p) is not None:
                        self.igra.razveljavi()
                        if vrednost == vrednost_najboljse:
                            najboljse_poteze.append(poteza)
                        elif vrednost > vrednost_najboljse:
                            print('boljse!', vrednost)
                            print('max',s)
                            vrednost_najboljse = vrednost
                            najboljse_poteze = [poteza]
                        self.igra.izbrani = []
                    najboljsa_poteza = random.choice(najboljse_poteze)
                    print('NAJmax:', vrednost)
                else:
                    # Minimiziramo
                    print('MIN')
                    najboljsa_poteza = None
                    vrednost_najboljse = Minimax.NESKONCNO
                    najboljse_poteze = []
                    s = 0
                    for poteza in self.igra.veljavne_poteze():
                        s += 1
                        [izbrani, p] = poteza
                        if type(izbrani[0]) == int:
                                (x,y) = izbrani
                                self.igra.izbrani.append((x,y))
                        else:
                            for (x,y) in izbrani:
                                self.igra.izbrani.append((x,y))
                        self.igra.shrani_pozicijo()
                        self.igra.povleci_potezo(p)
                        vrednost = self.minimax(globina-1, not maksimiziramo)[1]
                        if self.igra.povleci_potezo(p) is not None:
                            self.igra.razveljavi()
                        if vrednost == vrednost_najboljse:
                            najboljse_poteze.append(poteza)
                        elif vrednost < vrednost_najboljse:
                            print('slabse!', vrednost)
                            print('min',s)
                            vrednost_najboljse = vrednost
                            najboljse_poteze = [poteza]
                        self.igra.izbrani = []
                    najboljsa_poteza = random.choice(najboljse_poteze)
                    print('NAJmin:', vrednost)
                assert (najboljsa_poteza is not None), "minimax: izračunana poteza je None"
                return (najboljsa_poteza, vrednost_najboljse)
        else:
            assert False, "minimax: nedefinirano stanje igre"
<commit_msg>Združena datoteka - minimax<commit_after>import logging
import random

#from logika_igre import IGRALEC_1, IGRALEC_2, NI_KONEC, nasprotnik
from logika_igre import *

######################################################################
## Algoritem minimax

class Minimax:
    # Algoritem minimax predstavimo z objektom, ki hrani stanje igre in
    # algoritma, nima pa dostopa do GUI (ker ga ne sme uporabljati, saj deluje
    # v drugem vlaknu kot tkinter).

    def __init__(self, globina):
        self.globina = globina  # do katere globine iščemo
        self.prekinitev = False # ali moramo končati
        self.igra = None # objekt, ki opisuje igro (ga dobimo kasneje)
        self.jaz = None  # katerega igralca igramo (podatek dobimo kasneje)
        self.poteza = None # sem napišemo potezo, ko jo najdemo

    def prekini(self):
        """Metoda, ki jo pokliče GUI, če je treba nehati razmišljati, ker
           je uporabnik zaprl okno ali izbral novo igro."""
        self.prekinitev = True

    def izracunaj_potezo(self, igra):
        """Izračunaj potezo za trenutno stanje dane igre."""
        # To metodo pokličemo iz vzporednega vlakna
        self.igra = igra
        self.prekinitev = False # Glavno vlakno bo to nastvilo na True, če moramo nehati
        self.jaz = self.igra.na_potezi
        self.poteza = None # Sem napišemo potezo, ko jo najdemo
        # Poženemo minimax
        (poteza, vrednost) = self.minimax(self.globina, True)
        self.jaz = None
        self.igra = None
        if not self.prekinitev:
            # Potezo izvedemo v primeru, da nismo bili prekinjeni
            logging.debug("minimax: poteza {0}, vrednost {1}".format(poteza, vrednost))
            self.poteza = poteza

    # Vrednosti igre
    ZMAGA = 100000
    NESKONCNO = ZMAGA + 1 # Več kot zmaga

    def vrednost_pozicije(self):
        """Ocena vrednosti pozicije na plošči."""
        # Nastavimo vrednost na 0 in definiramo, kar bomo potrebovali.
        vrednost = 0
        plosca = self.igra.plosca
        izpodrinjeni = self.igra.izpodrinjeni
        moja_barva = self.igra.pripadajoca_barva(self.jaz)
        nasprotnikova_barva = self.igra.pripadajoca_barva(nasprotnik(self.jaz))
        prazno = self.igra.barva_praznih
        # Najprej preštejemo svoje in nasprotnikove izpodrinjene krogce (s tem spodbujamo agresivno igro - glej navodila)
        moji_izpodrinjeni = izpodrinjeni.count(moja_barva)
        nasprotnikovi_izpodrinjeni = izpodrinjeni.count(nasprotnikova_barva)
        vrednost += (1000 * moji_izpodrinjeni - 900 * nasprotnikovi_izpodrinjeni)
        # Naredimo seznam "smeri", v katerem bodo vse vrstice, stolpci in diagonale.
        smeri = []
        glavna_diagonala = []
        for i in range(11):
            x = []
            y = []
            if plosca[i][i] is not None:
                glavna_diagonala.append(plosca[i][i])
            for j in range(11):
                if plosca[i][j] is not None:
                    y.append(plosca[i][j])
                if plosca[j][i] is not None:
                    x.append(plosca[j][i])
            if len(x) != 0:
                smeri.append(x)
            if len(y) != 0:
                smeri.append(y)
        smeri.append(glavna_diagonala)
        zacetki_diagonal = [(1,2),(1,3),(1,4),(1,5)]
        for (i,j) in zacetki_diagonal:
            spodnja_diagonala = []
            zgornja_diagonala = []
            while plosca[i][j] is not None:
                spodnja_diagonala.append(plosca[i][j])
                zgornja_diagonala.append(plosca[j][i])
                i += 1
                j += 1
            smeri.append(spodnja_diagonala)
            smeri.append(zgornja_diagonala)
        pozicije = {
            # Pozicije, kjer lahko v naslednji potezi mi izrinemo s plošče - zelo dobro.
            (nasprotnikova_barva, moja_barva, moja_barva) : 3700,
            (nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 3700,
            (nasprotnikova_barva, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 3900,
            # Pozicije, kjer lahko čez 2 potezi izrinemo nasprotnika s plošče - dobro.
            (prazno, nasprotnikova_barva, moja_barva, moja_barva) : 1400,
            (prazno, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1400,
            (prazno, nasprotnikova_barva, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1500,
            (nasprotnikova_barva, prazno, moja_barva, moja_barva) : 1400,
            (nasprotnikova_barva, prazno, moja_barva, moja_barva, moja_barva) : 1400,
            (nasprotnikova_barva, prazno, nasprotnikova_barva, moja_barva, moja_barva, moja_barva) : 1500,
            # Pozicije, kjer nas lahko v naslednji potezi izrinejo s plošče - zelo slabo.
            (moja_barva, nasprotnikova_barva, nasprotnikova_barva) : -3600,
            (moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -3600,
            (moja_barva, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -3800,
            # Pozicije, kjer nas lahko čez 2 potezi izrinejo s plošče - slabo.
            (prazno, moja_barva, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (prazno, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (prazno, moja_barva, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1400,
            (moja_barva, prazno, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (moja_barva, prazno, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1300,
            (moja_barva, prazno, moja_barva, nasprotnikova_barva, nasprotnikova_barva, nasprotnikova_barva) : -1400}
        for smer in smeri:
##            #Nočemo biti na robu
##            if smer[1] == prazno:
##                vrednost += 10
##            if smer[-2] == prazno:
##                vrednost += 10
            if moja_barva not in smer or nasprotnikova_barva not in smer:
                continue
            else:
                for pozicija in pozicije:
                    # Pozicija se lahko pojavi na koncu ali pa na začetku smeri.
                    na_zacetku = len(pozicija)
                    na_koncu = len(pozicija)
                    for i in range(len(pozicija)):
                        if len(pozicija) > len(smer):
                            break
                        if smer[i] == pozicija[i] or smer[-1-i] == pozicija[i]:
                            if smer[i] == pozicija[i]:
                                na_zacetku -= 1
                            elif smer[-1-i] == pozicija[i]:
                                na_koncu -= 1
                        else:
                            break
                    if na_zacetku == 0 and na_koncu == 0:
                        vrednost += 2 * pozicije[pozicija]
                    elif na_zacetku == 0 or na_koncu == 0:
                        vrednost += pozicije[pozicija]
        return vrednost

    def minimax(self, globina, maksimiziramo):
        """Glavna metoda minimax."""
        if self.prekinitev:
            # Sporočili so nam, da moramo prekiniti
            logging.debug ("Minimax prekinja, globina = {0}".format(globina))
            return (None, 0)
        zmagovalec = self.igra.stanje_igre()
        if zmagovalec in (IGRALEC_1, IGRALEC_2):
            # Igre je konec, vrnemo njeno vrednost
            if zmagovalec == self.jaz:
                return (None, Minimax.ZMAGA)
            elif zmagovalec == nasprotnik(self.jaz):
                return (None, -Minimax.ZMAGA)
            else:
                return (None, 0)
        elif zmagovalec == NI_KONEC:
            # Igre ni konec
            if globina == 0:
                return (None, self.vrednost_pozicije())
            else:
                # Naredimo eno stopnjo minimax
                if maksimiziramo:
                    # Maksimiziramo
                    najboljsa_poteza = None
                    vrednost_najboljse = -Minimax.NESKONCNO
                    najboljse_poteze = []
                    for poteza in self.igra.veljavne_poteze():
                        [izbrani, p] = poteza
                        if type(izbrani[0]) == int:
                                (x,y) = izbrani
                                self.igra.izbrani.append((x,y))
                        else:
                            for (x,y) in izbrani:
                                self.igra.izbrani.append((x,y))
                        self.igra.shrani_pozicijo()
                        self.igra.povleci_potezo(p)
                        vrednost = self.minimax(globina-1, not maksimiziramo)[1]
                        if self.igra.povleci_potezo(p) is not None:
                            self.igra.razveljavi()
                        if vrednost == vrednost_najboljse:
                            najboljse_poteze.append(poteza)
                        elif vrednost > vrednost_najboljse:
                            vrednost_najboljse = vrednost
                            najboljse_poteze = [poteza]
                        self.igra.izbrani = []
                    najboljsa_poteza = random.choice(najboljse_poteze)
                else:
                    # Minimiziramo
                    najboljsa_poteza = None
                    vrednost_najboljse = Minimax.NESKONCNO
                    for poteza in self.igra.veljavne_poteze():
                        [izbrani, p] = poteza
                        if type(izbrani[0]) == int:
                                (x,y) = izbrani
                                self.igra.izbrani.append((x,y))
                        else:
                            for (x,y) in izbrani:
                                self.igra.izbrani.append((x,y))
                        self.igra.shrani_pozicijo()
                        self.igra.povleci_potezo(p)
                        vrednost = self.minimax(globina-1, not maksimiziramo)[1]
                        if self.igra.povleci_potezo(p) is not None:
                            self.igra.razveljavi()
                        if vrednost == vrednost_najboljse:
                            najboljse_poteze.append(poteza)
                        elif vrednost < vrednost_najboljse:
                            vrednost_najboljse = vrednost
                            najboljse_poteze = [poteza]
                        self.igra.izbrani = []
                    najboljsa_poteza = random.choice(najboljse_poteze)

                assert (najboljsa_poteza is not None), "minimax: izračunana poteza je None"
                return (najboljsa_poteza, vrednost_najboljse)
        else:
            assert False, "minimax: nedefinirano stanje igre"
<|endoftext|>


<commit_before><commit_msg>mgmt, bug fix for swagger automation (#32179)<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env python

"""minipkg.py - install pkgsrc

Usage:
    python minipkg.py
    python minipkg.py [-h | --help] [-v | --version]
"""

from __future__ import print_function

import hashlib
import os
import string
import subprocess
import sys
try:
    from urllib2 import (
        Request as url_request,
        urlopen as url_open,
    )
except ImportError:
    import urllib.request.Request as url_request
    import urllib.request.urlopen as url_open

__author__ = 'Mansour Moufid'
__copyright__ = 'Copyright 2015, 2016, Mansour Moufid'
__email__ = 'mansourmoufid@gmail.com'
__license__ = 'ISC'
__status__ = 'Development'
__version__ = '1.5'

supported_sys = ('Linux', 'Darwin')

supported_mach = {
    'x86_64': '64',
}

archives = [
    'http://minipkg.eliteraspberries.com/pkgsrc-2015Q4.tar.gz',
    'http://minipkg.eliteraspberries.com/pkgsrc-eliteraspberries-0.9.tar.gz',
]

hash_algorithm = hashlib.sha256

archive_hashes = [
    'fe56b3e5c2596a4533180de4c8a145f7e9d0f06b573e6a667770ec59176b18d4',
    '6d882da57b8fc190d88614e6d6c6334e49ef889ebf1b686763a83687af944176',
]

def which(name):
    p = subprocess.Popen(['which', name], stdout=subprocess.PIPE)
    p.wait()
    if not p.returncode == 0:
        return None
    out = p.stdout.read()
    return out.rstrip('\n')

def uname():
    p = subprocess.Popen(['uname', '-sm'], stdout=subprocess.PIPE)
    p.wait()
    assert p.returncode == 0, 'uname'
    (sys, mach) = p.stdout.read().split()
    return (sys, mach)

def fetch(url, hash):
    filename = os.path.basename(url)
    if not os.path.exists(filename):
        req = url_request(url)
        res = url_open(req)
        dat = res.read()
        with open(filename, 'wb+') as f:
            f.write(dat)
    with open(filename, 'r') as f:
        dat = f.read()
    h = hash_algorithm(dat)
    assert h.hexdigest() == hash

def extract(tgz, path):
    if not os.path.exists(path):
        os.mkdir(path)
    tar = tgz.rstrip('.gz')
    if not os.path.exists(tar):
        err = subprocess.call(['gunzip', tgz])
        assert err == 0, 'gunzip'
    err = subprocess.call(['tar', '-xf', tar, '-C', path])
    assert err == 0, 'tar'

recommended_packages = [
    'digest-20121220.tgz',
    'ncurses-6.0nb1.tgz',
    'nbpatch-20151107.tgz',
    'perl-5.22.0.tgz',
    'ocaml-4.02.3nb5.tgz',
    'ocaml-findlib-1.6.1nb3.tgz',
    'libtool-base-2.4.2nb10.tgz',
    'lzip-1.17.tgz',
    'gmp-6.1.0nb2.tgz',
    'zarith-1.4.1nb7.tgz',
    'gettext-lib-0.19.6.tgz',
    'p5-gettext-1.07.tgz',
    'xz-5.2.2.tgz',
    'gettext-tools-0.19.6.tgz',
    'help2man-1.47.3.tgz',
    'autoconf-2.69nb6.tgz',
    'ocamlgraph-1.8.6nb7.tgz',
    'alt-ergo-1.01.tgz',
    'gtar-base-1.28nb1.tgz',
    'frama-c-20150201nb6.tgz',
    'pkg-config-0.29.tgz',
    'fftw-3.3.4nb2.tgz',
    'parmap-1.0rc7nb4.tgz',
    'menhir-20151112nb3.tgz',
    'camlp4-4.02.6nb5.tgz',
    'pcre-8.38.tgz',
    'coccinelle-1.0.4nb2.tgz',
    'zlib-1.2.8nb3.tgz',
    'gmake-4.1nb1.tgz',
    'automake-1.15nb2.tgz',
    'gzip-1.6.tgz',
    'bzip2-1.0.6nb1.tgz',
]

def install_binary_package(home, repo, pkg):
    pkg_url = '/'.join([repo, 'All', pkg])
    prefix = os.path.join(home, 'pkg')
    ret = subprocess.call([
        os.path.join(home, 'pkg', 'sbin', 'pkg_add'),
        '-I',
        '-p', prefix,
        pkg_url,
    ])
    assert ret == 0, 'pkg_add'

cwd = os.path.split(os.path.abspath(__file__))[0]

minipkg_profile_template = """
export SH="$sh"
export PATH="$home/pkg/bin:$PATH"
export PATH="$home/pkg/sbin:$PATH"
export MANPATH="$home/pkg/man:$MANPATH"
export FRAMAC_LIB="$home/pkg/lib/frama-c"
export FRAMAC_SHARE="$home/pkg/share/frama-c"
export COCCINELLE_HOME="$home/pkg/lib/coccinelle"
"""

if __name__ == '__main__':

    if len(sys.argv) == 1:
        pass
    elif len(sys.argv) == 2:
        if sys.argv[1] in ('-h', '--help'):
            print(__doc__)
            print('Supported systems:', supported_sys)
            print('Supported architectures:', list(supported_mach.keys()))
            sys.exit(os.EX_OK)
        elif sys.argv[1] in ('-v', '--version'):
            print(os.path.basename(sys.argv[0]), 'version', __version__)
            sys.exit(os.EX_OK)
    else:
        print(__doc__)
        sys.exit(os.EX_USAGE)

    print('minipkg: version', __version__)

    # Step 1:
    # Determine some information about the machine.
    HOME = os.environ['HOME']
    OPSYS, mach = uname()
    assert OPSYS in supported_sys, 'unsupported system'
    assert mach in supported_mach, 'unsupported architecture'
    ABI = supported_mach[mach]
    CC = os.environ.get('CC', 'clang')
    assert which(CC), CC
    print('minipkg: HOME:', HOME)
    print('minipkg: OPSYS:', OPSYS)
    print('minipkg: ABI:', ABI)
    print('minipkg: CC:', CC)

    # Step 2:
    # Fetch the pkgsrc archive.
    for (archive, hash) in zip(archives, archive_hashes):
        print('minipkg: fetching', archive, '...')
        fetch(archive, hash)

    # Step 3:
    # Extract the pkgsrc archive.
    home_usr = os.path.join(HOME, 'usr')
    for tgz in map(os.path.basename, archives):
        print('minipkg: extracting', tgz, '...')
        extract(tgz, home_usr)
    localbase = os.path.join(HOME, 'usr', 'pkgsrc')
    overwrite_pkgpaths = [
        'devel/gmp',
        'devel/libffi',
        'devel/ncurses',
        'devel/readline',
    ]
    for pkgpath in overwrite_pkgpaths:
        cat, pkg = pkgpath.split('/')
        os.chdir(localbase)
        ret = subprocess.call(['rm', '-rf', pkgpath])
        assert ret == 0, 'rm'
        ret = subprocess.call([
            'ln', '-s',
            os.path.join(localbase, 'eliteraspberries', pkg),
            os.path.join(localbase, cat, pkg),
        ])
        assert ret == 0, 'ln'

    # Step 4:
    # Bootstrap pkgsrc.
    print('minipkg: bootstrapping ...')
    sh = os.environ.get('SH', '/bin/bash')
    sh = sh.split(os.pathsep)[0]
    assert os.path.exists(sh), sh
    os.environ.update({'SH': sh})
    bootstrap_path = os.path.join(HOME, 'usr', 'pkgsrc', 'bootstrap')
    if not os.path.exists(os.path.join(bootstrap_path, 'work')):
        os.chdir(bootstrap_path)
        p = subprocess.Popen(
            [
                './bootstrap',
                '--unprivileged',
                '--abi', ABI,
                '--compiler', CC,
                '--make-jobs', '4',
                '--prefer-pkgsrc', 'no',
                '--mk-fragment', os.path.join(cwd, 'mk.conf'),
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        out, err = p.communicate()
        log = os.path.join(HOME, 'pkgsrc-bootstrap-log.txt')
        with open(log, 'w+') as f:
            f.write(out)
            f.write(err)
        assert p.returncode == 0, 'bootstrap'
        try:
            os.remove(log)
        except OSError:
            pass

    # Step 5:
    # Set environment variables.
    print('minipkg: setting environment variables ...')
    template = string.Template(minipkg_profile_template)
    profile = template.safe_substitute({
        'home': HOME,
        'sh': sh,
    })
    minipkg_profile = os.path.join(HOME, '.minipkg_profile')
    with open(minipkg_profile, 'w+') as f:
        print('# generated by minipkg', file=f)
        f.write(profile)
    dotfile = os.path.join(HOME, '.bash_profile')
    try:
        with open(dotfile, 'r') as f:
            profile = f.read()
    except IOError:
        profile = ''
    with open(dotfile, 'w+') as f:
        print('source %s' % (minipkg_profile), file=f)
        print('', file=f)
        f.write(profile)

    # Step 6:
    # Install recommended binary packages.
    print('minipkg: installing packages ...')
    repo = '/'.join([
        'http://minipkg.eliteraspberries.com/packages',
        OPSYS,
        mach,
    ])
    for pkg in recommended_packages:
        install_binary_package(HOME, repo, pkg)

    print('minipkg: done!')
<commit_msg>Use the latest pkgsrc-eliteraspberries.<commit_after>#!/usr/bin/env python

"""minipkg.py - install pkgsrc

Usage:
    python minipkg.py
    python minipkg.py [-h | --help] [-v | --version]
"""

from __future__ import print_function

import hashlib
import os
import string
import subprocess
import sys
try:
    from urllib2 import (
        Request as url_request,
        urlopen as url_open,
    )
except ImportError:
    import urllib.request.Request as url_request
    import urllib.request.urlopen as url_open

__author__ = 'Mansour Moufid'
__copyright__ = 'Copyright 2015, 2016, Mansour Moufid'
__email__ = 'mansourmoufid@gmail.com'
__license__ = 'ISC'
__status__ = 'Development'
__version__ = '1.5'

supported_sys = ('Linux', 'Darwin')

supported_mach = {
    'x86_64': '64',
}

archives = [
    'http://minipkg.eliteraspberries.com/pkgsrc-2015Q4.tar.gz',
    'http://minipkg.eliteraspberries.com/pkgsrc-eliteraspberries-1.0.tar.gz',
]

hash_algorithm = hashlib.sha256

archive_hashes = [
    'fe56b3e5c2596a4533180de4c8a145f7e9d0f06b573e6a667770ec59176b18d4',
    'de601b528f771e795162df3d64aa376e644e900e0fb3f2dc45399d89c6216d24',
]

def which(name):
    p = subprocess.Popen(['which', name], stdout=subprocess.PIPE)
    p.wait()
    if not p.returncode == 0:
        return None
    out = p.stdout.read()
    return out.rstrip('\n')

def uname():
    p = subprocess.Popen(['uname', '-sm'], stdout=subprocess.PIPE)
    p.wait()
    assert p.returncode == 0, 'uname'
    (sys, mach) = p.stdout.read().split()
    return (sys, mach)

def fetch(url, hash):
    filename = os.path.basename(url)
    if not os.path.exists(filename):
        req = url_request(url)
        res = url_open(req)
        dat = res.read()
        with open(filename, 'wb+') as f:
            f.write(dat)
    with open(filename, 'r') as f:
        dat = f.read()
    h = hash_algorithm(dat)
    assert h.hexdigest() == hash

def extract(tgz, path):
    if not os.path.exists(path):
        os.mkdir(path)
    tar = tgz.rstrip('.gz')
    if not os.path.exists(tar):
        err = subprocess.call(['gunzip', tgz])
        assert err == 0, 'gunzip'
    err = subprocess.call(['tar', '-xf', tar, '-C', path])
    assert err == 0, 'tar'

recommended_packages = [
    'digest-20121220.tgz',
    'ncurses-6.0nb1.tgz',
    'nbpatch-20151107.tgz',
    'perl-5.22.0.tgz',
    'ocaml-4.02.3nb5.tgz',
    'ocaml-findlib-1.6.1nb4.tgz',
    'libtool-base-2.4.2nb10.tgz',
    'lzip-1.17.tgz',
    'gmp-6.1.0nb2.tgz',
    'zarith-1.4.1nb7.tgz',
    'gettext-lib-0.19.6.tgz',
    'p5-gettext-1.07.tgz',
    'xz-5.2.2.tgz',
    'gettext-tools-0.19.6.tgz',
    'help2man-1.47.3.tgz',
    'autoconf-2.69nb6.tgz',
    'ocamlgraph-1.8.6nb7.tgz',
    'alt-ergo-1.01.tgz',
    'gtar-base-1.28nb1.tgz',
    'frama-c-20151002.tgz',
    'pkg-config-0.29.tgz',
    'fftw-3.3.4nb2.tgz',
    'parmap-1.0rc7nb4.tgz',
    'menhir-20151112nb3.tgz',
    'camlp4-4.02.6nb5.tgz',
    'pcre-8.38.tgz',
    'coccinelle-1.0.4nb2.tgz',
    'zlib-1.2.8nb3.tgz',
    'gmake-4.1nb1.tgz',
    'automake-1.15nb2.tgz',
    'gzip-1.6.tgz',
    'bzip2-1.0.6nb1.tgz',
]

def install_binary_package(home, repo, pkg):
    pkg_url = '/'.join([repo, 'All', pkg])
    prefix = os.path.join(home, 'pkg')
    ret = subprocess.call([
        os.path.join(home, 'pkg', 'sbin', 'pkg_add'),
        '-I',
        '-p', prefix,
        pkg_url,
    ])
    assert ret == 0, 'pkg_add'

cwd = os.path.split(os.path.abspath(__file__))[0]

minipkg_profile_template = """
export SH="$sh"
export PATH="$home/pkg/bin:$PATH"
export PATH="$home/pkg/sbin:$PATH"
export MANPATH="$home/pkg/man:$MANPATH"
export FRAMAC_LIB="$home/pkg/lib/frama-c"
export FRAMAC_SHARE="$home/pkg/share/frama-c"
export COCCINELLE_HOME="$home/pkg/lib/coccinelle"
"""

if __name__ == '__main__':

    if len(sys.argv) == 1:
        pass
    elif len(sys.argv) == 2:
        if sys.argv[1] in ('-h', '--help'):
            print(__doc__)
            print('Supported systems:', supported_sys)
            print('Supported architectures:', list(supported_mach.keys()))
            sys.exit(os.EX_OK)
        elif sys.argv[1] in ('-v', '--version'):
            print(os.path.basename(sys.argv[0]), 'version', __version__)
            sys.exit(os.EX_OK)
    else:
        print(__doc__)
        sys.exit(os.EX_USAGE)

    print('minipkg: version', __version__)

    # Step 1:
    # Determine some information about the machine.
    HOME = os.environ['HOME']
    OPSYS, mach = uname()
    assert OPSYS in supported_sys, 'unsupported system'
    assert mach in supported_mach, 'unsupported architecture'
    ABI = supported_mach[mach]
    CC = os.environ.get('CC', 'clang')
    assert which(CC), CC
    print('minipkg: HOME:', HOME)
    print('minipkg: OPSYS:', OPSYS)
    print('minipkg: ABI:', ABI)
    print('minipkg: CC:', CC)

    # Step 2:
    # Fetch the pkgsrc archive.
    for (archive, hash) in zip(archives, archive_hashes):
        print('minipkg: fetching', archive, '...')
        fetch(archive, hash)

    # Step 3:
    # Extract the pkgsrc archive.
    home_usr = os.path.join(HOME, 'usr')
    for tgz in map(os.path.basename, archives):
        print('minipkg: extracting', tgz, '...')
        extract(tgz, home_usr)
    localbase = os.path.join(HOME, 'usr', 'pkgsrc')
    overwrite_pkgpaths = [
        'devel/gmp',
        'devel/libffi',
        'devel/ncurses',
        'devel/readline',
    ]
    for pkgpath in overwrite_pkgpaths:
        cat, pkg = pkgpath.split('/')
        os.chdir(localbase)
        ret = subprocess.call(['rm', '-rf', pkgpath])
        assert ret == 0, 'rm'
        ret = subprocess.call([
            'ln', '-s',
            os.path.join(localbase, 'eliteraspberries', pkg),
            os.path.join(localbase, cat, pkg),
        ])
        assert ret == 0, 'ln'

    # Step 4:
    # Bootstrap pkgsrc.
    print('minipkg: bootstrapping ...')
    sh = os.environ.get('SH', '/bin/bash')
    sh = sh.split(os.pathsep)[0]
    assert os.path.exists(sh), sh
    os.environ.update({'SH': sh})
    bootstrap_path = os.path.join(HOME, 'usr', 'pkgsrc', 'bootstrap')
    if not os.path.exists(os.path.join(bootstrap_path, 'work')):
        os.chdir(bootstrap_path)
        p = subprocess.Popen(
            [
                './bootstrap',
                '--unprivileged',
                '--abi', ABI,
                '--compiler', CC,
                '--make-jobs', '4',
                '--prefer-pkgsrc', 'no',
                '--mk-fragment', os.path.join(cwd, 'mk.conf'),
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        out, err = p.communicate()
        log = os.path.join(HOME, 'pkgsrc-bootstrap-log.txt')
        with open(log, 'w+') as f:
            f.write(out)
            f.write(err)
        assert p.returncode == 0, 'bootstrap'
        try:
            os.remove(log)
        except OSError:
            pass

    # Step 5:
    # Set environment variables.
    print('minipkg: setting environment variables ...')
    template = string.Template(minipkg_profile_template)
    profile = template.safe_substitute({
        'home': HOME,
        'sh': sh,
    })
    minipkg_profile = os.path.join(HOME, '.minipkg_profile')
    with open(minipkg_profile, 'w+') as f:
        print('# generated by minipkg', file=f)
        f.write(profile)
    dotfile = os.path.join(HOME, '.bash_profile')
    try:
        with open(dotfile, 'r') as f:
            profile = f.read()
    except IOError:
        profile = ''
    with open(dotfile, 'w+') as f:
        print('source %s' % (minipkg_profile), file=f)
        print('', file=f)
        f.write(profile)

    # Step 6:
    # Install recommended binary packages.
    print('minipkg: installing packages ...')
    repo = '/'.join([
        'http://minipkg.eliteraspberries.com/packages',
        OPSYS,
        mach,
    ])
    for pkg in recommended_packages:
        install_binary_package(HOME, repo, pkg)

    print('minipkg: done!')
<|endoftext|>