<commit_before>"""
This file is part of Dycapo.
    Copyright (C) 2009, 2010 FBK Foundation, (http://www.fbk.eu)
    Authors: SoNet Group (see AUTHORS)
    Dycapo 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.

    Dycapo 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 Dycapo.  If not, see <http://www.gnu.org/licenses/>.

"""
"""
This module holds all the XML-RPC methods that a Driver needs.
"""
import datetime
import models
import response_codes
import rpc4django
import utils

@rpc4django.rpcmethod(name='dycapo.add_trip',
                      signature=['Response', 'Trip', 'Mode', 'Prefs',
                      'Location', 'Location'],
                      permission='server.can_xmlrpc')
def add_trip(trip, mode, preferences, source, destination, ** kwargs):
    """
    DEPRECATED. Use add_trip_exp(Trip trip) instead.
    Inserts a new Trip in Dycapo System. It supports a source, a
    destination and the trip mode. See the models for more information.

    TODO

    - verify user permissions
    - multiple waypoints

    PARAMETERS
    - ``trip`` - a **Trip** object, representing the Trip that the Driver
    is willing to save
    - ``mode`` - a **Mode** object, representing the modalities of the Trip
    - ``preferences`` - a **Prefs** object, representing the Trip preferences
    - ``source`` - a **Location** object, representing where the Trip will
        start.
    - ``destination`` - a **Location** object, representing where the Trip
    will end.

    RETURNS
    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    dict_trip = utils.clean_ids(trip)
    dict_mode = utils.clean_ids(mode)
    dict_prefs = utils.clean_ids(preferences)
    dict_source = utils.clean_ids(source)
    dict_destination = utils.clean_ids(destination)

    driver = utils.get_xmlrpc_user(kwargs)

    source = models.Location()
    source = utils.populate_object_from_dictionary(source, dict_source)

    destination = models.Location()
    destination = utils.populate_object_from_dictionary(destination,
                                                        dict_destination)

    mode = models.Mode()
    mode = utils.populate_object_from_dictionary(mode, dict_mode)
    mode.person = driver
    try:
        retrieven_mode = models.Mode.objects.get(person=driver,
                                                 make=mode.make,
                                                 model=mode.model,
                                                 capacity=mode.capacity,
                                                 kind=mode.kind)
        retrieven_mode.vacancy = mode.vacancy
        mode = retrieven_mode

    except models.Mode.DoesNotExist:
        pass

    preferences = models.Prefs()
    preferences = utils.populate_object_from_dictionary(preferences,
                                                        dict_prefs)

    try:
        source.save()
        destination.save()
        mode.save()
        preferences.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()
    trip = models.Trip()
    trip = utils.populate_object_from_dictionary(trip, dict_trip)
    trip.author = driver
    trip.mode = mode
    trip.prefs = preferences
    try:
        trip.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip.locations.add(source)
    trip.locations.add(destination)

    participation = models.Participation()
    participation.person = driver
    participation.trip = trip
    participation.role = 'driver'
    participation.save()
    trip_stored = models.Trip.objects.get(id=trip.id)
    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_INSERTED, "Trip",
                           trip_stored.to_xmlrpc())
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.add_trip_exp',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def add_trip_exp(trip, ** kwargs):
    """
    Inserts a new Trip in Dycapo System. It supports a source, a
    destination and the trip mode. See the models for more information.

    TODO

    - verify user permissions
    - multiple waypoints

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the Driver

    RETURNS
    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    dict_trip = utils.clean_ids(trip)
    dict_mode = utils.clean_ids(trip["content"]["mode"])
    dict_prefs = utils.clean_ids(trip["content"]["prefs"])
    array_locations = trip["content"]["locations"]

    driver = utils.get_xmlrpc_user(kwargs)

    source = models.Location()
    dict_source = utils.get_location_from_array(array_locations,"orig")
    source = utils.populate_object_from_dictionary(source, dict_source)

    destination = models.Location()
    dict_destination = utils.get_location_from_array(array_locations,"dest")
    destination = utils.populate_object_from_dictionary(destination, dict_destination)

    mode = models.Mode()
    mode = utils.populate_object_from_dictionary(mode, dict_mode)
    vacancy = dict_mode['vacancy']
    preferences = models.Prefs()
    preferences = utils.populate_object_from_dictionary(preferences, dict_prefs)

    mode, created = models.Mode.objects.get_or_create(person=driver,
                                                 make=mode.make,
                                                 model=mode.model,
                                                 capacity=mode.capacity,
                                                 kind=mode.kind)
    mode.vacancy = vacancy

    try:
        source.save()
        destination.save()
        mode.save()
        preferences.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip = models.Trip()
    trip = utils.populate_object_from_dictionary(trip, dict_trip)
    trip.author = driver
    trip.mode = mode
    trip.prefs = preferences
    try:
        trip.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip.locations.add(source)
    trip.locations.add(destination)

    participation = models.Participation()
    participation.person = driver
    participation.trip = trip
    participation.role = 'driver'
    participation.save()

    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_INSERTED, "Trip",
                           trip.to_xmlrpc())

    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.start_trip',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def start_trip(trip, ** kwargs):
    """
    Starts a Trip

    TODO

    - verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the Driver
        is starting

    RETURNS
    An object of type **Response**, containing all the details
    of the operation and results (if any)
    """

    trip_dict = trip
    try:
        trip = models.Trip.objects.filter(id=trip_dict['id']).only("id","active").get()
    except (KeyError, models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "boolean", False)
        return resp.to_xmlrpc()

    participation = models.Participation.objects.get(trip=trip.id,
                                                     role='driver')
    driver = utils.get_xmlrpc_user(kwargs)

    if participation.started:
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_ALREADY_STARTED,
                               "boolean", False)
        return resp.to_xmlrpc()

    participation.started = True
    participation.started_timestamp = datetime.datetime.now()
    try:
        participation.started_position_id = driver.position_id
    except models.Location.DoesNotExist:
        participation.started_position = None
    participation.save()
    trip.active = True
    trip.save()

    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_STARTED, "boolean", True)
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.check_ride_requests',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def check_ride_requests(trip, ** kwargs):
    """
    This method is for a driver to see if there are ride requests
    for his Trip

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the
    Driver is checking

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip

    try:
        trip = models.Trip.objects.filter(id=trip_dict['id']).only("id").get()
    except (KeyError,models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "Trip", trip_dict)
        return resp.to_xmlrpc()

    driver = utils.get_xmlrpc_user(kwargs)

    participations_for_trip = (models.Participation.objects.filter(trip=trip.id)
                               .exclude(person=driver)
                               .filter(started=False)
                               .filter(finished=False)
                               .filter(requested=True)
                               .filter(requested_deleted=False)
                               ).only("person")

    if len(participations_for_trip) == 0:
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.RIDE_REQUESTS_NOT_FOUND,
                               "boolean", False)
        return resp.to_xmlrpc()
    else:
        participations = [participation.person.to_xmlrpc()
                          for participation in participations_for_trip]
        resp = models.Response(response_codes.POSITIVE,
                               response_codes.RIDE_REQUESTS_FOUND,
                               "boolean", participations)
        return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.accept_ride_request',
                      signature=['Response', 'Trip', 'Person'],
                      permission='server.can_xmlrpc')
def accept_ride_request(trip, person, ** kwargs):
    """
    This method is for a driver to accept a ride request by a rider.

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip in which
        the Driver is accepting a ride.
    - ``person`` - a **Person** object, representing the Rider that
        the Driver is accepting

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip
    person_dict = person

    try:
        trip = models.Trip.objects.filter(id=trip_dict['id']).only("id").get()
    except (KeyError, models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "Trip", trip_dict)
        return resp.to_xmlrpc()

    try:
        rider = models.Person.objects.filter(username=person_dict['username']).only("id","position").get()
    except (KeyError, models.Person.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.PERSON_NOT_FOUND,
                               "Person", person_dict)
        return resp.to_xmlrpc()

    try:
        rider_participation = models.Participation.objects.filter(trip=trip.id,
                                                               person=rider.id).get()
    except models.Participation.DoesNotExist:
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.PERSON_NOT_FOUND,
                               "boolean", False)
        return resp.to_xmlrpc()
    if rider_participation.requested and not rider_participation.accepted:
        rider_participation.accepted = True
        rider_participation.accepted_timestamp = datetime.datetime.now()
        try:
            rider_participation.accepted_position_id = rider.position_id
        except models.Location.DoesNotExist:
            rider_participation.accepted_position = None

        rider_participation.save()
        resp = models.Response(response_codes.POSITIVE,
                               response_codes.RIDE_REQUEST_ACCEPTED,
                               "boolean", True)
        return resp.to_xmlrpc()

    resp = models.Response(response_codes.NEGATIVE,
                           response_codes.RIDE_REQUEST_REFUSED,
                           "boolean", False)
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.refuse_ride_request',
                      signature=['Response', 'Trip', 'Person'],
                      permission='server.can_xmlrpc')
