<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2013-TODAY OpenERP SA (<http://www.openerp.com>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv, expression

class res_partner(osv.osv):
    _inherit = 'res.partner'

    _contact_type = [
        ('standalone', 'Standalone Contact'),
        ('attached', 'Attached to existing Contact'),
    ]

    def _get_contact_type(self, cr, uid, ids, field_name, args, context=None):
        result = dict.fromkeys(ids, 'standalone')
        for partner in self.browse(cr, uid, ids, context=context):
            if partner.contact_id:
                result[partner.id] = 'attached'
        return result

    _columns = {
        'contact_type': fields.function(_get_contact_type, type='selection', selection=_contact_type,
                                        string='Contact Type', required=True, select=1, store=True),
        'contact_id': fields.many2one('res.partner', 'Main Contact',
                                      domain=[('is_company','=',False),('contact_type','=','standalone')]),
        'other_contact_ids': fields.one2many('res.partner', 'contact_id', 'Others Positions'),

        # Person specific fields
        'birthdate_date': fields.date('Birthdate'),  # add a 'birthdate' as date field, i.e different from char 'birthdate' introduced v6.1!
        'nationality_id': fields.many2one('res.country', 'Nationality'),
    }

    _defaults = {
        'contact_type': 'standalone',
    }

    def _basecontact_check_context(self, cr, user, mode, context=None):
        if context is None:
            context = {}
        # Remove 'search_show_all_positions' for non-search mode.
        # Keeping it in context can result in unexpected behaviour (ex: reading
        # one2many might return wrong result - i.e with "attached contact" removed
        # even if it's directly linked to a company).
        if mode != 'search':
            context.pop('search_show_all_positions', None)
        return context

    def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
        if context is None:
            context = {}
        if context.get('search_show_all_positions') is False:
            # display only standalone contact matching ``args`` or having
            # attached contact matching ``args``
            args = expression.normalize_domain(args)
            attached_contact_args = expression.AND((args, [('contact_type', '=', 'attached')]))
            attached_contact_ids = super(res_partner, self).search(cr, user, attached_contact_args,
                                                                   context=context)
            args = expression.OR((
                expression.AND(([('contact_type', '=', 'standalone')], args)),
                [('other_contact_ids', 'in', attached_contact_ids)],
            ))
        return super(res_partner, self).search(cr, user, args, offset=offset, limit=limit,
                                               order=order, context=context, count=count)

    def create(self, cr, user, vals, context=None):
        context = self._basecontact_check_context(cr, user, 'create', context)
        if not vals.get('name') and vals.get('contact_id'):
            vals['name'] = self.browse(cr, user, vals['contact_id'], context=context)
        return super(res_partner, self).create(cr, user, vals, context=context)

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        context = self._basecontact_check_context(cr, user, 'read', context)
        return super(res_partner, self).read(cr, user, ids, fields=fields, context=context, load=load)

    def write(self, cr, user, ids, vals, context=None):
        context = self._basecontact_check_context(cr, user, 'write', context)
        return super(res_partner, self).write(cr, user, ids, vals, context=context)

    def unlink(self, cr, user, ids, context=None):
        context = self._basecontact_check_context(cr, user, 'unlink', context)
        return super(res_partner, self).unlink(cr, user, ids, context=context)

    def _commercial_partner_compute(self, cr, uid, ids, name, args, context=None):
        """ Returns the partner that is considered the commercial
        entity of this partner. The commercial entity holds the master data
        for all commercial fields (see :py:meth:`~_commercial_fields`) """
        result = super(res_partner, self)._commercial_partner_compute(cr, uid, ids, name, args, context=context)
        for partner in self.browse(cr, uid, ids, context=context):
            if partner.contact_type == 'attached' and not partner.parent_id:
                result[partner.id] = partner.contact_id.id
        return result

    def onchange_contact_id(self, cr, uid, ids, contact_id, context=None):
        values = {}
        if contact_id:
            values['name'] = self.browse(cr, uid, contact_id, context=context).name
        return {'value': values}

    def onchange_contact_type(self, cr, uid, ids, contact_type, context=None):
        values = {}
        if contact_type == 'standalone':
            values['contact_id'] = False
        return {'value': values}

class ir_actions_window(osv.osv):
    _inherit = 'ir.actions.act_window'

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        action_ids = ids
        if isinstance(ids, (int, long)):
            action_ids = [ids]
        actions = super(ir_actions_window, self).read(cr, user, action_ids, fields=fields, context=context, load=load)
        for action in actions:
            if action.get('res_model', '') == 'res.partner':
                # By default, only show standalone contact
                action_context = action.get('context', '{}') or '{}'
                if 'search_show_all_positions' not in action_context:
                    action['context'] = action_context.replace('{',
                            "{'search_show_all_positions': False,", 1)
        if isinstance(ids, (int, long)):
            if actions:
                return actions[0]
            return False
        return actions
<commit_msg>[FIX] base_contact: missing .name<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2013-TODAY OpenERP SA (<http://www.openerp.com>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv, expression

class res_partner(osv.osv):
    _inherit = 'res.partner'

    _contact_type = [
        ('standalone', 'Standalone Contact'),
        ('attached', 'Attached to existing Contact'),
    ]

    def _get_contact_type(self, cr, uid, ids, field_name, args, context=None):
        result = dict.fromkeys(ids, 'standalone')
        for partner in self.browse(cr, uid, ids, context=context):
            if partner.contact_id:
                result[partner.id] = 'attached'
        return result

    _columns = {
        'contact_type': fields.function(_get_contact_type, type='selection', selection=_contact_type,
                                        string='Contact Type', required=True, select=1, store=True),
        'contact_id': fields.many2one('res.partner', 'Main Contact',
                                      domain=[('is_company','=',False),('contact_type','=','standalone')]),
        'other_contact_ids': fields.one2many('res.partner', 'contact_id', 'Others Positions'),

        # Person specific fields
        'birthdate_date': fields.date('Birthdate'),  # add a 'birthdate' as date field, i.e different from char 'birthdate' introduced v6.1!
        'nationality_id': fields.many2one('res.country', 'Nationality'),
    }

    _defaults = {
        'contact_type': 'standalone',
    }

    def _basecontact_check_context(self, cr, user, mode, context=None):
        if context is None:
            context = {}
        # Remove 'search_show_all_positions' for non-search mode.
        # Keeping it in context can result in unexpected behaviour (ex: reading
        # one2many might return wrong result - i.e with "attached contact" removed
        # even if it's directly linked to a company).
        if mode != 'search':
            context.pop('search_show_all_positions', None)
        return context

    def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
        if context is None:
            context = {}
        if context.get('search_show_all_positions') is False:
            # display only standalone contact matching ``args`` or having
            # attached contact matching ``args``
            args = expression.normalize_domain(args)
            attached_contact_args = expression.AND((args, [('contact_type', '=', 'attached')]))
            attached_contact_ids = super(res_partner, self).search(cr, user, attached_contact_args,
                                                                   context=context)
            args = expression.OR((
                expression.AND(([('contact_type', '=', 'standalone')], args)),
                [('other_contact_ids', 'in', attached_contact_ids)],
            ))
        return super(res_partner, self).search(cr, user, args, offset=offset, limit=limit,
                                               order=order, context=context, count=count)

    def create(self, cr, user, vals, context=None):
        context = self._basecontact_check_context(cr, user, 'create', context)
        if not vals.get('name') and vals.get('contact_id'):
            vals['name'] = self.browse(cr, user, vals['contact_id'], context=context).name
        return super(res_partner, self).create(cr, user, vals, context=context)

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        context = self._basecontact_check_context(cr, user, 'read', context)
        return super(res_partner, self).read(cr, user, ids, fields=fields, context=context, load=load)

    def write(self, cr, user, ids, vals, context=None):
        context = self._basecontact_check_context(cr, user, 'write', context)
        return super(res_partner, self).write(cr, user, ids, vals, context=context)

    def unlink(self, cr, user, ids, context=None):
        context = self._basecontact_check_context(cr, user, 'unlink', context)
        return super(res_partner, self).unlink(cr, user, ids, context=context)

    def _commercial_partner_compute(self, cr, uid, ids, name, args, context=None):
        """ Returns the partner that is considered the commercial
        entity of this partner. The commercial entity holds the master data
        for all commercial fields (see :py:meth:`~_commercial_fields`) """
        result = super(res_partner, self)._commercial_partner_compute(cr, uid, ids, name, args, context=context)
        for partner in self.browse(cr, uid, ids, context=context):
            if partner.contact_type == 'attached' and not partner.parent_id:
                result[partner.id] = partner.contact_id.id
        return result

    def onchange_contact_id(self, cr, uid, ids, contact_id, context=None):
        values = {}
        if contact_id:
            values['name'] = self.browse(cr, uid, contact_id, context=context).name
        return {'value': values}

    def onchange_contact_type(self, cr, uid, ids, contact_type, context=None):
        values = {}
        if contact_type == 'standalone':
            values['contact_id'] = False
        return {'value': values}

class ir_actions_window(osv.osv):
    _inherit = 'ir.actions.act_window'

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        action_ids = ids
        if isinstance(ids, (int, long)):
            action_ids = [ids]
        actions = super(ir_actions_window, self).read(cr, user, action_ids, fields=fields, context=context, load=load)
        for action in actions:
            if action.get('res_model', '') == 'res.partner':
                # By default, only show standalone contact
                action_context = action.get('context', '{}') or '{}'
                if 'search_show_all_positions' not in action_context:
                    action['context'] = action_context.replace('{',
                            "{'search_show_all_positions': False,", 1)
        if isinstance(ids, (int, long)):
            if actions:
                return actions[0]
            return False
        return actions
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
__VERSION__ = '0.1.6'
from sqlalchemy.sql.expression import asc, desc
from sqlalchemy.sql import or_, and_
from sqlalchemy.orm.properties import RelationshipProperty
from sqlalchemy.sql.expression import cast
from sqlalchemy import String

from collections import namedtuple

ColumnTuple = namedtuple('ColumnDT', ['column_name', 'mData', 'search_like', 'filter', 'search_date_range'])

def get_attr(sqla_object, attribute):
    """Returns the value of an attribute of an SQLAlchemy entity
    """
    output = sqla_object
    for x in attribute.split('.'):
        output = getattr(output, x)
    return output

class ColumnDT(ColumnTuple):
    """Class defining a DataTables Column with a ColumnTuple:

    :param column_name: name of the column as defined by the SQLAlchemy model
    :type column_name: str
    :param mData: name of the mData property as defined in the DataTables javascript options (default None)
    :type mData: str
    :param search_like: search criteria to like on without forgetting to escape the '%' character
    :type search_like: str
    :param filter: the method needed to be executed on the cell values of the column
    as an equivalent of a jinja2 filter (default None)
    :type filter: a callable object

    :returns: a ColumnDT object
    """
    def __new__(cls, column_name, mData=None, search_like=None, filter=str, search_date_range=None):
        """
        On creation, sets default None values for mData and string value for
        filter (cause: Object representation is not JSON serializable)
        """
        return super(ColumnDT, cls).__new__(cls, column_name, mData, search_like, filter, search_date_range)

class DataTables:
    """Class defining a DataTables object with:

    :param request: request containing the GET values, specified by the
    datatable for filtering, sorting and paging
    :type request: pyramid.request
    :param sqla_object: your SQLAlchemy table object
    :type sqla_object: sqlalchemy.ext.declarative.DeclarativeMeta
    :param query: the query wanted to be seen in the the table
    :type query: sqlalchemy.orm.query.Query
    :param columns: columns specification for the datatables
    :type columns: list

    :returns: a DataTables object
    """
    def __init__(self, request, sqla_object, query, columns):
        """Initializes the object with the attributes needed, and runs the query
        """
        self.request_values = request.params
        self.sqla_object = sqla_object
        self.query = query
        self.columns = columns
        self.results = None

        # total in the table after filtering
        self.cardinality_filtered = 0

        # total in the table unfiltered
        self.cardinality = 0

        self.run()

    def output_result(self):
        """Outputs the results in the format needed by DataTables
        """
        output = {}
        output['sEcho'] = str(int(self.request_values['sEcho']))
        output['iTotalRecords'] = str(self.cardinality)
        output['iTotalDisplayRecords'] = str(self.cardinality_filtered)
        output['aaData'] = self.results

        return output

    def run(self):
        """Launch filtering, sorting and paging processes to output results
        """
        # count before filtering
        self.cardinality = self.query.count()

        # the term entered in the datatable's search box
        self.filtering()

        # field chosen to sort on
        self.sorting()

        # pages have a 'start' and 'length' attributes
        self.paging()

        # fetch the result of the queries
        self.results = self.query.all()

        #return formatted results with correct filters applied
        formatted_results = []
        for i in range(len(self.results)):
            row = dict()
            for j in range(len(self.columns)):
                col = self.columns[j]
                tmp_row = get_attr(self.results[i], col.column_name)
                if col.filter:
                    tmp_row = col.filter(tmp_row)
                row[col.mData if col.mData else str(j)] = tmp_row
            formatted_results.append(row)

        self.results = formatted_results

    def filtering(self):
        """Construct the query, by adding filtering(LIKE) on all columns when the datatable's search box is used
        """
        search_value = self.request_values.get('sSearch')
        condition = None
        def search(idx, col):
            tmp_column_name = col.column_name.split('.')
            obj = getattr(self.sqla_object, tmp_column_name[0])
            if not hasattr(obj, "property"): # Ex: hybrid_property or property
                sqla_obj = self.sqla_object
                column_name = col.column_name
            elif isinstance(obj.property, RelationshipProperty): #Ex: ForeignKey
                # Ex: address.description
                sqla_obj = obj.mapper.class_
                column_name = "".join(tmp_column_name[1:])
                if not column_name:
                    # find first primary key
                    column_name = obj.property.table.primary_key.columns \
                        .values()[0].name
            else:
                sqla_obj = self.sqla_object
                column_name = col.column_name
            return sqla_obj, column_name

        if search_value:
            conditions = []
            for idx, col in enumerate(self.columns):
                if self.request_values.get('bSearchable_%s' % idx) in (
                        True, 'true'):
                    sqla_obj, column_name = search(idx, col)
                    conditions.append(cast(get_attr(sqla_obj, column_name), String).ilike('%%%s%%' % search_value))
            condition = or_(*conditions)
        conditions = []
        for idx, col in enumerate(self.columns):
            if self.request_values.get('bSearchable_%s' % idx) in (True, 'true'):
                search_value2 = self.request_values.get('sSearch_%s' % idx)
                if not search_value2:
                    continue
                sqla_obj, column_name = search(idx, col)
                if col.search_like:
                    conditions.append(get_attr(sqla_obj, column_name).like(col.search_like % search_value2))
                elif col.search_date_range:
                    _start, _end = search_value2.split(',')
                    conditions.append(and_(get_attr(sqla_obj, column_name) >= _start,
                                           get_attr(sqla_obj, column_name) <= _end))
                else:
                    conditions.append(get_attr(sqla_obj, column_name).__eq__(search_value2))

                if condition is not None:
                    condition = and_(condition, and_(*conditions))
                else:
                    condition= and_(*conditions)

        if condition is not None:
            self.query = self.query.filter(condition)
            # count after filtering
            self.cardinality_filtered = self.query.count()
        else:
            self.cardinality_filtered = self.cardinality

    def sorting(self):
        """Construct the query, by adding sorting(ORDER BY) on the columns needed to be applied on
        """
        sorting = []

        Order = namedtuple('order', ['name', 'dir'])

        if self.request_values.get('iSortCol_0') \
            and self.request_values.get('iSortingCols') > 0:

            for i in range(int(self.request_values['iSortingCols'])):
                sorting.append(Order( self.columns[int(self.request_values['iSortCol_'+str(i)])].column_name,
                        self.request_values['sSortDir_'+str(i)]))

        for sort in sorting:
            tmp_sort_name = sort.name.split('.')
            obj = getattr(self.sqla_object, tmp_sort_name[0])
            if not hasattr(obj, "property"): #hybrid_property or property
                sort_name = sort.name

                if hasattr(self.sqla_object, "__tablename__"):
                    tablename = self.sqla_object.__tablename__
                else:
                    tablename = self.sqla_object.__table__.name
            elif isinstance(obj.property, RelationshipProperty): # Ex: ForeignKey
                 # Ex: address.description => description => addresses.description
                sort_name = "".join(tmp_sort_name[1:])
                if not sort_name:
                    # Find first primary key
                    sort_name = obj.property.table.primary_key.columns \
                            .values()[0].name
                tablename = obj.property.table.name
            else: #-> ColumnProperty
                sort_name = sort.name

                if hasattr(self.sqla_object, "__tablename__"):
                    tablename = self.sqla_object.__tablename__
                else:
                    tablename = self.sqla_object.__table__.name

            sort_name = "%s.%s" % (tablename, sort_name)
            self.query = self.query.order_by(
                asc(sort_name) if sort.dir == 'asc' else desc(sort_name))

    def paging(self):
        """Construct the query, by slicing the results in order to limit rows showed on the page, and paginate the rest
        """
        pages = namedtuple('pages', ['start', 'length'])

        if (self.request_values['iDisplayStart'] != "" ) \
            and (self.request_values['iDisplayLength'] != -1 ):
            pages.start = int(self.request_values['iDisplayStart'])
            pages.length = int(self.request_values['iDisplayLength'])

        offset = pages.start + pages.length
        self.query = self.query.slice(pages.start, offset)
<commit_msg>fixes<commit_after># -*- coding: utf-8 -*-
__VERSION__ = '0.1.6'
from sqlalchemy.sql.expression import asc, desc
from sqlalchemy.sql import or_, and_
from sqlalchemy.orm.properties import RelationshipProperty
from sqlalchemy.sql.expression import cast
from sqlalchemy import String

from collections import namedtuple

ColumnTuple = namedtuple('ColumnDT', ['column_name', 'mData', 'search_like', 'filter', 'search_date_range'])

def get_attr(sqla_object, attribute):
    """Returns the value of an attribute of an SQLAlchemy entity
    """
    output = sqla_object
    for x in attribute.split('.'):
        output = getattr(output, x)
    return output

class ColumnDT(ColumnTuple):
    """Class defining a DataTables Column with a ColumnTuple:

    :param column_name: name of the column as defined by the SQLAlchemy model
    :type column_name: str
    :param mData: name of the mData property as defined in the DataTables javascript options (default None)
    :type mData: str
    :param search_like: search criteria to like on without forgetting to escape the '%' character
    :type search_like: str
    :param filter: the method needed to be executed on the cell values of the column
    as an equivalent of a jinja2 filter (default None)
    :type filter: a callable object

    :returns: a ColumnDT object
    """
    def __new__(cls, column_name, mData=None, search_like=None, filter=str, search_date_range=None):
        """
        On creation, sets default None values for mData and string value for
        filter (cause: Object representation is not JSON serializable)
        """
        return super(ColumnDT, cls).__new__(cls, column_name, mData, search_like, filter, search_date_range)

class DataTables:
    """Class defining a DataTables object with:

    :param request: request containing the GET values, specified by the
    datatable for filtering, sorting and paging
    :type request: pyramid.request
    :param sqla_object: your SQLAlchemy table object
    :type sqla_object: sqlalchemy.ext.declarative.DeclarativeMeta
    :param query: the query wanted to be seen in the the table
    :type query: sqlalchemy.orm.query.Query
    :param columns: columns specification for the datatables
    :type columns: list

    :returns: a DataTables object
    """
    def __init__(self, request, sqla_object, query, columns):
        """Initializes the object with the attributes needed, and runs the query
        """
        self.request_values = request.params
        self.sqla_object = sqla_object
        self.query = query
        self.columns = columns
        self.results = None

        # total in the table after filtering
        self.cardinality_filtered = 0

        # total in the table unfiltered
        self.cardinality = 0

        self.run()

    def output_result(self):
        """Outputs the results in the format needed by DataTables
        """
        output = {}
        output['sEcho'] = str(int(self.request_values['sEcho']))
        output['iTotalRecords'] = str(self.cardinality)
        output['iTotalDisplayRecords'] = str(self.cardinality_filtered)
        output['aaData'] = self.results

        return output

    def run(self):
        """Launch filtering, sorting and paging processes to output results
        """
        # count before filtering
        self.cardinality = self.query.count()

        # the term entered in the datatable's search box
        self.filtering()

        # field chosen to sort on
        self.sorting()

        # pages have a 'start' and 'length' attributes
        self.paging()

        # fetch the result of the queries
        self.results = self.query.all()

        #return formatted results with correct filters applied
        formatted_results = []
        for i in range(len(self.results)):
            row = dict()
            for j in range(len(self.columns)):
                col = self.columns[j]
                tmp_row = get_attr(self.results[i], col.column_name)
                if col.filter:
                    tmp_row = col.filter(tmp_row.encode('utf8'))
                row[col.mData if col.mData else str(j)] = tmp_row
            formatted_results.append(row)

        self.results = formatted_results

    def filtering(self):
        """Construct the query, by adding filtering(LIKE) on all columns when the datatable's search box is used
        """
        search_value = self.request_values.get('sSearch')
        condition = None
        def search(idx, col):
            tmp_column_name = col.column_name.split('.')
            obj = getattr(self.sqla_object, tmp_column_name[0])
            if not hasattr(obj, "property"): # Ex: hybrid_property or property
                sqla_obj = self.sqla_object
                column_name = col.column_name
            elif isinstance(obj.property, RelationshipProperty): #Ex: ForeignKey
                # Ex: address.description
                sqla_obj = obj.mapper.class_
                column_name = "".join(tmp_column_name[1:])
                if not column_name:
                    # find first primary key
                    column_name = obj.property.table.primary_key.columns \
                        .values()[0].name
            else:
                sqla_obj = self.sqla_object
                column_name = col.column_name
            return sqla_obj, column_name

        if search_value:
            conditions = []
            for idx, col in enumerate(self.columns):
                if self.request_values.get('bSearchable_%s' % idx) in (
                        True, 'true'):
                    sqla_obj, column_name = search(idx, col)
                    conditions.append(cast(get_attr(sqla_obj, column_name), String).ilike('%%%s%%' % search_value))
            condition = or_(*conditions)
        conditions = []
        for idx, col in enumerate(self.columns):
            if self.request_values.get('bSearchable_%s' % idx) in (True, 'true'):
                search_value2 = self.request_values.get('sSearch_%s' % idx)
                if not search_value2:
                    continue
                sqla_obj, column_name = search(idx, col)
                if col.search_like:
                    conditions.append(get_attr(sqla_obj, column_name).like(col.search_like % search_value2))
                elif col.search_date_range:
                    _start, _end = search_value2.split(',')
                    conditions.append(and_(get_attr(sqla_obj, column_name) >= _start,
                                           get_attr(sqla_obj, column_name) <= _end))
                else:
                    conditions.append(get_attr(sqla_obj, column_name).__eq__(search_value2))

                if condition is not None:
                    condition = and_(condition, and_(*conditions))
                else:
                    condition= and_(*conditions)

        if condition is not None:
            self.query = self.query.filter(condition)
            # count after filtering
            self.cardinality_filtered = self.query.count()
        else:
            self.cardinality_filtered = self.cardinality

    def sorting(self):
        """Construct the query, by adding sorting(ORDER BY) on the columns needed to be applied on
        """
        sorting = []

        Order = namedtuple('order', ['name', 'dir'])

        if self.request_values.get('iSortCol_0') \
            and self.request_values.get('iSortingCols') > 0:

            for i in range(int(self.request_values['iSortingCols'])):
                sorting.append(Order( self.columns[int(self.request_values['iSortCol_'+str(i)])].column_name,
                        self.request_values['sSortDir_'+str(i)]))

        for sort in sorting:
            tmp_sort_name = sort.name.split('.')
            obj = getattr(self.sqla_object, tmp_sort_name[0])
            if not hasattr(obj, "property"): #hybrid_property or property
                sort_name = sort.name

                if hasattr(self.sqla_object, "__tablename__"):
                    tablename = self.sqla_object.__tablename__
                else:
                    tablename = self.sqla_object.__table__.name
            elif isinstance(obj.property, RelationshipProperty): # Ex: ForeignKey
                 # Ex: address.description => description => addresses.description
                sort_name = "".join(tmp_sort_name[1:])
                if not sort_name:
                    # Find first primary key
                    sort_name = obj.property.table.primary_key.columns \
                            .values()[0].name
                tablename = obj.property.table.name
            else: #-> ColumnProperty
                sort_name = sort.name

                if hasattr(self.sqla_object, "__tablename__"):
                    tablename = self.sqla_object.__tablename__
                else:
                    tablename = self.sqla_object.__table__.name

            sort_name = "%s.%s" % (tablename, sort_name)
            self.query = self.query.order_by(
                asc(sort_name) if sort.dir == 'asc' else desc(sort_name))

    def paging(self):
        """Construct the query, by slicing the results in order to limit rows showed on the page, and paginate the rest
        """
        pages = namedtuple('pages', ['start', 'length'])

        if (self.request_values['iDisplayStart'] != "" ) \
            and (self.request_values['iDisplayLength'] != -1 ):
            pages.start = int(self.request_values['iDisplayStart'])
            pages.length = int(self.request_values['iDisplayLength'])

        offset = pages.start + pages.length
        self.query = self.query.slice(pages.start, offset)
<|endoftext|>


<commit_before>__version__ = '1.00'
<commit_msg>import CrashReporter in __init__.py<commit_after>__version__ = '1.00'

from crashreporter import CrashReporter<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
Equipment system.
"""

from basinboa.universe.item import STYLE_ARMOR, STYLE_WEAPON

SLOT_HEAD = 'head'
SLOT_FACE = 'face'
SLOT_EAR = 'ear'
SLOT_NECK = 'neck'
SLOT_BODY = 'body'
SLOT_ARM = 'arm'
SLOT_LEFTHAND = 'lefthand'
SLOT_RIGHTHAND= 'righthand'
SLOT_LEG = 'leg'
SLOT_FOOT = 'foot'

class Equipment(object):
    """docstring for Equipment"""
    def __init__(self):
        super(Equipment, self).__init__()
        self.head = None
        self.face = None
        self.ear = None
        self.neck = None
        self.body = None
        self.arm = None
        self.lefthand = None
        self.righthand = None
        self.leg = None
        self.foot = None

    def has_equipment(self, item_name):
        """docstring for has_equipment"""
        eqs = self.dump().values()
        if item.name in [eq.name for eq in eqs]:
                return True
        return False

    def pop_equipment(self, item_name):
        """docstring for pop_equipment"""
        for slot,item in self.dump().items():
            if item:
                if item.name == item_name:
                    setattr(self, slot, None)
                    return item
        return None

    def pop_equipment_by_slot(self, slot):
        """docstring for pop_equipment_by_slot"""
        if self._has_slot(slot):
            item = getattr(self, slot)
            setattr(self, slot, None)
            return item
        return None

    def _has_slot(self, slot):
        """docstring for has_slot"""
        return True if hasattr(self, slot) else False

    def _equip(self, item, style):
        """docstring for equip"""
        if item.style == style:
            if self._has_slot(item.slot):
                setattr(self, item.slot, item)
                return True
            else:
                return False
        return False

    def _wield(self, item, auto=True, right=True, twohand=False):
        """docstring for _wield"""
        if twohand:
            self.lefthand = item
            self.righthand = item
            return
        else:
            if auto:
            #. wield weapen with hand that empty, else wield with righthand
                if not self.righthand:
                    self.righthand = item
                    return
                if not self.lefthand:
                    self.lefthand = item
                    return
                if self.lefthand and self.righthand:
                    self.righthand = item
                    return
            else:
                if right:
                    self.righthand = item
                else:
                    self.lefthand = item

    def _remove(self, item):
        """docstring for _remove"""
        setattr(self, item.slot, None)
        return True

    def slot_empty(self, slot):
        """docstring for slot_empty"""
        if hasattr(self, slot):
            return True if not getattr(self, slot) else False
        return False

    def wear(self, item):
        """docstring for wear"""
        return self._equip(item, STYLE_ARMOR)

    def wield(self, item, auto=True, right=True):
        """docstring for wield"""
        if item.style == STYLE_WEAPON:
            self._wield(item, auto=auto, right=right)
            return True
        return False

    def hold(self, item):
        """docstring for hold"""
        if item.style == STYLE_WEAPON:
            self._wield(item, twohand=True)
            return True
        return False

    def remove(self, item):
        """docstring for remove"""
        return self._remove()

    def _get_attr(self, data, attr):
        """docstring for get_attr"""
        if hasattr(self, attr):
            data[attr] = getattr(self, attr)
        return data

    def _set_attr(self, data, attr):
        """docstring for set_attr"""
        if data.has_key(attr):
            setattr(self, attr, data[attr])

    def dump(self):
        """docstring for dump"""
        attrs = [
            'head', 'face', 'ear', 'neck',
            'body', 'arm', 'lefthand', 'righthand',
            'leg', 'foot',
        ]
        data = {}
        for attr in attrs:
            data = self._get_attr(data, attr)
        return data

    def load(self, data):
        """docstring for load"""
        attrs = [
            'head', 'face', 'ear', 'neck',
            'body', 'arm', 'lefthand', 'righthand',
            'leg', 'foot',
        ]
        for attr in attrs:
            self._set_attr(data, attr)

<commit_msg>fix typo.<commit_after>#!/usr/bin/env python
"""
Equipment system.
"""

from basinboa.universe.item import STYLE_ARMOR, STYLE_WEAPON

SLOT_HEAD = 'head'
SLOT_FACE = 'face'
SLOT_EAR = 'ear'
SLOT_NECK = 'neck'
SLOT_BODY = 'body'
SLOT_ARM = 'arm'
SLOT_LEFTHAND = 'lefthand'
SLOT_RIGHTHAND= 'righthand'
SLOT_LEG = 'leg'
SLOT_FOOT = 'foot'

class Equipment(object):
    """docstring for Equipment"""
    def __init__(self):
        super(Equipment, self).__init__()
        self.head = None
        self.face = None
        self.ear = None
        self.neck = None
        self.body = None
        self.arm = None
        self.lefthand = None
        self.righthand = None
        self.leg = None
        self.foot = None

    def has_equipment(self, item_name):
        """docstring for has_equipment"""
        eqs = self.dump().values()
        if item_name in [eq.name for eq in eqs if eq]:
                return True
        return False

    def pop_equipment(self, item_name):
        """docstring for pop_equipment"""
        for slot,item in self.dump().items():
            if item:
                if item.name == item_name:
                    setattr(self, slot, None)
                    return item
        return None

    def pop_equipment_by_slot(self, slot):
        """docstring for pop_equipment_by_slot"""
        if self._has_slot(slot):
            item = getattr(self, slot)
            setattr(self, slot, None)
            return item
        return None

    def _has_slot(self, slot):
        """docstring for has_slot"""
        return True if hasattr(self, slot) else False

    def _equip(self, item, style):
        """docstring for equip"""
        if item.style == style:
            if self._has_slot(item.slot):
                setattr(self, item.slot, item)
                return True
            else:
                return False
        return False

    def _wield(self, item, auto=True, right=True, twohand=False):
        """docstring for _wield"""
        if twohand:
            self.lefthand = item
            self.righthand = item
            return
        else:
            if auto:
            #. wield weapen with hand that empty, else wield with righthand
                if not self.righthand:
                    self.righthand = item
                    return
                if not self.lefthand:
                    self.lefthand = item
                    return
                if self.lefthand and self.righthand:
                    self.righthand = item
                    return
            else:
                if right:
                    self.righthand = item
                else:
                    self.lefthand = item

    def _remove(self, item):
        """docstring for _remove"""
        setattr(self, item.slot, None)
        return True

    def slot_empty(self, slot):
        """docstring for slot_empty"""
        if hasattr(self, slot):
            return True if not getattr(self, slot) else False
        return False

    def wear(self, item):
        """docstring for wear"""
        return self._equip(item, STYLE_ARMOR)

    def wield(self, item, auto=True, right=True):
        """docstring for wield"""
        if item.style == STYLE_WEAPON:
            self._wield(item, auto=auto, right=right)
            return True
        return False

    def hold(self, item):
        """docstring for hold"""
        if item.style == STYLE_WEAPON:
            self._wield(item, twohand=True)
            return True
        return False

    def remove(self, item):
        """docstring for remove"""
        return self._remove()

    def _get_attr(self, data, attr):
        """docstring for get_attr"""
        if hasattr(self, attr):
            data[attr] = getattr(self, attr)
        return data

    def _set_attr(self, data, attr):
        """docstring for set_attr"""
        if data.has_key(attr):
            setattr(self, attr, data[attr])

    def dump(self):
        """docstring for dump"""
        attrs = [
            'head', 'face', 'ear', 'neck',
            'body', 'arm', 'lefthand', 'righthand',
            'leg', 'foot',
        ]
        data = {}
        for attr in attrs:
            data = self._get_attr(data, attr)
        return data

    def load(self, data):
        """docstring for load"""
        attrs = [
            'head', 'face', 'ear', 'neck',
            'body', 'arm', 'lefthand', 'righthand',
            'leg', 'foot',
        ]
        for attr in attrs:
            self._set_attr(data, attr)

<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This code demonstrates how to use dedupe with a comma separated values
(CSV) file. All operations are performed in memory, so will run very
quickly on datasets up to ~10,000 rows.

We start with a CSV file containing our messy data. In this example,
it is listings of early childhood education centers in Chicago
compiled from several different sources.

The output will be a CSV with our clustered results.

For larger datasets, see our [mysql_example](http://open-city.github.com/dedupe/doc/mysql_example.html)
"""

import os
import csv
import re
import collections
import logging
import optparse

import AsciiDammit

import dedupe

# ## Logging

# Dedupe uses Python logging to show or suppress verbose output. Added for convenience.
# To enable verbose logging, run `python examples/csv_example/csv_example.py -v`

optp = optparse.OptionParser()
optp.add_option('-v', '--verbose', dest='verbose', action='count',
                help='Increase verbosity (specify multiple times for more)'
                )
(opts, args) = optp.parse_args()
log_level = logging.WARNING
if opts.verbose == 1:
    log_level = logging.INFO
elif opts.verbose >= 2:
    log_level = logging.DEBUG
logging.basicConfig(level=log_level)

# ## Setup

# Switch to our working directory and set up our input and out put paths,
# as well as our settings and training file locations
os.chdir('./examples/csv_example/')
input_files = ['CPS_Early_Childhood_Portal_scrape.csv','chapin_dfss_providers_2011_070212.csv']
output_files = ['CPS_Early_Childhoos_Output.csv','chapin_Output.csv']
settings_file = 'csv_example_data_matching_learned_settings'
training_file = 'csv_example_data_matching_training.json'

# Dedupe can take custom field comparison functions, here's one
# we'll use for zipcodes
def sameOrNotComparator(field_1, field_2) :
    if field_1 == field_2 :
        return 1
    else:
        return 0

def preProcess(column):
    """
    Do a little bit of data cleaning with the help of [AsciiDammit](https://github.com/tnajdek/ASCII--Dammit)
    and Regex. Things like casing, extra spaces, quotes and new lines can be ignored.
    """

    column = AsciiDammit.asciiDammit(column)
    column = re.sub('  +', ' ', column)
    column = re.sub('\n', ' ', column)
    column = column.strip().strip('"').strip("'").lower().strip()
    return column

def readData(filenames):
    """
    Read in our data from a CSV file and create a dictionary of records,
    where the key is a unique record ID and each value is a
    [frozendict](http://code.activestate.com/recipes/414283-frozen-dictionaries/)
    (hashable dictionary) of the row fields.
    """

    data_d = {}
    row_id = 0
    for filename in filenames:
        with open(filename) as f:
            reader = csv.DictReader(f)
            for row in reader:
                clean_row = [(k, preProcess(v)) for (k, v) in row.items()]
                clean_row.append(('dataSet',filename))
                data_d[row_id] = dedupe.core.frozendict(clean_row)
                row_id += 1

    return data_d

print 'importing data ...'
data_d = readData(input_files)

# ## Training

if os.path.exists(settings_file):
    print 'reading from', settings_file
    deduper = dedupe.Dedupe(settings_file)

else:
    # To train dedupe, we feed it a random sample of records.
    data_sample = dedupe.dataSample(data_d, 150000)

    # Define the fields dedupe will pay attention to
    #
    # Notice how we are telling dedupe to use a custom field comparator
    # for the 'Zip' field.
    fields = {
        'Site name': {'type': 'String'},
        'Address': {'type': 'String'},
        'Zip': {'type': 'String', 'Has Missing':True},
        'Phone': {'type': 'String', 'Has Missing':True},
        }

    # Create a new deduper object and pass our data model to it.
    deduper = dedupe.Dedupe(fields)

    # If we have training data saved from a previous run of dedupe,
    # look for it an load it in.
    # __Note:__ if you want to train from scratch, delete the training_file
    if os.path.exists(training_file):
        print 'reading labeled examples from ', training_file
        deduper.train(data_sample, training_file)

    # ## Active learning

    # Starts the training loop. Dedupe will find the next pair of records
    # it is least certain about and ask you to label them as duplicates
    # or not.

    # use 'y', 'n' and 'u' keys to flag duplicates
    # press 'f' when you are finished
    print 'starting active labeling...'
    deduper.train(data_sample, dedupe.training.consoleLabel)

    # When finished, save our training away to disk
    deduper.writeTraining(training_file)

# ## Blocking

print 'blocking...'
# Initialize our blocker. We'll learn our blocking rules if we haven't
# loaded them from a saved settings file.
blocker = deduper.blockingFunction()

# Save our weights and predicates to disk.  If the settings file
# exists, we will skip all the training and learning next time we run
# this file.
deduper.writeSettings(settings_file)

# Load all the original data in to memory and place
# them in to blocks. Each record can be blocked in many ways, so for
# larger data, memory will be a limiting factor.

blocked_data = dedupe.blockData(data_d, blocker)

# ## Clustering

# Find the threshold that will maximize a weighted average of our precision and recall.
# When we set the recall weight to 2, we are saying we care twice as much
# about recall as we do precision.
#
# If we had more data, we would not pass in all the blocked data into
# this function but a representative sample.

threshold = deduper.goodThreshold(blocked_data, recall_weight=2)

# `duplicateClusters` will return sets of record IDs that dedupe
# believes are all referring to the same entity.

print 'clustering...'
clustered_dupes = deduper.duplicateClusters(blocked_data, threshold)

print '# duplicate sets', len(clustered_dupes)

# ## Writing Results

# Write our original data back out to a CSV with a new column called
# 'Cluster ID' which indicates which records refer to each other.

cluster_membership = collections.defaultdict(lambda : 'x')
for (cluster_id, cluster) in enumerate(clustered_dupes):
    for record_id in cluster:
        cluster_membership[record_id] = cluster_id

writer_coll = {}
for filename in output_files:
        f = open(filename,'w')
        writer_coll[filename] = csv.writer(f)

row_id=0
for i in range(len(input_files)):
    with open(input_files[i]) as f:
        reader = csv.reader(f)

        heading_row = reader.next()
        heading_row.insert(0, 'Cluster ID')
        writer_coll[output_files[i]].writerow(heading_row)

        for row in reader:
            cluster_id = cluster_membership[row_id]
            row.insert(0, cluster_id)
            writer_coll[output_files[i]].writerow(row)
            row_id += 1<commit_msg>Pull the Changes csv_example.py to csv_data_matching.py<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This code demonstrates how to use dedupe with a comma separated values
(CSV) file. All operations are performed in memory, so will run very
quickly on datasets up to ~10,000 rows.

We start with a CSV file containing our messy data. In this example,
it is listings of early childhood education centers in Chicago
compiled from several different sources.

The output will be a CSV with our clustered results.

For larger datasets, see our [mysql_example](http://open-city.github.com/dedupe/doc/mysql_example.html)
"""

import os
import csv
import re
import collections
import logging
import optparse

import AsciiDammit

import dedupe

# ## Logging

# Dedupe uses Python logging to show or suppress verbose output. Added for convenience.
# To enable verbose logging, run `python examples/csv_example/csv_example.py -v`

optp = optparse.OptionParser()
optp.add_option('-v', '--verbose', dest='verbose', action='count',
                help='Increase verbosity (specify multiple times for more)'
                )
(opts, args) = optp.parse_args()
log_level = logging.WARNING
if opts.verbose == 1:
    log_level = logging.INFO
elif opts.verbose >= 2:
    log_level = logging.DEBUG
logging.basicConfig(level=log_level)

# ## Setup

# Switch to our working directory and set up our input and out put paths,
# as well as our settings and training file locations
os.chdir('./examples/csv_example/')
input_files = ['CPS_Early_Childhood_Portal_scrape.csv','chapin_dfss_providers_2011_070212.csv']
output_files = ['CPS_Early_Childhoos_Output.csv','chapin_Output.csv']
settings_file = 'csv_example_data_matching_learned_settings'
training_file = 'csv_example_data_matching_training.json'

# Dedupe can take custom field comparison functions, here's one
# we'll use for zipcodes
def sameOrNotComparator(field_1, field_2) :
    if field_1 == field_2 :
        return 1
    else:
        return 0

def preProcess(column):
    """
    Do a little bit of data cleaning with the help of [AsciiDammit](https://github.com/tnajdek/ASCII--Dammit)
    and Regex. Things like casing, extra spaces, quotes and new lines can be ignored.
    """

    column = AsciiDammit.asciiDammit(column)
    column = re.sub('  +', ' ', column)
    column = re.sub('\n', ' ', column)
    column = column.strip().strip('"').strip("'").lower().strip()
    return column

def readData(filenames):
    """
    Read in our data from a CSV file and create a dictionary of records,
    where the key is a unique record ID and each value is a
    [frozendict](http://code.activestate.com/recipes/414283-frozen-dictionaries/)
    (hashable dictionary) of the row fields.
    """

    data_d = {}
    for filename in filenames:
        with open(filename) as f:
            reader = csv.DictReader(f)
            for row in reader:
                clean_row = [(k, preProcess(v)) for (k, v) in row.items()]
                clean_row.append(('dataSet',filename))
                row_id = int(row['Id'])
                data_d[row_id] = dedupe.core.frozendict(clean_row)

    return data_d

print 'importing data ...'
data_d = readData(input_files)

# ## Training

if os.path.exists(settings_file):
    print 'reading from', settings_file
    deduper = dedupe.Dedupe(settings_file)

else:
    # To train dedupe, we feed it a random sample of records.
    data_sample = dedupe.dataSample(data_d, 150000)

    # Define the fields dedupe will pay attention to
    #
    # Notice how we are telling dedupe to use a custom field comparator
    # for the 'Zip' field.
    fields = {
        'Site name': {'type': 'String'},
        'Address': {'type': 'String'},
        'Zip': {'type': 'String', 'Has Missing':True},
        'Phone': {'type': 'String', 'Has Missing':True},
        }

    # Create a new deduper object and pass our data model to it.
    deduper = dedupe.Dedupe(fields)

    # If we have training data saved from a previous run of dedupe,
    # look for it an load it in.
    # __Note:__ if you want to train from scratch, delete the training_file
    if os.path.exists(training_file):
        print 'reading labeled examples from ', training_file
        deduper.train(data_sample, training_file)

    # ## Active learning

    # Starts the training loop. Dedupe will find the next pair of records
    # it is least certain about and ask you to label them as duplicates
    # or not.

    # use 'y', 'n' and 'u' keys to flag duplicates
    # press 'f' when you are finished
    print 'starting active labeling...'
    deduper.train(data_sample, dedupe.training.consoleLabel)

    # When finished, save our training away to disk
    deduper.writeTraining(training_file)

# ## Blocking

print 'blocking...'
# Initialize our blocker. We'll learn our blocking rules if we haven't
# loaded them from a saved settings file.
blocker = deduper.blockingFunction()

# Save our weights and predicates to disk.  If the settings file
# exists, we will skip all the training and learning next time we run
# this file.
deduper.writeSettings(settings_file)

# Load all the original data in to memory and place
# them in to blocks. Each record can be blocked in many ways, so for
# larger data, memory will be a limiting factor.

blocked_data = dedupe.blockData(data_d, blocker)

# ## Clustering

# Find the threshold that will maximize a weighted average of our precision and recall.
# When we set the recall weight to 2, we are saying we care twice as much
# about recall as we do precision.
#
# If we had more data, we would not pass in all the blocked data into
# this function but a representative sample.

threshold = deduper.goodThreshold(blocked_data, recall_weight=2)

# `duplicateClusters` will return sets of record IDs that dedupe
# believes are all referring to the same entity.

print 'clustering...'
clustered_dupes = deduper.duplicateClusters(blocked_data, threshold)

print '# duplicate sets', len(clustered_dupes)

# ## Writing Results

# Write our original data back out to a CSV with a new column called
# 'Cluster ID' which indicates which records refer to each other.

cluster_membership = collections.defaultdict(lambda : 'x')
for (cluster_id, cluster) in enumerate(clustered_dupes):
    for record_id in cluster:
        cluster_membership[record_id] = cluster_id

writer_coll = {}
for filename in output_files:
        f = open(filename,'w')
        writer_coll[filename] = csv.writer(f)

for i in range(len(input_files)):
    with open(input_files[i]) as f:
        reader = csv.reader(f)

        heading_row = reader.next()
        heading_row.insert(0, 'Cluster ID')
        writer_coll[output_files[i]].writerow(heading_row)

        for row in reader:
            row_id = int(row[0])
            cluster_id = cluster_membership[row_id]
            row.insert(0, cluster_id)
            writer_coll[output_files[i]].writerow(row)
<|endoftext|>


<commit_before>import alphasign
import sys
import time
import urllib2

def update_sign():

        sign = alphasign.Serial(device='/dev/ttyUSB0')
        sign.connect()
        sign.clear_memory()

        # create an empty alphasign.String
        alpha_str = alphasign.String()

        # create a single alphasign.Text object with a placeholder for our alphasign.String
        alpha_txt = alphasign.Text(alpha_str.call(),mode=alphasign.modes.COMPRESSED_ROTATE)

        # allocate memory for these objects on the sign
        sign.allocate((alpha_str,alpha_txt))

        # tell sign to only display the text part
        sign.set_run_sequence((alpha_txt,))

        # write objects
        for obj in (alpha_str,alpha_txt):
            sign.write(obj)

        # This gives time for the serial write to complete before we issue the next write.
        time.sleep(5)

        last_payload = ''

        while True:

            try:
                # fetch new-line separated plain text from Interweb
                payload = urllib2.urlopen("https://server.appletonmakerspace.org/beta-brite-message-file.txt").read()
            except Exception:
                payload = 'HALP! Internet down!?'

            # alert bystanders with beep when we update
            if payload != last_payload:
                sign.beep(frequency=20, duration=1)
                last_payload = payload

            # loop over each line of plain text, displaying for 10 seconds
            for line in payload.splitlines():
                alpha_str.data = line
                sign.write(alpha_str)
                time.sleep(10)

            # when the last line is read, the while loop repeats and fetches again

if __name__ == "__main__":
    update_sign()

<commit_msg>Switch to using the new wiki for message input<commit_after>import alphasign
import sys
import time
import urllib2

def update_sign():

        sign = alphasign.Serial(device='/dev/ttyUSB0')
        sign.connect()
        sign.clear_memory()

        # create an empty alphasign.String
        alpha_str = alphasign.String()

        # create a single alphasign.Text object with a placeholder for our alphasign.String
        alpha_txt = alphasign.Text(alpha_str.call(),mode=alphasign.modes.COMPRESSED_ROTATE)

        # allocate memory for these objects on the sign
        sign.allocate((alpha_str,alpha_txt))

        # tell sign to only display the text part
        sign.set_run_sequence((alpha_txt,))

        # write objects
        for obj in (alpha_str,alpha_txt):
            sign.write(obj)

        # This gives time for the serial write to complete before we issue the next write.
        time.sleep(5)

        last_payload = ''

        while True:

            try:
                # fetch new-line separated plain text from Interweb
                payload = urllib2.urlopen("https://server.appletonmakerspace.org/wiki/doku.php?id=sign_text&do=export_raw").read()
            except Exception:
                payload = 'HALP! Internet down!?'

            # alert bystanders with beep when we update
            if payload != last_payload:
                sign.beep(frequency=20, duration=1)
                last_payload = payload

            # loop over each line of plain text, displaying for 10 seconds
            for line in payload.splitlines():
                alpha_str.data = line
                sign.write(alpha_str)
                time.sleep(10)

            # when the last line is read, the while loop repeats and fetches again

if __name__ == "__main__":
    update_sign()

<|endoftext|>


<commit_before>from django.template import Context, Template
from django.template.loader import render_to_string
from django.forms.util import flatatt

from layout import LayoutObject, Field, Div
from utils import render_field

class AppendedText(Field):
    template = "bootstrap/layout/appended_text.html"

    def __init__(self, field, text, *args, **kwargs):
        self.field = field
        self.text = text
        if 'active' in kwargs:
            self.active = kwargs.pop('active')

        super(AppendedText, self).__init__(field, *args, **kwargs)

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'crispy_appended_text': self.text, 'active': getattr(self, "active", False)})
        return render_field(self.field, form, form_style, context, template=self.template, attrs=self.attrs, template_pack=template_pack)

class PrependedText(AppendedText):
    template = "bootstrap/layout/prepended_text.html"

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'crispy_prepended_text': self.text, 'active': getattr(self, "active", False)})
        return render_field(self.field, form, form_style, context, template=self.template, attrs=self.attrs, template_pack=template_pack)

class AppendedPrependedText(Field):
    template = "bootstrap/layout/appended_prepended_text.html"

    def __init__(self, field, prepended_text=None, appended_text=None, *args, **kwargs):
        self.field = field
        self.appended_text = appended_text
        self.prepended_text = prepended_text
        if 'active' in kwargs:
            self.active = kwargs.pop('active')

        super(AppendedPrependedText, self).__init__(field, *args, **kwargs)

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'crispy_appended_text': self.appended_text,
                        'crispy_prepended_text': self.prepended_text,
                        'active': getattr(self, "active", False)})
        return render_field(self.field, form, form_style, context, template=self.template, attrs=self.attrs, template_pack=template_pack)

class FormActions(LayoutObject):
    """
    Bootstrap layout object. It wraps fields in a

    Example::

        FormActions(
            HTML(Information Saved),
            Submit('Save', 'Save', css_class='btn-primary')
        )
    """
    template = "bootstrap/layout/formactions.html"

    def __init__(self, *fields, **kwargs):
        self.fields = list(fields)
        self.template = kwargs.pop('template', self.template)
        self.attrs = kwargs
        if 'css_class' in self.attrs:
            self.attrs['class'] = self.attrs.pop('css_class')

    def render(self, form, form_style, context, template_pack='bootstrap'):
        html = u''
        for field in self.fields:
            html += render_field(field, form, form_style, context, template_pack=template_pack)

        return render_to_string(self.template, Context({'formactions': self, 'fields_output': html}))

    def flat_attrs(self):
        return flatatt(self.attrs)

class InlineCheckboxes(Field):
    """
    Layout object for rendering checkboxes inline::

        InlineCheckboxes('field_name')
    """
    template = "bootstrap/layout/checkboxselectmultiple_inline.html"

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'inline_class': 'inline'})
        html = super(InlineCheckboxes, self).render(form, form_style, context)
        # We delete the inserted key to avoid side effects
        del context.dicts[-2]['inline_class']
        return html

class FieldWithButtons(Div):
    template = 'bootstrap/layout/field_with_buttons.html'

    def render(self, form, form_style, context):
        # We first render the buttons
        buttons = ''
        for field in self.fields[1:]:
            buttons += render_field(field, form, form_style, context,
                'bootstrap/layout/field.html', layout_object=self)

        context.update({'div': self, 'buttons': buttons})

        if isinstance(self.fields[0], Field):
            # FieldWithButtons(Field('field_name'), StrictButton("go"))
            # We render the field passing its name and attributes
            return render_field(self.fields[0][0], form, form_style, context,
                'bootstrap/layout/field_with_buttons.html', attrs=self.fields[0].attrs)
        else:
            return render_field(self.fields[0], form, form_style, context,
                'bootstrap/layout/field_with_buttons.html')

class StrictButton(object):
    """
    Layout oject for rendering an HTML button::

        Button("button content", css_class="extra")
    """
    template = 'bootstrap/layout/button.html'
    field_classes = 'btn'

    def __init__(self, content, **kwargs):
        self.content = content
        self.template = kwargs.pop('template', self.template)

        kwargs.setdefault('type', 'button')

        # We turn css_id and css_class into id and class
        if kwargs.has_key('css_id'):
            kwargs['id'] = kwargs.pop('css_id')
        kwargs['class'] = self.field_classes
        if kwargs.has_key('css_class'):
            kwargs['class'] += " %s" % kwargs.pop('css_class')

        self.flat_attrs = flatatt(kwargs)

    def render(self, form, form_style, context):
        self.content = Template(unicode(self.content)).render(context)
        return render_to_string(self.template, Context({'button': self}))
<commit_msg>FieldWithButtons should use template variable<commit_after>from django.template import Context, Template
from django.template.loader import render_to_string
from django.forms.util import flatatt

from layout import LayoutObject, Field, Div
from utils import render_field

class AppendedText(Field):
    template = "bootstrap/layout/appended_text.html"

    def __init__(self, field, text, *args, **kwargs):
        self.field = field
        self.text = text
        if 'active' in kwargs:
            self.active = kwargs.pop('active')

        super(AppendedText, self).__init__(field, *args, **kwargs)

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'crispy_appended_text': self.text, 'active': getattr(self, "active", False)})
        return render_field(self.field, form, form_style, context, template=self.template, attrs=self.attrs, template_pack=template_pack)

class PrependedText(AppendedText):
    template = "bootstrap/layout/prepended_text.html"

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'crispy_prepended_text': self.text, 'active': getattr(self, "active", False)})
        return render_field(self.field, form, form_style, context, template=self.template, attrs=self.attrs, template_pack=template_pack)

class AppendedPrependedText(Field):
    template = "bootstrap/layout/appended_prepended_text.html"

    def __init__(self, field, prepended_text=None, appended_text=None, *args, **kwargs):
        self.field = field
        self.appended_text = appended_text
        self.prepended_text = prepended_text
        if 'active' in kwargs:
            self.active = kwargs.pop('active')

        super(AppendedPrependedText, self).__init__(field, *args, **kwargs)

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'crispy_appended_text': self.appended_text,
                        'crispy_prepended_text': self.prepended_text,
                        'active': getattr(self, "active", False)})
        return render_field(self.field, form, form_style, context, template=self.template, attrs=self.attrs, template_pack=template_pack)

class FormActions(LayoutObject):
    """
    Bootstrap layout object. It wraps fields in a

    Example::

        FormActions(
            HTML(Information Saved),
            Submit('Save', 'Save', css_class='btn-primary')
        )
    """
    template = "bootstrap/layout/formactions.html"

    def __init__(self, *fields, **kwargs):
        self.fields = list(fields)
        self.template = kwargs.pop('template', self.template)
        self.attrs = kwargs
        if 'css_class' in self.attrs:
            self.attrs['class'] = self.attrs.pop('css_class')

    def render(self, form, form_style, context, template_pack='bootstrap'):
        html = u''
        for field in self.fields:
            html += render_field(field, form, form_style, context, template_pack=template_pack)

        return render_to_string(self.template, Context({'formactions': self, 'fields_output': html}))

    def flat_attrs(self):
        return flatatt(self.attrs)

class InlineCheckboxes(Field):
    """
    Layout object for rendering checkboxes inline::

        InlineCheckboxes('field_name')
    """
    template = "bootstrap/layout/checkboxselectmultiple_inline.html"

    def render(self, form, form_style, context, template_pack='bootstrap'):
        context.update({'inline_class': 'inline'})
        html = super(InlineCheckboxes, self).render(form, form_style, context)
        # We delete the inserted key to avoid side effects
        del context.dicts[-2]['inline_class']
        return html

class FieldWithButtons(Div):
    template = 'bootstrap/layout/field_with_buttons.html'

    def render(self, form, form_style, context):
        # We first render the buttons
        buttons = ''
        for field in self.fields[1:]:
            buttons += render_field(field, form, form_style, context,
                'bootstrap/layout/field.html', layout_object=self)

        context.update({'div': self, 'buttons': buttons})

        if isinstance(self.fields[0], Field):
            # FieldWithButtons(Field('field_name'), StrictButton("go"))
            # We render the field passing its name and attributes
            return render_field(self.fields[0][0], form, form_style, context,
                self.template, attrs=self.fields[0].attrs)
        else:
            return render_field(self.fields[0], form, form_style, context, self.template)

class StrictButton(object):
    """
    Layout oject for rendering an HTML button::

        Button("button content", css_class="extra")
    """
    template = 'bootstrap/layout/button.html'
    field_classes = 'btn'

    def __init__(self, content, **kwargs):
        self.content = content
        self.template = kwargs.pop('template', self.template)

        kwargs.setdefault('type', 'button')

        # We turn css_id and css_class into id and class
        if kwargs.has_key('css_id'):
            kwargs['id'] = kwargs.pop('css_id')
        kwargs['class'] = self.field_classes
        if kwargs.has_key('css_class'):
            kwargs['class'] += " %s" % kwargs.pop('css_class')

        self.flat_attrs = flatatt(kwargs)

    def render(self, form, form_style, context):
        self.content = Template(unicode(self.content)).render(context)
        return render_to_string(self.template, Context({'button': self}))
<|endoftext|>


<commit_before>"""
====================================================
Extracting the time series of activations in a label
====================================================

"""
# Author: Alexandre Gramfort <gramfort@nmr.mgh.harvard.edu>
#
# License: BSD (3-clause)

print __doc__

import mne
from mne.datasets import sample

data_path = sample.data_path('..')
stc_fname = data_path + '/MEG/sample/sample_audvis-meg-lh.stc'
label = 'Aud-lh'
label_fname = data_path + '/MEG/sample/labels/%s.label' % label

values, times, vertices = mne.label_time_courses(label_fname, stc_fname)

print "Number of vertices : %d" % len(vertices)

# View source activations
import pylab as pl
pl.plot(times, values.T)
pl.xlabel('time (ms)')
pl.ylabel('Source amplitude')
pl.title('Activations in Label : %s' % label)
pl.show()
<commit_msg>Fix time units (s->ms)<commit_after>"""
====================================================
Extracting the time series of activations in a label
====================================================

"""
# Author: Alexandre Gramfort <gramfort@nmr.mgh.harvard.edu>
#
# License: BSD (3-clause)

print __doc__

import mne
from mne.datasets import sample

data_path = sample.data_path('..')
stc_fname = data_path + '/MEG/sample/sample_audvis-meg-lh.stc'
label = 'Aud-lh'
label_fname = data_path + '/MEG/sample/labels/%s.label' % label

values, times, vertices = mne.label_time_courses(label_fname, stc_fname)

print "Number of vertices : %d" % len(vertices)

times=times*1000

# View source activations
import pylab as pl
pl.plot(times, values.T)
pl.xlabel('time (ms)')
pl.ylabel('Source amplitude')
pl.title('Activations in Label : %s' % label)
pl.show()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Author: Chris L8 https://github.com/chrisl8
# URL: https://github.com/chrisl8/ArloBot

import rospy
import tf
import sys
import time

from std_msgs.msg import String
from std_msgs.msg import Bool
from arlobot_msgs.msg import usbRelayStatus
from arlobot_msgs.srv import *

#For USB relay board
from pylibftdi import BitBangDevice
from pylibftdi import Driver # Required to get serial number of unknown USB Relay device.

# From:
# ----------------------------------------------------------------------------
#
#   DRCONTROL.PY
#
#   Copyright (C) 2012 Sebastian Sjoholm, sebastian.sjoholm@gmail.com
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#   Version history can be found at
#   http://code.google.com/p/drcontrol/wiki/VersionHistory
#
#   $Rev$
#   $Date$
#
# ----------------------------------------------------------------------------
# For SainSmart 8 port USB model http://www.sainsmart.com/sainsmart-4-channel-12-v-usb-relay-board-module-controller-for-automation-robotics-1.html
class relay_data(dict):

    address = {
            "1":"1",
            "2":"2",
            "3":"4",
            "4":"8",
            "5":"10",
            "6":"20",
            "7":"40",
            "8":"80",
            "all":"FF"
            }

    def __getitem__(self, key): return self[key]
    def keys(self): return self.keys()

# ----------------------------------------------------------------------------
# testBit() returns a nonzero result, 2**offset, if the bit at 'offset' is one.
# http://wiki.python.org/moin/BitManipulation
# ----------------------------------------------------------------------------

def testBit(int_type, offset):
    mask = 1 << offset
    return(int_type & mask)

# ----------------------------------------------------------------------------
# LIST_DEVICES()
#
# Routine modified from the original pylibftdi example by Ben Bass
# ----------------------------------------------------------------------------

def list_devices():
    print "Vendor\t\tProduct\t\t\tSerial"
    dev_list = []
    for device in Driver().list_devices():
        device = map(lambda x: x.decode('latin1'), device)
        vendor, product, serial = device
        print "%s\t\t%s\t\t%s" % (vendor, product, serial)

def return_device_serial_number():
    #print "Vendor\t\tProduct\t\t\tSerial"
    dev_list = []
    for device in Driver().list_devices():
        device = map(lambda x: x.decode('latin1'), device)
        vendor, product, serial = device
        #print "%s\t\t%s\t\t%s" % (vendor, product, serial)
    return serial

# For SainSmart 8 port USB model http://www.sainsmart.com/sainsmart-4-channel-12-v-usb-relay-board-module-controller-for-automation-robotics-1.html
def get_relay_state( data, relay ):
    if relay == "1":
        return testBit(data, 0)
    if relay == "2":
        return testBit(data, 1)
    if relay == "3":
        return testBit(data, 2)
    if relay == "4":
        return testBit(data, 3)
    if relay == "5":
        return testBit(data, 4)
    if relay == "6":
        return testBit(data, 5)
    if relay == "7":
        return testBit(data, 6)
    if relay == "8":
        return testBit(data, 7)

class UsbRelay(object):
    '''
    Helper class for communicating with a Propeller board over serial port
    '''

    def __init__(self):
        rospy.init_node('arlobot_usbrelay')
        # http://wiki.ros.org/rospy_tutorials/Tutorials/WritingPublisherSubscriber
        self.r = rospy.Rate(0.25) # 1hz refresh rate
        #self.r = rospy.Rate(1) # 1hz refresh rate

        # Prevent overlapping calls to the serial port
        self._Busy = False

        # Wait for the arlobot_bringup launch file to initiate the usbRelayInstalled parameter before starting:
        while not rospy.has_param('/arlobot/usbRelayInstalled') and not rospy.is_shutdown():
            rospy.loginfo("arlobot_bringup not started yet, waiting . . .")
            rospy.sleep(1)

        self.relayExists = rospy.get_param("/arlobot/usbRelayInstalled", False)
        if self.relayExists:
            #list_devices()
            #NOTE: This will return the LAST device, so if you have multiple USB Relay boards this will have to be modified
            self.relaySerialNumber = return_device_serial_number()

        else:
            rospy.loginfo("No USB Relay board installed.")

        # Create a service that can be called to toggle any relay by name:
        # http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv
        # http://wiki.ros.org/ROS/Tutorials/WritingServiceClient%28python%29
        relayToggle = rospy.Service('~toggle_relay', ToggleRelay, self._ToggleRelayByName)
        relayFind = rospy.Service('~find_relay', FindRelay, self._FindRelayByName)

        # Publishers
        self._usbRelayStatusPublisher = rospy.Publisher('~usbRelayStatus', usbRelayStatus, queue_size=1) # for publishing status of USB Relays

    def _FindRelayByName(self, req):
        # This function will return the relay number for a given name based on the usbrelay.yaml loaded parameters
        # In theory any node can do this, but it helps to make this service available, since the topic we publish requires
        # You to know the number of the relay to figure out which array entry is the one you want.
        boardExists = False
        foundRelay = False
        relayNumber = 0
        if self.relayExists and not rospy.is_shutdown():
            if self.relayExists: # Do not do this if no relay exists.
                # Toggle Relay
                boardExists = True
                for i in range(1,9): # Walk the relays to find the one with the right name.
                    relayEnabled = rospy.get_param("~relay" + str(i) + "enabled", False)
                    if relayEnabled: # Do not touch (poll or anything) Relays that are not listed as enabled.
                        relayLabel = rospy.get_param("~relay" + str(i) + "label", "No Label")
                        if relayLabel == req.relay:
                            foundRelay = True
                            relayNumber = i
        return(boardExists, foundRelay, relayNumber)

    def _ToggleRelayByName(self, req):
        boardExists = False
        foundRelay = False
        toggleSuccess = False
        if self.relayExists: # Do not do this if no relay exists.
            # Toggle Relay
            boardExists = True
            for i in range(1,9): # Walk the relays to find the one with the right name.
                relayEnabled = rospy.get_param("~relay" + str(i) + "enabled", False)
                if relayEnabled: # Do not touch (poll or anything) Relays that are not listed as enabled.
                    relayLabel = rospy.get_param("~relay" + str(i) + "label", "No Label")
                    if relayLabel == req.relay:
                        foundRelay = True
                        while self._Busy: # Prevent simultaneous polling of serial port by multiple processes within this app due to ROS threading.
                            rospy.loginfo("BitBangDevice Busy . . .")
                            rospy.sleep(0.4)
                        self._Busy = True
                        rospy.loginfo("Changing relay " + str(self.relaySerialNumber) + " to " + str(req.state))
                        if req.state:
                            BitBangDevice(self.relaySerialNumber).port |= int(relay_data.address[str(i)], 16)
                            #BitBangDevice(relaySerialNumber).port |= int(relay.address[leftMotorRelay], 16)
                        elif not req.state:
                            BitBangDevice(self.relaySerialNumber).port &= ~int(relay_data.address[str(i)], 16)
                        checkState = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )
                        self._Busy = False
                        if checkState == 0:
                            newState = False
                        else:
                            newState = True
                        if newState == req.state:
                            toggleSuccess = True
        return(boardExists, foundRelay, toggleSuccess)

    def Run(self):
        # Get and broadcast status of all USB Relays.
        while not rospy.is_shutdown():
            relaystatus = usbRelayStatus()
            relaystatus.relayOn = [False] * 8 # Fill array for use.
            if self.relayExists: # Only poll if the relay exists.
                relaystatus.relayPresent = True
                # Gather USB Relay status for each relay and publish
                for i in range(1,9):
                    if not rospy.is_shutdown(): # ROS tends to get shut down while this is looping and throw a lot of errors
                        relayEnabled = rospy.get_param("~relay" + str(i) + "enabled", False)
                        if relayEnabled: # Do not touch (poll or anything) Relays that are not listed as enabled.
                            relayLabel = rospy.get_param("~relay" + str(i) + "label", "No Label")
                            while self._Busy: # Prevent simultaneous polling of serial port by multiple processes within this app due to ROS threading.
                                rospy.loginfo("BitBangDevice Busy . . .")
                                rospy.sleep(0.2)
                            self._Busy = True
                            state = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )
                            self._Busy = False
                            if state == 0:
                                #print "Relay " + str(i) + " state:\tOFF (" + str(state) + ")"
                                #print str(i) + " - " + relayLabel + ": OFF"
                                relaystatus.relayOn[i-1] = False
                            else:
                                #print "Relay " + str(i) + " state:\tON (" + str(state) + ")"
                                #print str(i) + " - " + relayLabel + ": ON"
                                relaystatus.relayOn[i-1] = True
            else: # If the relay does not exist just broadcast "False" to everything.
                relaystatus.relayPresent = False
            self._usbRelayStatusPublisher.publish(relaystatus) # Publish USB Relay status
            self.r.sleep() # Sleep long enough to maintain the rate set in __init__

    def Stop(self):
        rospy.loginfo("Shutting off all relays . . .")
        # At this point ROS is shutting down, so any attempts to check parameters or log may crash.
        self._Busy = True # We are shutting down, so make everyone else stall and plow ahead:
        for i in range(1,9): # Walk the relays
            state = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )
            while not state == 0: # Loop if it doesn't shut off.
                BitBangDevice(self.relaySerialNumber).port &= ~int(relay_data.address[str(i)], 16)
                state = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )

if __name__ == '__main__':
    node = UsbRelay()
    rospy.on_shutdown(node.Stop)
    try:
        node.Run()
    except rospy.ROSInterruptException:
        node.Stop()
<commit_msg>Extend sleep times on UsbRelay when busy to prevent thrashing.<commit_after>#!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Author: Chris L8 https://github.com/chrisl8
# URL: https://github.com/chrisl8/ArloBot

import rospy
import tf
import sys
import time

from std_msgs.msg import String
from std_msgs.msg import Bool
from arlobot_msgs.msg import usbRelayStatus
from arlobot_msgs.srv import *

#For USB relay board
from pylibftdi import BitBangDevice
from pylibftdi import Driver # Required to get serial number of unknown USB Relay device.

# From:
# ----------------------------------------------------------------------------
#
#   DRCONTROL.PY
#
#   Copyright (C) 2012 Sebastian Sjoholm, sebastian.sjoholm@gmail.com
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#   Version history can be found at
#   http://code.google.com/p/drcontrol/wiki/VersionHistory
#
#   $Rev$
#   $Date$
#
# ----------------------------------------------------------------------------
# For SainSmart 8 port USB model http://www.sainsmart.com/sainsmart-4-channel-12-v-usb-relay-board-module-controller-for-automation-robotics-1.html
class relay_data(dict):

    address = {
            "1":"1",
            "2":"2",
            "3":"4",
            "4":"8",
            "5":"10",
            "6":"20",
            "7":"40",
            "8":"80",
            "all":"FF"
            }

    def __getitem__(self, key): return self[key]
    def keys(self): return self.keys()

# ----------------------------------------------------------------------------
# testBit() returns a nonzero result, 2**offset, if the bit at 'offset' is one.
# http://wiki.python.org/moin/BitManipulation
# ----------------------------------------------------------------------------

def testBit(int_type, offset):
    mask = 1 << offset
    return(int_type & mask)

# ----------------------------------------------------------------------------
# LIST_DEVICES()
#
# Routine modified from the original pylibftdi example by Ben Bass
# ----------------------------------------------------------------------------

def list_devices():
    print "Vendor\t\tProduct\t\t\tSerial"
    dev_list = []
    for device in Driver().list_devices():
        device = map(lambda x: x.decode('latin1'), device)
        vendor, product, serial = device
        print "%s\t\t%s\t\t%s" % (vendor, product, serial)

def return_device_serial_number():
    #print "Vendor\t\tProduct\t\t\tSerial"
    dev_list = []
    for device in Driver().list_devices():
        device = map(lambda x: x.decode('latin1'), device)
        vendor, product, serial = device
        #print "%s\t\t%s\t\t%s" % (vendor, product, serial)
    return serial

# For SainSmart 8 port USB model http://www.sainsmart.com/sainsmart-4-channel-12-v-usb-relay-board-module-controller-for-automation-robotics-1.html
def get_relay_state( data, relay ):
    if relay == "1":
        return testBit(data, 0)
    if relay == "2":
        return testBit(data, 1)
    if relay == "3":
        return testBit(data, 2)
    if relay == "4":
        return testBit(data, 3)
    if relay == "5":
        return testBit(data, 4)
    if relay == "6":
        return testBit(data, 5)
    if relay == "7":
        return testBit(data, 6)
    if relay == "8":
        return testBit(data, 7)

class UsbRelay(object):
    '''
    Helper class for communicating with a Propeller board over serial port
    '''

    def __init__(self):
        rospy.init_node('arlobot_usbrelay')
        # http://wiki.ros.org/rospy_tutorials/Tutorials/WritingPublisherSubscriber
        self.r = rospy.Rate(0.25) # 1hz refresh rate
        #self.r = rospy.Rate(1) # 1hz refresh rate

        # Prevent overlapping calls to the serial port
        self._Busy = False

        # Wait for the arlobot_bringup launch file to initiate the usbRelayInstalled parameter before starting:
        while not rospy.has_param('/arlobot/usbRelayInstalled') and not rospy.is_shutdown():
            rospy.loginfo("arlobot_bringup not started yet, waiting . . .")
            rospy.sleep(1)

        self.relayExists = rospy.get_param("/arlobot/usbRelayInstalled", False)
        if self.relayExists:
            #list_devices()
            #NOTE: This will return the LAST device, so if you have multiple USB Relay boards this will have to be modified
            self.relaySerialNumber = return_device_serial_number()

        else:
            rospy.loginfo("No USB Relay board installed.")

        # Create a service that can be called to toggle any relay by name:
        # http://wiki.ros.org/ROS/Tutorials/CreatingMsgAndSrv
        # http://wiki.ros.org/ROS/Tutorials/WritingServiceClient%28python%29
        relayToggle = rospy.Service('~toggle_relay', ToggleRelay, self._ToggleRelayByName)
        relayFind = rospy.Service('~find_relay', FindRelay, self._FindRelayByName)

        # Publishers
        self._usbRelayStatusPublisher = rospy.Publisher('~usbRelayStatus', usbRelayStatus, queue_size=1) # for publishing status of USB Relays

    def _FindRelayByName(self, req):
        # This function will return the relay number for a given name based on the usbrelay.yaml loaded parameters
        # In theory any node can do this, but it helps to make this service available, since the topic we publish requires
        # You to know the number of the relay to figure out which array entry is the one you want.
        boardExists = False
        foundRelay = False
        relayNumber = 0
        if self.relayExists and not rospy.is_shutdown():
            if self.relayExists: # Do not do this if no relay exists.
                # Toggle Relay
                boardExists = True
                for i in range(1,9): # Walk the relays to find the one with the right name.
                    relayEnabled = rospy.get_param("~relay" + str(i) + "enabled", False)
                    if relayEnabled: # Do not touch (poll or anything) Relays that are not listed as enabled.
                        relayLabel = rospy.get_param("~relay" + str(i) + "label", "No Label")
                        if relayLabel == req.relay:
                            foundRelay = True
                            relayNumber = i
        return(boardExists, foundRelay, relayNumber)

    def _ToggleRelayByName(self, req):
        boardExists = False
        foundRelay = False
        toggleSuccess = False
        if self.relayExists: # Do not do this if no relay exists.
            # Toggle Relay
            boardExists = True
            for i in range(1,9): # Walk the relays to find the one with the right name.
                relayEnabled = rospy.get_param("~relay" + str(i) + "enabled", False)
                if relayEnabled: # Do not touch (poll or anything) Relays that are not listed as enabled.
                    relayLabel = rospy.get_param("~relay" + str(i) + "label", "No Label")
                    if relayLabel == req.relay:
                        foundRelay = True
                        while self._Busy: # Prevent simultaneous polling of serial port by multiple processes within this app due to ROS threading.
                            rospy.loginfo("BitBangDevice Busy . . .")
                            rospy.sleep(0.5)
                        self._Busy = True
                        rospy.loginfo("Changing relay " + str(self.relaySerialNumber) + " to " + str(req.state))
                        if req.state:
                            BitBangDevice(self.relaySerialNumber).port |= int(relay_data.address[str(i)], 16)
                            #BitBangDevice(relaySerialNumber).port |= int(relay.address[leftMotorRelay], 16)
                        elif not req.state:
                            BitBangDevice(self.relaySerialNumber).port &= ~int(relay_data.address[str(i)], 16)
                        checkState = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )
                        self._Busy = False
                        if checkState == 0:
                            newState = False
                        else:
                            newState = True
                        if newState == req.state:
                            toggleSuccess = True
        return(boardExists, foundRelay, toggleSuccess)

    def Run(self):
        # Get and broadcast status of all USB Relays.
        while not rospy.is_shutdown():
            relaystatus = usbRelayStatus()
            relaystatus.relayOn = [False] * 8 # Fill array for use.
            if self.relayExists: # Only poll if the relay exists.
                relaystatus.relayPresent = True
                # Gather USB Relay status for each relay and publish
                for i in range(1,9):
                    if not rospy.is_shutdown(): # ROS tends to get shut down while this is looping and throw a lot of errors
                        relayEnabled = rospy.get_param("~relay" + str(i) + "enabled", False)
                        if relayEnabled: # Do not touch (poll or anything) Relays that are not listed as enabled.
                            relayLabel = rospy.get_param("~relay" + str(i) + "label", "No Label")
                            while self._Busy: # Prevent simultaneous polling of serial port by multiple processes within this app due to ROS threading.
                                rospy.loginfo("BitBangDevice Busy . . .")
                                rospy.sleep(1)
                            self._Busy = True
                            state = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )
                            self._Busy = False
                            if state == 0:
                                #print "Relay " + str(i) + " state:\tOFF (" + str(state) + ")"
                                #print str(i) + " - " + relayLabel + ": OFF"
                                relaystatus.relayOn[i-1] = False
                            else:
                                #print "Relay " + str(i) + " state:\tON (" + str(state) + ")"
                                #print str(i) + " - " + relayLabel + ": ON"
                                relaystatus.relayOn[i-1] = True
            else: # If the relay does not exist just broadcast "False" to everything.
                relaystatus.relayPresent = False
            self._usbRelayStatusPublisher.publish(relaystatus) # Publish USB Relay status
            self.r.sleep() # Sleep long enough to maintain the rate set in __init__

    def Stop(self):
        rospy.loginfo("Shutting off all relays . . .")
        # At this point ROS is shutting down, so any attempts to check parameters or log may crash.
        self._Busy = True # We are shutting down, so make everyone else stall and plow ahead:
        for i in range(1,9): # Walk the relays
            state = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )
            while not state == 0: # Loop if it doesn't shut off.
                BitBangDevice(self.relaySerialNumber).port &= ~int(relay_data.address[str(i)], 16)
                state = get_relay_state( BitBangDevice(self.relaySerialNumber).port, str(i) )

if __name__ == '__main__':
    node = UsbRelay()
    rospy.on_shutdown(node.Stop)
    try:
        node.Run()
    except rospy.ROSInterruptException:
        node.Stop()
<|endoftext|>