def refuse_ride_request(trip, person, ** kwargs):
    """
    This method is for a driver to refuse a ride request by a rider.

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip in which
        the Driver is refusing a ride.
    - ``person`` - a **Person** object, representing the Rider that
        the Driver is refusing

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip
    person_dict = person

    try:
        trip = models.Trip.objects.filter(id=trip_dict['id']).only("id").get()
    except (KeyError, models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "Trip", trip_dict)
        return resp.to_xmlrpc()

    try:
        rider = models.Person.objects.filter(username=person_dict['username']).only("id","position").get()
    except (KeyError, models.Person.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.PERSON_NOT_FOUND,
                               "Person", person_dict)
        return resp.to_xmlrpc()

    try:
        rider_participation = models.Participation.objects.filter(trip=trip.id,
                                                               person=rider.id).get()
    except models.Participation.DoesNotExist:
        resp = models.Response(response_codes.NEGATIVE,
                           response_codes.PERSON_NOT_FOUND,
                           "boolean", False)
        return resp.to_xmlrpc()

    rider_participation.refused = True
    rider_participation.refused_timestamp = datetime.datetime.now()
    try:
        rider_participation.refused_position_id = rider.position_id
    except models.Location.DoesNotExist:
        rider_participation.accepted_position = None

    rider_participation.save()
    resp = models.Response(response_codes.POSITIVE,
                               response_codes.RIDE_REQUEST_REFUSED,
                               "boolean", True)
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.finish_trip',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def finish_trip(trip, ** kwargs):
    """
    This method is for a driver to close a Trip.

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the driver
    is closing

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip
    trip = models.Trip.objects.filter(id=trip_dict['id']).only("id").get()
    driver = utils.get_xmlrpc_user(kwargs)

    if driver.is_participating():
        participation = driver.get_active_participation()
        participation.finished = True
        participation.finished_timestamp = utils.now()
        participation.save()
    trip.active = False
    trip.save()

    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_DELETED,
                           "boolean", True)
    return resp.to_xmlrpc()
<commit_msg>cleaning driver.py<commit_after>"""
This file is part of Dycapo.
    Copyright (C) 2009, 2010 FBK Foundation, (http://www.fbk.eu)
    Authors: SoNet Group (see AUTHORS)
    Dycapo 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.

    Dycapo 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 Dycapo.  If not, see <http://www.gnu.org/licenses/>.

"""
"""
This module holds all the XML-RPC methods that a Driver needs.
"""
import datetime
import models
import response_codes
import rpc4django
import utils

@rpc4django.rpcmethod(name='dycapo.add_trip',
                      signature=['Response', 'Trip', 'Mode', 'Prefs',
                      'Location', 'Location'],
                      permission='server.can_xmlrpc')
def add_trip(trip, mode, preferences, source, destination, ** kwargs):
    """
    DEPRECATED. Use add_trip_exp(Trip trip) instead.
    Inserts a new Trip in Dycapo System. It supports a source, a
    destination and the trip mode. See the models for more information.

    TODO

    - verify user permissions
    - multiple waypoints

    PARAMETERS
    - ``trip`` - a **Trip** object, representing the Trip that the Driver
    is willing to save
    - ``mode`` - a **Mode** object, representing the modalities of the Trip
    - ``preferences`` - a **Prefs** object, representing the Trip preferences
    - ``source`` - a **Location** object, representing where the Trip will
        start.
    - ``destination`` - a **Location** object, representing where the Trip
    will end.

    RETURNS
    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    dict_trip = utils.clean_ids(trip)
    dict_mode = utils.clean_ids(mode)
    dict_prefs = utils.clean_ids(preferences)
    dict_source = utils.clean_ids(source)
    dict_destination = utils.clean_ids(destination)

    driver = utils.get_xmlrpc_user(kwargs)

    source = models.Location(**dict_source)

    destination = models.Location(**dict_destination)

    mode = models.Mode(**dict_mode)
    mode.person = driver
    try:
        retrieven_mode = models.Mode.objects.get(person=driver,
                                                 make=mode.make,
                                                 model=mode.model,
                                                 capacity=mode.capacity,
                                                 kind=mode.kind)
        retrieven_mode.vacancy = mode.vacancy
        mode = retrieven_mode

    except models.Mode.DoesNotExist:
        pass

    preferences = models.Prefs(**dict_prefs)

    try:
        source.save()
        destination.save()
        mode.save()
        preferences.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip = models.Trip(author=driver, mode=mode, prefs=preferences,
                       **dict_trip)

    try:
        trip.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip.locations.add(source)
    trip.locations.add(destination)

    participation = models.Participation(person=driver, trip=trip,
                                         role='driver')
    participation.save()
    trip_stored = models.Trip.objects.get(id=trip.id)
    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_INSERTED, "Trip",
                           trip_stored.to_xmlrpc())
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.add_trip_exp',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def add_trip_exp(trip, ** kwargs):
    """
    Inserts a new Trip in Dycapo System. It supports a source, a
    destination and the trip mode. See the models for more information.

    TODO

    - verify user permissions
    - multiple waypoints

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the Driver

    RETURNS
    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    dict_trip = utils.clean_ids(trip)
    dict_mode = utils.clean_ids(trip["content"]["mode"])
    dict_prefs = utils.clean_ids(trip["content"]["prefs"])
    array_locations = trip["content"]["locations"]

    driver = utils.get_xmlrpc_user(kwargs)

    dict_source = utils.get_location_from_array(array_locations,"orig")
    source = models.Location(**dict_source)

    dict_destination = utils.get_location_from_array(array_locations,"dest")
    destination = models.Location(**dict_destination)

    mode = models.Mode(**dict_mode)
    vacancy = dict_mode['vacancy']
    preferences = models.Prefs(**dict_prefs)

    mode, created = models.Mode.objects.get_or_create(person=driver,
                                                 make=mode.make,
                                                 model=mode.model,
                                                 capacity=mode.capacity,
                                                 kind=mode.kind)
    mode.vacancy = vacancy

    try:
        source.save()
        destination.save()
        mode.save()
        preferences.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip = models.Trip(author=driver, mode=mode, prefs=preferences,
                       **dict_trip)
    try:
        trip.save()
    except Exception, e:
        resp = models.Response(response_codes.NEGATIVE, str(e), "boolean",
                               False)
        return resp.to_xmlrpc()

    trip.locations.add(source)
    trip.locations.add(destination)

    participation = models.Participation(person=driver, trip=trip,
                                         role='driver')
    participation.save()

    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_INSERTED, "Trip",
                           trip.to_xmlrpc())

    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.start_trip',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def start_trip(trip, ** kwargs):
    """
    Starts a Trip

    TODO

    - verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the Driver
        is starting

    RETURNS
    An object of type **Response**, containing all the details
    of the operation and results (if any)
    """

    trip_dict = trip
    try:
        trip = models.Trip.objects.only("id","active").get(id=trip_dict['id'])
    except (KeyError, models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "boolean", False)
        return resp.to_xmlrpc()

    participation = models.Participation.objects.get(trip=trip.id,
                                                     role='driver')
    driver = utils.get_xmlrpc_user(kwargs)

    if participation.started:
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_ALREADY_STARTED,
                               "boolean", False)
        return resp.to_xmlrpc()

    participation.started = True
    participation.started_timestamp = datetime.datetime.now()
    try:
        participation.started_position_id = driver.position_id
    except models.Location.DoesNotExist:
        participation.started_position = None
    participation.save()
    trip.active = True
    trip.save()

    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_STARTED, "boolean", True)
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.check_ride_requests',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def check_ride_requests(trip, ** kwargs):
    """
    This method is for a driver to see if there are ride requests
    for his Trip

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the
    Driver is checking

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip

    try:
        trip = models.Trip.objects.only("id").get(id=trip_dict['id'])
    except (KeyError,models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "Trip", trip_dict)
        return resp.to_xmlrpc()

    driver = utils.get_xmlrpc_user(kwargs)

    participations_for_trip = (models.Participation.objects.filter(trip=trip.id)
                               .exclude(person=driver)
                               .filter(started=False)
                               .filter(finished=False)
                               .filter(requested=True)
                               .filter(requested_deleted=False)
                               ).only("person")

    if not len(participations_for_trip):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.RIDE_REQUESTS_NOT_FOUND,
                               "boolean", False)
        return resp.to_xmlrpc()
    else:
        participations = [participation.person.to_xmlrpc()
                          for participation in participations_for_trip]
        resp = models.Response(response_codes.POSITIVE,
                               response_codes.RIDE_REQUESTS_FOUND,
                               "boolean", participations)
        return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.accept_ride_request',
                      signature=['Response', 'Trip', 'Person'],
                      permission='server.can_xmlrpc')
def accept_ride_request(trip, person, ** kwargs):
    """
    This method is for a driver to accept a ride request by a rider.

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip in which
        the Driver is accepting a ride.
    - ``person`` - a **Person** object, representing the Rider that
        the Driver is accepting

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip
    person_dict = person

    try:
        trip = models.Trip.objects.only("id").get(id=trip_dict['id'])
    except (KeyError, models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "Trip", trip_dict)
        return resp.to_xmlrpc()

    try:
        rider = models.Person.objects.only("id","position").get(
            username=person_dict['username'])
    except (KeyError, models.Person.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.PERSON_NOT_FOUND,
                               "Person", person_dict)
        return resp.to_xmlrpc()

    try:
        rider_participation = models.Participation.objects.get(trip=trip.id,
                                                               person=rider.id)
    except models.Participation.DoesNotExist:
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.PERSON_NOT_FOUND,
                               "boolean", False)
        return resp.to_xmlrpc()
    if rider_participation.requested and not rider_participation.accepted:
        rider_participation.accepted = True
        rider_participation.accepted_timestamp = datetime.datetime.now()
        try:
            rider_participation.accepted_position_id = rider.position_id
        except models.Location.DoesNotExist:
            rider_participation.accepted_position = None

        rider_participation.save()
        resp = models.Response(response_codes.POSITIVE,
                               response_codes.RIDE_REQUEST_ACCEPTED,
                               "boolean", True)
        return resp.to_xmlrpc()

    resp = models.Response(response_codes.NEGATIVE,
                           response_codes.RIDE_REQUEST_REFUSED,
                           "boolean", False)
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.refuse_ride_request',
                      signature=['Response', 'Trip', 'Person'],
                      permission='server.can_xmlrpc')
def refuse_ride_request(trip, person, ** kwargs):
    """
    This method is for a driver to refuse a ride request by a rider.

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip in which
        the Driver is refusing a ride.
    - ``person`` - a **Person** object, representing the Rider that
        the Driver is refusing

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip
    person_dict = person

    try:
        trip = models.Trip.objects.only("id").get(id=trip_dict['id'])
    except (KeyError, models.Trip.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.TRIP_NOT_FOUND,
                               "Trip", trip_dict)
        return resp.to_xmlrpc()

    try:
        rider = models.Person.objects.only("id","position").get(
            username=person_dict['username'])
    except (KeyError, models.Person.DoesNotExist):
        resp = models.Response(response_codes.NEGATIVE,
                               response_codes.PERSON_NOT_FOUND,
                               "Person", person_dict)
        return resp.to_xmlrpc()

    try:
        rider_participation = models.Participation.objects.get(trip=trip.id,
                                                               person=rider.id)
    except models.Participation.DoesNotExist:
        resp = models.Response(response_codes.NEGATIVE,
                           response_codes.PERSON_NOT_FOUND,
                           "boolean", False)
        return resp.to_xmlrpc()

    rider_participation.refused = True
    rider_participation.refused_timestamp = datetime.datetime.now()
    try:
        rider_participation.refused_position_id = rider.position_id
    except models.Location.DoesNotExist:
        rider_participation.accepted_position = None

    rider_participation.save()
    resp = models.Response(response_codes.POSITIVE,
                               response_codes.RIDE_REQUEST_REFUSED,
                               "boolean", True)
    return resp.to_xmlrpc()

@rpc4django.rpcmethod(name='dycapo.finish_trip',
                      signature=['Response', 'Trip'],
                      permission='server.can_xmlrpc')
def finish_trip(trip, ** kwargs):
    """
    This method is for a driver to close a Trip.

    TODO

    -verify user permissions

    PARAMETERS

    - ``trip`` - a **Trip** object, representing the Trip that the driver
    is closing

    RETURNS

    An object of type **Response**, containing all the details of the
    operation and results (if any)
    """

    trip_dict = trip
    trip = models.Trip.objects.only("id").get(id=trip_dict['id'])
    driver = utils.get_xmlrpc_user(kwargs)

    if driver.is_participating():
        participation = driver.get_active_participation()
        participation.finished = True
        participation.finished_timestamp = utils.now()
        participation.save()
    trip.active = False
    trip.save()

    resp = models.Response(response_codes.POSITIVE,
                           response_codes.TRIP_DELETED,
                           "boolean", True)
    return resp.to_xmlrpc()
<|endoftext|>


<commit_before>version = '0.0.4'<commit_msg>Bump version number to 0.0.5<commit_after>version = '0.0.5'<|endoftext|>


<commit_before><commit_msg>Adding unit test for N-input dynlib<commit_after><|endoftext|>


<commit_before>import logging
import json
import requests
import time
import field_convertors
import os
import subprocess

def work(input,output,key="",sheet=None,num_cols=2,convertors={},
         spreadsheet_name_key=None,spreadsheet_index_key=None):
    if sheet is None:
        sheets = [ None ]
    else:
        if type(sheet) is str or type(sheet) is unicode:
            sheets = [ sheet ]
        else:
            sheets = sheet
    out = None
    for sheet in sheets:
        sheetp = "sheet=%s&" % sheet if sheet is not None else ""
        columns = ",".join([ chr(65+i) for i in range(num_cols) ])
        params = (key,sheetp,columns)
        URL="https://docs.google.com/a/open-budget.org.il/spreadsheets/d/%s/gviz/tq?%stq=select+%s&tqx=reqId:1;out:json;+responseHandler:x" % params
        print URL
        retries = 3
        while retries > 0:
            try:
                user_agent = {'User-agent': 'Mozilla/5.0', 'Connection':'Close'}
                data = requests.get(URL,headers=user_agent) # remove JavaScript handler
                print data
                data = data.text[2:-2]
                break
            except Exception,e:
                logging.error("Failed to open url, retries=%d (%s)" % (retries, str(e)))
            time.sleep(10)
            retries = retries - 1
            assert(retries > 0)
        data = json.loads(data)

        header = [x['label'] for x in data['table']['cols']]
        start=0
        if list(set(header))[0] == "":
            header = [x['v'] if x is not None else None for x in data['table']['rows'][0]['c']]
            start = 1
        rows = [[x['v'] if x is not None else None for x in data['table']['rows'][i]['c']] for i in range(start,len(data['table']['rows']))]

        _convertors = dict([ (h, field_convertors.__dict__[convertors.get(h,'id')]) for h in header ])
        rows = [ dict([(k,_convertors[k](v)) for k,v in zip(header,row)]) for row in rows ]
        if spreadsheet_name_key is not None and sheet is not None:
            for row in rows:
                row[spreadsheet_name_key] = sheet
        if spreadsheet_index_key is not None:
            for i,row in enumerate(rows):
                row[spreadsheet_index_key] = i
        if len(rows) > 0 and out is None:
            out = file(output,'w')
        for row in rows:
            out.write(json.dumps(row,sort_keys=True)+"\n")

if __name__ == "__main__":
    jargs = [json.loads(x) for x in sys.argv[1:8]]
    inp,out,key,sheet,num_cols,convertors,spreadsheet_name_key,spreadsheet_index_key = jargs[:]
    work(inp,out,key,sheet,num_cols,convertors,spreadsheet_name_key,spreadsheet_index_key)
    sys.exit(0)

class spreadsheet_to_jsons(object):
    def process(self,input,output,key="",sheet=None,num_cols=2,convertors={},
                spreadsheet_name_key=None,spreadsheet_index_key=None):
        env = os.environ.copy()
        cwd = os.getcwd()
        args = ['/usr/bin/env', 'python', __file__]
        jargs = [input,output,key,sheet,num_cols,convertors,spreadsheet_name_key,spreadsheet_index_key]
        jargs = [json.dumps(arg) for arg in jargs]
        args.extend(jargs)
        logging.info("RUNNING %s" % " ".join(args))
        logging.info("cwd='%s'" % cwd)
        scraper = subprocess.Popen(args,
                                   cwd=cwd,env=env,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = scraper.communicate()
        for x in stdout.split('\n'):
            logging.debug(x)
        for x in stderr.split('\n'):
            logging.error(x)
        assert(len(stderr.strip())==0)
<commit_msg>more robust spreadsheet_to_jsons<commit_after>import logging
import json
import requests
import time
import field_convertors
import os
import subprocess
import sys

def work(input,output,key="",sheet=None,num_cols=2,convertors={},
         spreadsheet_name_key=None,spreadsheet_index_key=None):
    if sheet is None:
        sheets = [ None ]
    else:
        if type(sheet) is str or type(sheet) is unicode:
            sheets = [ sheet ]
        else:
            sheets = sheet
    out = None
    for sheet in sheets:
        sheetp = "sheet=%s&" % sheet if sheet is not None else ""
        columns = ",".join([ chr(65+i) for i in range(num_cols) ])
        params = (key,sheetp,columns)
        URL="https://docs.google.com/a/open-budget.org.il/spreadsheets/d/%s/gviz/tq?%stq=select+%s&tqx=reqId:1;out:json;+responseHandler:x" % params
        print URL
        retries = 3
        while retries > 0:
            try:
                user_agent = {'User-agent': 'Mozilla/5.0', 'Connection':'Close'}
                data = requests.get(URL,headers=user_agent) # remove JavaScript handler
                print data
                data = data.text[2:-2]
                break
            except Exception,e:
                logging.error("Failed to open url, retries=%d (%s)" % (retries, str(e)))
            time.sleep(10)
            retries = retries - 1
            assert(retries > 0)
        data = json.loads(data)

        header = [x['label'] for x in data['table']['cols']]
        start=0
        if list(set(header))[0] == "":
            header = [x['v'] if x is not None else None for x in data['table']['rows'][0]['c']]
            start = 1
        rows = [[x['v'] if x is not None else None for x in data['table']['rows'][i]['c']] for i in range(start,len(data['table']['rows']))]

        _convertors = dict([ (h, field_convertors.__dict__[convertors.get(h,'id')]) for h in header ])
        rows = [ dict([(k,_convertors[k](v)) for k,v in zip(header,row)]) for row in rows ]
        if spreadsheet_name_key is not None and sheet is not None:
            for row in rows:
                row[spreadsheet_name_key] = sheet
        if spreadsheet_index_key is not None:
            for i,row in enumerate(rows):
                row[spreadsheet_index_key] = i
        if len(rows) > 0 and out is None:
            out = file(output,'w')
        for row in rows:
            out.write(json.dumps(row,sort_keys=True)+"\n")

if __name__ == "__main__":
    jargs = [json.loads(x) for x in sys.argv[1:8]]
    inp,out,key,sheet,num_cols,convertors,spreadsheet_name_key,spreadsheet_index_key = jargs[:]
    work(inp,out,key,sheet,num_cols,convertors,spreadsheet_name_key,spreadsheet_index_key)
    sys.exit(0)

class spreadsheet_to_jsons(object):
    def process(self,input,output,key="",sheet=None,num_cols=2,convertors={},
                spreadsheet_name_key=None,spreadsheet_index_key=None):
        env = os.environ.copy()
        cwd = os.getcwd()
        args = ['/usr/bin/env', 'python', __file__]
        jargs = [input,output,key,sheet,num_cols,convertors,spreadsheet_name_key,spreadsheet_index_key]
        jargs = [json.dumps(arg) for arg in jargs]
        args.extend(jargs)
        logging.info("RUNNING %s" % " ".join(args))
        logging.info("cwd='%s'" % cwd)
        scraper = subprocess.Popen(args,
                                   cwd=cwd,env=env,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = scraper.communicate()
        for x in stdout.split('\n'):
            logging.debug(x)
        for x in stderr.split('\n'):
            logging.error(x)
        assert(len(stderr.strip())==0)
<|endoftext|>


<commit_before>#
# This file is part of Plinth.
#
# 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/>.
#

"""
Plinth module for radicale.
"""

import augeas
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _

from plinth import actions
from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
from plinth.menu import main_menu
from plinth.utils import format_lazy

version = 1

service = None

managed_services = ['radicale']

managed_packages = ['radicale']

title = _('Calendar and Addressbook \n (Radicale)')

description = [
    format_lazy(
        _('Radicale is a CalDAV and CardDAV server. It allows synchronization '
          'and sharing of scheduling and contact data. To use Radicale, a '
          ' supported client application '
          'is needed. Radicale can be accessed by any user with a {box_name} '
          'login.'), box_name=_(cfg.box_name)),
]

reserved_usernames = ['radicale']

CONFIG_FILE = '/etc/radicale/config'

def init():
    """Initialize the radicale module."""
    menu = main_menu.get('apps')
    menu.add_urlname(title, 'glyphicon-calendar', 'radicale:index')

    global service
    setup_helper = globals()['setup_helper']
    if setup_helper.get_state() != 'needs-setup':
        service = service_module.Service(
            managed_services[0], title, ports=['http', 'https'],
            is_external=True,
            enable=enable, disable=disable)

        if service.is_enabled():
            add_shortcut()

def setup(helper, old_version=None):
    """Install and configure the module."""
    helper.install(managed_packages)
    helper.call('post', actions.superuser_run, 'radicale', ['setup'])
    global service
    if service is None:
        service = service_module.Service(
            managed_services[0], title, ports=['http', 'https'],
            is_external=True,
            enable=enable, disable=disable)
    helper.call('post', service.notify_enabled, None, True)
    helper.call('post', add_shortcut)

def add_shortcut():
    frontpage.add_shortcut('radicale', title,
                           details=description,
                           configure_url=reverse_lazy('radicale:index'),
                           login_required=True)

def enable():
    """Enable the module."""
    actions.superuser_run('radicale', ['enable'])
    add_shortcut()

def disable():
    """Disable the module."""
    actions.superuser_run('radicale', ['disable'])
    frontpage.remove_shortcut('radicale')

def load_augeas():
    """Prepares the augeas."""
    aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
                        augeas.Augeas.NO_MODL_AUTOLOAD)

    # INI file lens
    aug.set('/augeas/load/Puppet/lens', 'Puppet.lns')
    aug.set('/augeas/load/Puppet/incl[last() + 1]', CONFIG_FILE)

    aug.load()
    return aug

def get_rights_value():
    """Returns the current Rights value."""
    aug = load_augeas()
    value = aug.get('/files' + CONFIG_FILE + '/rights/type')
    return value

def diagnose():
    """Run diagnostics and return the results."""
    results = []

    results.append(action_utils.diagnose_port_listening(5232, 'tcp4'))
    results.append(action_utils.diagnose_port_listening(5232, 'tcp6'))
    results.extend(action_utils.diagnose_url_on_all(
        'https://{host}/radicale', check_certificate=False))

    return results
<commit_msg>radicale: Update link to documentation<commit_after>#
# This file is part of Plinth.
#
# 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/>.
#

"""
Plinth module for radicale.
"""

import augeas
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _

from plinth import actions
from plinth import action_utils
from plinth import cfg
from plinth import frontpage
from plinth import service as service_module
from plinth.menu import main_menu
from plinth.utils import format_lazy

version = 1

service = None

managed_services = ['radicale']

managed_packages = ['radicale']

title = _('Calendar and Addressbook \n (Radicale)')

description = [
    format_lazy(
        _('Radicale is a CalDAV and CardDAV server. It allows synchronization '
          'and sharing of scheduling and contact data. To use Radicale, a '
          'supported client '
          'application is needed. Radicale can be accessed by any user '
          'with a {box_name} login.'), box_name=_(cfg.box_name)),
]

reserved_usernames = ['radicale']

CONFIG_FILE = '/etc/radicale/config'

def init():
    """Initialize the radicale module."""
    menu = main_menu.get('apps')
    menu.add_urlname(title, 'glyphicon-calendar', 'radicale:index')

    global service
    setup_helper = globals()['setup_helper']
    if setup_helper.get_state() != 'needs-setup':
        service = service_module.Service(
            managed_services[0], title, ports=['http', 'https'],
            is_external=True,
            enable=enable, disable=disable)

        if service.is_enabled():
            add_shortcut()

def setup(helper, old_version=None):
    """Install and configure the module."""
    helper.install(managed_packages)
    helper.call('post', actions.superuser_run, 'radicale', ['setup'])
    global service
    if service is None:
        service = service_module.Service(
            managed_services[0], title, ports=['http', 'https'],
            is_external=True,
            enable=enable, disable=disable)
    helper.call('post', service.notify_enabled, None, True)
    helper.call('post', add_shortcut)

def add_shortcut():
    frontpage.add_shortcut('radicale', title,
                           details=description,
                           configure_url=reverse_lazy('radicale:index'),
                           login_required=True)

def enable():
    """Enable the module."""
    actions.superuser_run('radicale', ['enable'])
    add_shortcut()

def disable():
    """Disable the module."""
    actions.superuser_run('radicale', ['disable'])
    frontpage.remove_shortcut('radicale')

def load_augeas():
    """Prepares the augeas."""
    aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
                        augeas.Augeas.NO_MODL_AUTOLOAD)

    # INI file lens
    aug.set('/augeas/load/Puppet/lens', 'Puppet.lns')
    aug.set('/augeas/load/Puppet/incl[last() + 1]', CONFIG_FILE)

    aug.load()
    return aug

def get_rights_value():
    """Returns the current Rights value."""
    aug = load_augeas()
    value = aug.get('/files' + CONFIG_FILE + '/rights/type')
    return value

def diagnose():
    """Run diagnostics and return the results."""
    results = []

    results.append(action_utils.diagnose_port_listening(5232, 'tcp4'))
    results.append(action_utils.diagnose_port_listening(5232, 'tcp6'))
    results.extend(action_utils.diagnose_url_on_all(
        'https://{host}/radicale', check_certificate=False))

    return results
<|endoftext|>


<commit_before># PYSPARK_DRIVER_PYTHON=ipython pyspark --packages com.databricks:spark-csv_2.10:1.4.0

# Load the on-time parquet file
on_time_dataframe = spark.read.parquet('data/on_time_performance.parquet')
on_time_dataframe.registerTempTable("on_time_performance")

from pyspark.sql.types import StringType, IntegerType, DoubleType
from pyspark.sql.types import StructType, StructField

wban_schema = StructType([
  StructField("REGION", StringType(), True),
  StructField("WBAN_ID", StringType(), True),
  StructField("STATION_NAME", StringType(), True),
  StructField("STATE_PROVINCE", StringType(), True),
  StructField("COUNTY", StringType(), True),
  StructField("COUNTRY", StringType(), True),
  StructField("EXTENDED_NAME", StringType(), True),
  StructField("CALL_SIGN", StringType(), True),
  StructField("STATION_TYPE", StringType(), True),
  StructField("DATE_ASSIGNED", StringType(), True),
  StructField("BEGIN_DATE", StringType(), True),
  StructField("COMMENTS", StringType(), True),
  StructField("LOCATION", StringType(), True),
  StructField("ELEV_OTHER", StringType(), True),
  StructField("ELEV_GROUND", StringType(), True),
  StructField("ELEV_RUNWAY", StringType(), True),
  StructField("ELEV_BAROMETRIC", StringType(), True),
  StructField("ELEV_STATION", StringType(), True),
  StructField("ELEV_UPPER_AIR", StringType(), True)
])

# Load the WBAN station master list
wban_master_list = spark.read.format('com.databricks.spark.csv')\
  .options(header='true', inferschema='false', delimiter='|')\
  .schema(wban_schema)\
  .load('data/wbanmasterlist.psv')
wban_master_list.show(5)

# Filter to only airports
airport_wbans = wban_master_list.filter(
  wban_master_list.STATION_NAME.endswith("AIRPORT")
)
airport_wbans.count() # 338

#
# Compare to airport count in on-time-performance table
#

# Get the airports from the origin/destination
origin_airports = spark.sql("""
SELECT Origin AS Airport
FROM on_time_performance
""")
dest_airports = spark.sql("""
SELECT Dest AS Airport
FROM on_time_performance
""")

# Combine the airports into one relation & sqlize it
all_airports_flights = origin_airports.union(dest_airports)
all_airports_flights.registerTempTable("all_airports_flights")

# Get the set of unique airport codes
distinct_airports = spark.sql("""
SELECT DISTINCT(Airport) FROM all_airports_flights
""")

# Get a count of the airport codes
distinct_airports.count() # 332

# Load the weather records themselves
hourly_weather_records = spark.read.format('com.databricks.spark.csv')\
  .options(header='true', inferschema='true', delimiter=',')\
  .load('data/2015*hourly.txt')
hourly_weather_records.show()

# Show a few fields for a period for (probably) one station
trimmed_hourly_weather_records = hourly_weather_records.select(
  hourly_weather_records.WBAN,
  hourly_weather_records.Date,
  hourly_weather_records.Time,
  hourly_weather_records.SkyCondition,
  hourly_weather_records.WeatherType,
  hourly_weather_records.DryBulbCelsius,
  hourly_weather_records.Visibility,
  hourly_weather_records.WindSpeed,
  hourly_weather_records.WindDirection,
)
trimmed_hourly_weather_records.show()
<commit_msg>Now loads all weather types<commit_after># Load the on-time parquet file
on_time_dataframe = spark.read.parquet('data/on_time_performance.parquet')
on_time_dataframe.registerTempTable("on_time_performance")

from pyspark.sql.types import StringType, IntegerType, DoubleType
from pyspark.sql.types import StructType, StructField

wban_schema = StructType([
  StructField("REGION", StringType(), True),
  StructField("WBAN_ID", StringType(), True),
  StructField("STATION_NAME", StringType(), True),
  StructField("STATE_PROVINCE", StringType(), True),
  StructField("COUNTY", StringType(), True),
  StructField("COUNTRY", StringType(), True),
  StructField("EXTENDED_NAME", StringType(), True),
  StructField("CALL_SIGN", StringType(), True),
  StructField("STATION_TYPE", StringType(), True),
  StructField("DATE_ASSIGNED", StringType(), True),
  StructField("BEGIN_DATE", StringType(), True),
  StructField("COMMENTS", StringType(), True),
  StructField("LOCATION", StringType(), True),
  StructField("ELEV_OTHER", StringType(), True),
  StructField("ELEV_GROUND", StringType(), True),
  StructField("ELEV_RUNWAY", StringType(), True),
  StructField("ELEV_BAROMETRIC", StringType(), True),
  StructField("ELEV_STATION", StringType(), True),
  StructField("ELEV_UPPER_AIR", StringType(), True)
])

# Load the WBAN station master list
wban_master_list = spark.read.format('com.databricks.spark.csv')\
  .options(header='true', inferschema='false', delimiter='|')\
  .schema(wban_schema)\
  .load('data/wbanmasterlist.psv')
wban_master_list.show(5)

# Filter to only airports
airport_wbans = wban_master_list.filter(
  wban_master_list.STATION_NAME.endswith("AIRPORT")
)
airport_wbans.count() # 338

#
# Compare to airport count in on-time-performance table
#

# Get the airports from the origin/destination
origin_airports = spark.sql("""
  SELECT Origin AS Airport
  FROM on_time_performance
""")
dest_airports = spark.sql("""
  SELECT Dest AS Airport
  FROM on_time_performance
""")

# Combine the airports into one relation & sqlize it
distinct_airports = origin_airports\
  .union(dest_airports)\
  .distinct()

# Get a count of the airport codes
distinct_airports.count()

# Get a count of the airport codes
distinct_airports.count() # 332

# Load the weather records themselves
hourly_weather_records = spark.read.format('com.databricks.spark.csv')\
  .options(header='true', inferschema='true', delimiter=',')\
  .load('data/2015*hourly.txt')
hourly_weather_records.show()

# Show a few fields for a period for (probably) one station
trimmed_hourly_weather_records = hourly_weather_records.select(
  hourly_weather_records.WBAN,
  hourly_weather_records.Date,
  hourly_weather_records.Time,
  hourly_weather_records.SkyCondition,
  hourly_weather_records.WeatherType,
  hourly_weather_records.DryBulbCelsius,
  hourly_weather_records.Visibility,
  hourly_weather_records.WindSpeed,
  hourly_weather_records.WindDirection,
)
trimmed_hourly_weather_records.show()

#
# Load hourly observations
#

from pyspark.sql.types import StringType, IntegerType, DoubleType
from pyspark.sql.types import StructType, StructField

hourly_schema = StructType([
  StructField("WBAN", StringType(), True),
  StructField("Date", StringType(), True),
  StructField("Time", StringType(), True),
  StructField("StationType", StringType(), True),
  StructField("SkyCondition", StringType(), True),
  StructField("SkyConditionFlag", StringType(), True),
  StructField("Visibility", StringType(), True),
  StructField("VisibilityFlag", StringType(), True),
  StructField("WeatherType", StringType(), True),
  StructField("WeatherTypeFlag", StringType(), True),
  StructField("DryBulbFarenheit", StringType(), True),
  StructField("DryBulbFarenheitFlag", StringType(), True),
  StructField("DryBulbCelsius", StringType(), True),
  StructField("DryBulbCelsiusFlag", StringType(), True),
  StructField("WetBulbFarenheit", StringType(), True),
  StructField("WetBulbFarenheitFlag", StringType(), True),
  StructField("WetBulbCelsius", StringType(), True),
  StructField("WetBulbCelsiusFlag", StringType(), True),
  StructField("DewPointFarenheit", StringType(), True),
  StructField("DewPointFarenheitFlag", StringType(), True),
  StructField("DewPointCelsius", StringType(), True),
  StructField("DewPointCelsiusFlag", StringType(), True),
  StructField("RelativeHumidity", StringType(), True),
  StructField("RelativeHumidityFlag", StringType(), True),
  StructField("WindSpeed", StringType(), True),
  StructField("WindSpeedFlag", StringType(), True),
  StructField("WindDirection", StringType(), True),
  StructField("WindDirectionFlag", StringType(), True),
  StructField("ValueForWindCharacter", StringType(), True),
  StructField("ValueForWindCharacterFlag", StringType(), True),
  StructField("StationPressure", StringType(), True),
  StructField("StationPressureFlag", StringType(), True),
  StructField("PressureTendency", StringType(), True),
  StructField("PressureTendencyFlag", StringType(), True),
  StructField("PressureChange", StringType(), True),
  StructField("PressureChangeFlag", StringType(), True),
  StructField("SeaLevelPressure", StringType(), True),
  StructField("SeaLevelPressureFlag", StringType(), True),
  StructField("RecordType", StringType(), True),
  StructField("RecordTypeFlag", StringType(), True),
  StructField("HourlyPrecip", StringType(), True),
  StructField("HourlyPrecipFlag", StringType(), True),
  StructField("Altimeter", StringType(), True),
  StructField("AltimeterFlag", StringType(), True),
])

# Load the weather records themselves
hourly_weather_records = spark.read.format('com.databricks.spark.csv')\
  .options(header='true', inferschema='false', delimiter=',')\
  .schema(hourly_schema)\
  .load('data/2015*hourly.txt')
hourly_weather_records.show()

#
# Load daily observations
#

# Load the weather records themselves
daily_schema = StructType([
  StructField("WBAN", StringType(), True),
  StructField("YearMonthDay", StringType(), True),
  StructField("Tmax", StringType(), True),
  StructField("TmaxFlag", StringType(), True),
  StructField("Tmin", StringType(), True),
  StructField("TminFlag", StringType(), True),
  StructField("Tavg", StringType(), True),
  StructField("TavgFlag", StringType(), True),
  StructField("Depart", StringType(), True),
  StructField("DepartFlag", StringType(), True),
  StructField("DewPoint", StringType(), True),
  StructField("DewPointFlag", StringType(), True),
  StructField("WetBulb", StringType(), True),
  StructField("WetBulbFlag", StringType(), True),
  StructField("Heat", StringType(), True),
  StructField("HeatFlag", StringType(), True),
  StructField("Cool", StringType(), True),
  StructField("CoolFlag", StringType(), True),
  StructField("Sunrise", StringType(), True),
  StructField("SunriseFlag", StringType(), True),
  StructField("Sunset", StringType(), True),
  StructField("SunsetFlag", StringType(), True),
  StructField("CodeSum", StringType(), True),
  StructField("CodeSumFlag", StringType(), True),
  StructField("Depth", StringType(), True),
  StructField("DepthFlag", StringType(), True),
  StructField("Water1", StringType(), True),
  StructField("Water1Flag", StringType(), True),
  StructField("SnowFall", StringType(), True),
  StructField("SnowFallFlag", StringType(), True),
  StructField("PrecipTotal", StringType(), True),
  StructField("PrecipTotalFlag", StringType(), True),
  StructField("StnPressure", StringType(), True),
  StructField("StnPressureFlag", StringType(), True),
  StructField("SeaLevel", StringType(), True),
  StructField("SeaLevelFlag", StringType(), True),
  StructField("ResultSpeed", StringType(), True),
  StructField("ResultSpeedFlag", StringType(), True),
  StructField("ResultDir", StringType(), True),
  StructField("ResultDirFlag", StringType(), True),
  StructField("AvgSpeed", StringType(), True),
  StructField("AvgSpeedFlag", StringType(), True),
  StructField("Max5Speed", StringType(), True),
  StructField("Max5SpeedFlag", StringType(), True),
  StructField("Max5Dir", StringType(), True),
  StructField("Max5DirFlag", StringType(), True),
  StructField("Max2Speed", StringType(), True),
  StructField("Max2SpeedFlag", StringType(), True),
  StructField("Max2Dir", StringType(), True),
  StructField("Max2DirFlag", StringType(), True),
])

daily_weather_records = spark.read.format('com.databricks.spark.csv')\
  .options(header='true', inferschema='false', delimiter=',')\
  .schema(daily_schema)\
  .load('data/2015*daily.txt')
daily_weather_records.show()
<|endoftext|>


<commit_before>import uuid

from django.db import models

def sane_repr(*attrs):
    if 'id' not in attrs and 'pk' not in attrs:
        attrs = ('id',) + attrs

    def _repr(self):
        cls = type(self).__name__

        pairs = (
            '%s=%s' % (a, repr(getattr(self, a, None)))
            for a in attrs)

        return '<%s at 0x%x: %s>' % (cls, id(self), ', '.join(pairs))

    return _repr

def sane_str(*attrs):
    def _str(self):
        return '; '.join(str(getattr(self, attr, '-')) for attr in attrs)
    return _str

class KeybarModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)

    class Meta:
        abstract = True

    __repr__ = sane_repr('id')
<commit_msg>Add default str repr<commit_after>import uuid

from django.db import models

def sane_repr(*attrs):
    if 'id' not in attrs and 'pk' not in attrs:
        attrs = ('id',) + attrs

    def _repr(self):
        cls = type(self).__name__

        pairs = (
            '%s=%s' % (a, repr(getattr(self, a, None)))
            for a in attrs)

        return '<%s at 0x%x: %s>' % (cls, id(self), ', '.join(pairs))

    return _repr

def sane_str(*attrs):
    def _str(self):
        return '; '.join(str(getattr(self, attr, '-')) for attr in attrs)
    return _str

class KeybarModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)

    class Meta:
        abstract = True

    __repr__ = sane_repr('id')
    __str__ = sane_str('id')
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
#   Debian Changes Bot
#   Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
#
#   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/>.

import os
import time
import random
import supybot
import threading

from supybot.commands import wrap, many
from supybot import ircdb, log, schedule

from btsutils.debbugs import BugExceptions

from DebianDevelChangesBot.mailparsers import get_message
from DebianDevelChangesBot.datasources import get_datasources, TestingRCBugs, \
    NewQueue, RmQueue, Maintainer
from DebianDevelChangesBot.utils import parse_mail, FifoReader, colourise, \
    rewrite_topic, madison, bug_synopsis, format_email_address

class DebianDevelChanges(supybot.callbacks.Plugin):
    threaded = True

    def __init__(self, irc):
        self.__parent = super(DebianDevelChanges, self)
        self.__parent.__init__(irc)
        self.irc = irc
        self.topic_lock = threading.Lock()

        fr = FifoReader()
        fifo_loc = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(
            os.path.abspath(__file__)))), 'bin', 'debian-devel-changes.fifo')
        fr.start(self._email_callback, fifo_loc)

        self.queued_topics = {}
        self.last_n_messages = []

        # Schedule datasource updates
        for klass, interval, name in get_datasources():
            try:
                schedule.removePeriodicEvent(name)
            except KeyError:
                pass

            def wrapper(klass=klass):
                klass().update()
                self._topic_callback()

            schedule.addPeriodicEvent(wrapper, interval, name, now=False)
            schedule.addEvent(wrapper, time.time() + 1)

    def die(self):
        FifoReader().stop()
        for _, _, name in get_datasources():
            try:
                schedule.removePeriodicEvent(name)
            except KeyError:
                # A newly added event may not exist, ignore exception.
                pass

    def _email_callback(self, fileobj):
        try:
            email = parse_mail(fileobj)
            msg = get_message(email)

            if not msg:
                return

            txt = colourise(msg.for_irc())
            for channel in self.irc.state.channels:
                if txt in self.last_n_messages:
                    continue

                self.last_n_messages.insert(0, txt)
                self.last_n_messages = self.last_n_messages[:20]

                if self.registryValue('show_changes', channel):
                    ircmsg = supybot.ircmsgs.privmsg(channel, txt)
                    self.irc.queueMsg(ircmsg)

        except:
           log.exception('Uncaught exception')

    def _topic_callback(self):
        self.topic_lock.acquire()

        sections = {
            TestingRCBugs().get_num_bugs: 'RC bug count:',
            NewQueue().get_size: 'NEW queue:',
            RmQueue().get_size: 'RM queue:',
        }

        try:
            values = {}
            for callback, prefix in sections.iteritems():
                values[callback] = callback()

            for channel in self.irc.state.channels:
                new_topic = topic = self.irc.state.getTopic(channel)

                for callback, prefix in sections.iteritems():
                    if values[callback]:
                        new_topic = rewrite_topic(new_topic, prefix, values[callback])

                if topic != new_topic:
                    log.info("Queueing change of topic in #%s to '%s'" % (channel, new_topic))
                    self.queued_topics[channel] = new_topic

                    event_name = '%s_topic' % channel
                    try:
                        schedule.removeEvent(event_name)
                    except KeyError:
                        pass
                    schedule.addEvent(lambda channel=channel: self._update_topic(channel),
                        time.time() + 60, event_name)
        finally:
            self.topic_lock.release()

    def _update_topic(self, channel):
        self.topic_lock.acquire()
        try:
            try:
                new_topic = self.queued_topics[channel]
                log.info("Changing topic in #%s to '%s'" % (channel, new_topic))
                self.irc.queueMsg(supybot.ircmsgs.topic(channel, new_topic))
            except KeyError:
                pass
        finally:
            self.topic_lock.release()

    def morning(self, irc, msg, args):
        num_bugs = TestingRCBugs().get_num_bugs()
        if type(num_bugs) is not int:
            irc.reply("Good morning, %s!" % msg.name)
            return

        advice = random.choice((
            'Why not go and fix one?',
            'Why not peek at the list and find one?',
            'Stop blogging about fixing RC bugs and fix one.',
            'Stop IRCing and fix one.',
            'You realise they don\'t fix themselves, right?',
            'How about fixing yourself some caffeine and then poking at the bug list?',
        ))
        txt = "Good morning, %s! There are currently %d RC bugs in Lenny. %s" % \
            (msg.nick, num_bugs, advice)
        irc.reply(txt)
    morning = wrap(morning)

    def rc(self, irc, msg, args):
        num_bugs = TestingRCBugs().get_num_bugs()
        if type(num_bugs) is int:
            irc.reply("There are %d release-critical bugs in the testing distribution. " \
                "See http://bts.turmzimmer.net/details.php?bydist=lenny&igncontrib=on&ignnonfree=on" % num_bugs)
        else:
            irc.reply("No data at this time.")
    rc = wrap(rc)

    def update(self, irc, msg, args):
        if not ircdb.checkCapability(msg.prefix, 'owner'):
            irc.reply("You are not authorised to run this command.")
            return

        for klass, interval, name in get_datasources():
            klass().update()
            irc.reply("Updated %s." % name)
        self._topic_callback()
    update = wrap(update)

    def madison(self, irc, msg, args, package):
        try:
            lines = madison(package)
            if not lines:
                irc.reply('Did not get a response -- is "%s" a valid package?' % package)
                return

            field_styles = ('package', 'version', 'distribution', 'section')
            for line in lines:
                out = []
                fields = line.strip().split('|', len(field_styles))
                for style, data in zip(field_styles, fields):
                    out.append('[%s]%s' % (style, data))
                irc.reply(colourise('[reset]|'.join(out)), prefixNick=False)
        except Exception, e:
            irc.reply("Error: %s" % e.message)
    madison = wrap(madison, ['text'])

    def bug(self, irc, msg, args, bug_string):
        try:
            msg = bug_synopsis(bug_string)
            if msg:
                irc.reply(colourise(msg.for_irc()), prefixNick=False)
        except ValueError:
            irc.reply('Could not parse bug number')
        except Exception, e:
            irc.reply("Error: %s" % e.message)

    bug = wrap(bug, ['text'])

    def get_pool_url(self, package):
        if package.startswith('lib'):
            return (package[:4], package)
        else:
            return (package[:1], package)

    def _maintainer(self, irc, msg, args, items):
        for package in items:
            info = Maintainer().get_maintainer(package)
            if info:
                display_name = format_email_address("%s <%s>" % (info['name'], info['email']), max_domain=18)

                login = info['email']
                if login.endswith('@debian.org'):
                    login = login.replace('@debian.org', '')

                msg = "[desc]Maintainer for[reset] [package]%s[reset] [desc]is[reset] [by]%s[reset]: " % (package, display_name)
                msg += "[url]http://qa.debian.org/developer.php?login=%s[/url]" % login
            else:
                msg = 'Unknown source package "%s"' % package

            irc.reply(colourise(msg), prefixNick=False)
    maintainer = wrap(_maintainer, [many('anything')])
    maint = wrap(_maintainer, [many('anything')])
    who_maintains = wrap(_maintainer, [many('anything')])

    def _qa(self, irc, msg, args, items):
        for package in items:
            url = "http://packages.qa.debian.org/%s/%s.html" % self.get_pool_url(package)
            msg = "[desc]QA page for[reset] [package]%s[reset]: [url]%s[/url]" % (package, url)
            irc.reply(colourise(msg), prefixNick=False)
    qa = wrap(_qa, [many('anything')])
    overview = wrap(_qa, [many('anything')])
    package = wrap(_qa, [many('anything')])
    pkg = wrap(_qa, [many('anything')])
    srcpkg = wrap(_qa, [many('anything')])

    def _changelog(self, irc, msg, args, items):
        for package in items:
            url = "http://packages.debian.org/changelogs/pool/main/%s/%s/current/changelog" % self.get_pool_url(package)
            msg = "[desc]debian/changelog for[reset] [package]%s[reset]: [url]%s[/url]" % (package, url)
            irc.reply(colourise(msg), prefixNick=False)
    changelog = wrap(_changelog, [many('anything')])
    changes = wrap(_changelog, [many('anything')])

    def _copyright(self, irc, msg, args, items):
        for package in items:
            url = "http://packages.debian.org/changelogs/pool/main/%s/%s/current/copyright" % self.get_pool_url(package)
            msg = "[desc]debian/copyright for[reset] [package]%s[reset]: [url]%s[/url]" % (package, url)
            irc.reply(colourise(msg), prefixNick=False)
    copyright = wrap(_copyright, [many('anything')])

    def _buggraph(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Bug graph for[reset] [package]%s[reset]: [url]http://people.debian.org/~glandium/bts/%s/%s.png[/url]" % \
                (package, package[0], package)
            irc.reply(colourise(msg), prefixNick=False)
    buggraph = wrap(_buggraph, [many('anything')])
    bug_graph = wrap(_buggraph, [many('anything')])

    def _buildd(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]buildd status for[reset] [package]%s[reset]: [url]http://buildd.debian.org/pkg.cgi?pkg=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    buildd = wrap(_buildd, [many('anything')])

    def _buildde(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]experimental/backports.org buildd status for[reset] [package]%s[reset]: [url]http://experimental.ftbfs.de/build.php?pkg=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    buildde = wrap(_buildde, [many('anything')])
    builddb = wrap(_buildde, [many('anything')])
    experimental = wrap(_buildde, [many('anything')])
    backports = wrap(_buildde, [many('anything')])

    def _popcon(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Popcon statistics for[reset] [package]%s[reset]: [url]http://qa.debian.org/developer.php?popcon=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    popcon = wrap(_popcon, [many('anything')])

    def _testing(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Testing migration status for[reset] [package]%s[reset]: [url]http://release.debian.org/migration/testing.pl?package=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    testing = wrap(_testing, [many('anything')])
    migration = wrap(_testing, [many('anything')])

    def _dehs(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Debian External Health Status for[reset] [package]%s[reset]: [url]http://dehs.alioth.debian.org/report.php?package=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    dehs = wrap(_dehs, [many('anything')])
    health = wrap(_dehs, [many('anything')])

    def _swirl(self, irc, msg, args):
        swirl = [
            "  [brightred] ,''`.[reset]",
            "  [brightred]: :' :[reset]           [b]Debian GNU/Linux[/b]",
            "  [brightred]`. `' [reset]           [url]http://www.debian.org/[/url]",
            "  [brightred]  `-  [reset]",
        ]
        for line in swirl:
            irc.reply(colourise(line), prefixNick=False)
    swirl = wrap(_swirl)
    debian = wrap(_swirl)

    def _pas(self, irc, msg, args):
        line = "[desc]Packages-arch-specific[reset]: [url]http://cvs.debian.org/srcdep/Packages-arch-specific?root=dak&view=auto[/url]"
        irc.reply(colourise(line))
    pas = wrap(_pas)
    packages_arch_specific = wrap(_pas)
    not_for_us = wrap(_pas)
    nfu = wrap(_pas)

    def _new(self, irc, msg, args):
        line = "[desc]NEW queue is[reset]: [url]%s[/url]. [desc]Current size is:[reset] %d" % \
            (NewQueue().URL, NewQueue().get_size())
        irc.reply(colourise(line))
    new = wrap(_new)
    new_queue = wrap(_new)
    newqueue = wrap(_new)

Class = DebianDevelChanges
<commit_msg>Use prefixNick=false.<commit_after># -*- coding: utf-8 -*-
#
#   Debian Changes Bot
#   Copyright (C) 2008 Chris Lamb <chris@chris-lamb.co.uk>
#
#   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/>.

import os
import time
import random
import supybot
import threading

from supybot.commands import wrap, many
from supybot import ircdb, log, schedule

from btsutils.debbugs import BugExceptions

from DebianDevelChangesBot.mailparsers import get_message
from DebianDevelChangesBot.datasources import get_datasources, TestingRCBugs, \
    NewQueue, RmQueue, Maintainer
from DebianDevelChangesBot.utils import parse_mail, FifoReader, colourise, \
    rewrite_topic, madison, bug_synopsis, format_email_address

class DebianDevelChanges(supybot.callbacks.Plugin):
    threaded = True

    def __init__(self, irc):
        self.__parent = super(DebianDevelChanges, self)
        self.__parent.__init__(irc)
        self.irc = irc
        self.topic_lock = threading.Lock()

        fr = FifoReader()
        fifo_loc = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(
            os.path.abspath(__file__)))), 'bin', 'debian-devel-changes.fifo')
        fr.start(self._email_callback, fifo_loc)

        self.queued_topics = {}
        self.last_n_messages = []

        # Schedule datasource updates
        for klass, interval, name in get_datasources():
            try:
                schedule.removePeriodicEvent(name)
            except KeyError:
                pass

            def wrapper(klass=klass):
                klass().update()
                self._topic_callback()

            schedule.addPeriodicEvent(wrapper, interval, name, now=False)
            schedule.addEvent(wrapper, time.time() + 1)

    def die(self):
        FifoReader().stop()
        for _, _, name in get_datasources():
            try:
                schedule.removePeriodicEvent(name)
            except KeyError:
                # A newly added event may not exist, ignore exception.
                pass

    def _email_callback(self, fileobj):
        try:
            email = parse_mail(fileobj)
            msg = get_message(email)

            if not msg:
                return

            txt = colourise(msg.for_irc())
            for channel in self.irc.state.channels:
                if txt in self.last_n_messages:
                    continue

                self.last_n_messages.insert(0, txt)
                self.last_n_messages = self.last_n_messages[:20]

                if self.registryValue('show_changes', channel):
                    ircmsg = supybot.ircmsgs.privmsg(channel, txt)
                    self.irc.queueMsg(ircmsg)

        except:
           log.exception('Uncaught exception')

    def _topic_callback(self):
        self.topic_lock.acquire()

        sections = {
            TestingRCBugs().get_num_bugs: 'RC bug count:',
            NewQueue().get_size: 'NEW queue:',
            RmQueue().get_size: 'RM queue:',
        }

        try:
            values = {}
            for callback, prefix in sections.iteritems():
                values[callback] = callback()

            for channel in self.irc.state.channels:
                new_topic = topic = self.irc.state.getTopic(channel)

                for callback, prefix in sections.iteritems():
                    if values[callback]:
                        new_topic = rewrite_topic(new_topic, prefix, values[callback])

                if topic != new_topic:
                    log.info("Queueing change of topic in #%s to '%s'" % (channel, new_topic))
                    self.queued_topics[channel] = new_topic

                    event_name = '%s_topic' % channel
                    try:
                        schedule.removeEvent(event_name)
                    except KeyError:
                        pass
                    schedule.addEvent(lambda channel=channel: self._update_topic(channel),
                        time.time() + 60, event_name)
        finally:
            self.topic_lock.release()

    def _update_topic(self, channel):
        self.topic_lock.acquire()
        try:
            try:
                new_topic = self.queued_topics[channel]
                log.info("Changing topic in #%s to '%s'" % (channel, new_topic))
                self.irc.queueMsg(supybot.ircmsgs.topic(channel, new_topic))
            except KeyError:
                pass
        finally:
            self.topic_lock.release()

    def morning(self, irc, msg, args):
        num_bugs = TestingRCBugs().get_num_bugs()
        if type(num_bugs) is not int:
            irc.reply("Good morning, %s!" % msg.name)
            return

        advice = random.choice((
            'Why not go and fix one?',
            'Why not peek at the list and find one?',
            'Stop blogging about fixing RC bugs and fix one.',
            'Stop IRCing and fix one.',
            'You realise they don\'t fix themselves, right?',
            'How about fixing yourself some caffeine and then poking at the bug list?',
        ))
        txt = "Good morning, %s! There are currently %d RC bugs in Lenny. %s" % \
            (msg.nick, num_bugs, advice)
        irc.reply(txt, prefixNick=false)
    morning = wrap(morning)

    def rc(self, irc, msg, args):
        num_bugs = TestingRCBugs().get_num_bugs()
        if type(num_bugs) is int:
            irc.reply("There are %d release-critical bugs in the testing distribution. " \
                "See http://bts.turmzimmer.net/details.php?bydist=lenny&igncontrib=on&ignnonfree=on" % num_bugs)
        else:
            irc.reply("No data at this time.")
    rc = wrap(rc)

    def update(self, irc, msg, args):
        if not ircdb.checkCapability(msg.prefix, 'owner'):
            irc.reply("You are not authorised to run this command.")
            return

        for klass, interval, name in get_datasources():
            klass().update()
            irc.reply("Updated %s." % name)
        self._topic_callback()
    update = wrap(update)

    def madison(self, irc, msg, args, package):
        try:
            lines = madison(package)
            if not lines:
                irc.reply('Did not get a response -- is "%s" a valid package?' % package)
                return

            field_styles = ('package', 'version', 'distribution', 'section')
            for line in lines:
                out = []
                fields = line.strip().split('|', len(field_styles))
                for style, data in zip(field_styles, fields):
                    out.append('[%s]%s' % (style, data))
                irc.reply(colourise('[reset]|'.join(out)), prefixNick=False)
        except Exception, e:
            irc.reply("Error: %s" % e.message)
    madison = wrap(madison, ['text'])

    def bug(self, irc, msg, args, bug_string):
        try:
            msg = bug_synopsis(bug_string)
            if msg:
                irc.reply(colourise(msg.for_irc()), prefixNick=False)
        except ValueError:
            irc.reply('Could not parse bug number')
        except Exception, e:
            irc.reply("Error: %s" % e.message)

    bug = wrap(bug, ['text'])

    def get_pool_url(self, package):
        if package.startswith('lib'):
            return (package[:4], package)
        else:
            return (package[:1], package)

    def _maintainer(self, irc, msg, args, items):
        for package in items:
            info = Maintainer().get_maintainer(package)
            if info:
                display_name = format_email_address("%s <%s>" % (info['name'], info['email']), max_domain=18)

                login = info['email']
                if login.endswith('@debian.org'):
                    login = login.replace('@debian.org', '')

                msg = "[desc]Maintainer for[reset] [package]%s[reset] [desc]is[reset] [by]%s[reset]: " % (package, display_name)
                msg += "[url]http://qa.debian.org/developer.php?login=%s[/url]" % login
            else:
                msg = 'Unknown source package "%s"' % package

            irc.reply(colourise(msg), prefixNick=False)
    maintainer = wrap(_maintainer, [many('anything')])
    maint = wrap(_maintainer, [many('anything')])
    who_maintains = wrap(_maintainer, [many('anything')])

    def _qa(self, irc, msg, args, items):
        for package in items:
            url = "http://packages.qa.debian.org/%s/%s.html" % self.get_pool_url(package)
            msg = "[desc]QA page for[reset] [package]%s[reset]: [url]%s[/url]" % (package, url)
            irc.reply(colourise(msg), prefixNick=False)
    qa = wrap(_qa, [many('anything')])
    overview = wrap(_qa, [many('anything')])
    package = wrap(_qa, [many('anything')])
    pkg = wrap(_qa, [many('anything')])
    srcpkg = wrap(_qa, [many('anything')])

    def _changelog(self, irc, msg, args, items):
        for package in items:
            url = "http://packages.debian.org/changelogs/pool/main/%s/%s/current/changelog" % self.get_pool_url(package)
            msg = "[desc]debian/changelog for[reset] [package]%s[reset]: [url]%s[/url]" % (package, url)
            irc.reply(colourise(msg), prefixNick=False)
    changelog = wrap(_changelog, [many('anything')])
    changes = wrap(_changelog, [many('anything')])

    def _copyright(self, irc, msg, args, items):
        for package in items:
            url = "http://packages.debian.org/changelogs/pool/main/%s/%s/current/copyright" % self.get_pool_url(package)
            msg = "[desc]debian/copyright for[reset] [package]%s[reset]: [url]%s[/url]" % (package, url)
            irc.reply(colourise(msg), prefixNick=False)
    copyright = wrap(_copyright, [many('anything')])

    def _buggraph(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Bug graph for[reset] [package]%s[reset]: [url]http://people.debian.org/~glandium/bts/%s/%s.png[/url]" % \
                (package, package[0], package)
            irc.reply(colourise(msg), prefixNick=False)
    buggraph = wrap(_buggraph, [many('anything')])
    bug_graph = wrap(_buggraph, [many('anything')])

    def _buildd(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]buildd status for[reset] [package]%s[reset]: [url]http://buildd.debian.org/pkg.cgi?pkg=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    buildd = wrap(_buildd, [many('anything')])

    def _buildde(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]experimental/backports.org buildd status for[reset] [package]%s[reset]: [url]http://experimental.ftbfs.de/build.php?pkg=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    buildde = wrap(_buildde, [many('anything')])
    builddb = wrap(_buildde, [many('anything')])
    experimental = wrap(_buildde, [many('anything')])
    backports = wrap(_buildde, [many('anything')])

    def _popcon(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Popcon statistics for[reset] [package]%s[reset]: [url]http://qa.debian.org/developer.php?popcon=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    popcon = wrap(_popcon, [many('anything')])

    def _testing(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Testing migration status for[reset] [package]%s[reset]: [url]http://release.debian.org/migration/testing.pl?package=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    testing = wrap(_testing, [many('anything')])
    migration = wrap(_testing, [many('anything')])

    def _dehs(self, irc, msg, args, items):
        for package in items:
            msg = "[desc]Debian External Health Status for[reset] [package]%s[reset]: [url]http://dehs.alioth.debian.org/report.php?package=%s[/url]" % \
                (package, package)
            irc.reply(colourise(msg), prefixNick=False)
    dehs = wrap(_dehs, [many('anything')])
    health = wrap(_dehs, [many('anything')])

    def _swirl(self, irc, msg, args):
        swirl = [
            "  [brightred] ,''`.[reset]",
            "  [brightred]: :' :[reset]           [b]Debian GNU/Linux[/b]",
            "  [brightred]`. `' [reset]           [url]http://www.debian.org/[/url]",
            "  [brightred]  `-  [reset]",
        ]
        for line in swirl:
            irc.reply(colourise(line), prefixNick=False)
    swirl = wrap(_swirl)
    debian = wrap(_swirl)

    def _pas(self, irc, msg, args):
        line = "[desc]Packages-arch-specific[reset]: [url]http://cvs.debian.org/srcdep/Packages-arch-specific?root=dak&view=auto[/url]"
        irc.reply(colourise(line))
    pas = wrap(_pas)
    packages_arch_specific = wrap(_pas)
    not_for_us = wrap(_pas)
    nfu = wrap(_pas)

    def _new(self, irc, msg, args):
        line = "[desc]NEW queue is[reset]: [url]%s[/url]. [desc]Current size is:[reset] %d" % \
            (NewQueue().URL, NewQueue().get_size())
        irc.reply(colourise(line))
    new = wrap(_new)
    new_queue = wrap(_new)
    newqueue = wrap(_new)

Class = DebianDevelChanges
<|endoftext|>