<commit_before>import requests
import json
import ConfigParser
import sys
import getopt
from urlparse import urlparse

application_key = ""
auth_token = ""
gtd_board_id = ""

def get_cards_in_list(board_id, list_name):
    # Get a list of Lists on the board
    response = requests.get('https://api.trello.com/1/boards/' + board_id + '/lists?cards=none&key=' + application_key + '&token=' + auth_token)

    lists_json = response.json();

    # TODO: handle failed response

    # Find the named list
    list_id = None
    for l in lists_json:
        if l['name'] == list_name:
            list_id = l['id']
            break

    # TODO: handle missing list

    # List the cards on that list
    response = requests.get('https://api.trello.com/1/lists/' + list_id + '/cards?key=' + application_key + '&token=' + auth_token)

    # TODO: handle failed response

    return response.json()

def get_next_action_list():
    next_action_list = []
    error_list = []

    project_card_list = get_cards_in_list(gtd_board_id, 'Projects')

    for project_card in project_card_list:
        next_action_text = project_card['name'] + ' - '
        try:
            # The description of each card should contain the URL
            url = project_card['desc']

            # Parse the URL to get the short link
            url_bits = urlparse(url)
            # URLs all seem to be of the form /x/xyz123/nice-description
            path_bits = url_bits.path.split('/')
            short_id = path_bits[2]
            todo_card_list = get_cards_in_list(short_id, 'Todo')
            next_action_card = todo_card_list[0]
            next_action_text += next_action_card['name']

            next_action_list.append(next_action_text)
        except:
            error_list.append("Failed to determine next action for '" + project_card['name'] + "'")

    # Now return all the non-project Next Actions so that there's a consolidated list
    next_action_card_list = get_cards_in_list(gtd_board_id, 'Next Actions')

    for next_action_card in next_action_card_list:
        next_action_list.append(next_action_card['name'])

    return next_action_list, error_list

def print_error_and_exit(message):
    sys.stderr.write(message + "\n")
    sys.exit(1)

def load_config(config_name):
    global application_key
    global auth_token
    global gtd_board_id

    config = ConfigParser.ConfigParser()
    config.read(".trellonextactions")

    gtd_board_id = config.get(config_name, 'board_id')
    application_key = config.get(config_name, 'application_key')
    auth_token = config.get(config_name, 'auth_token')

def print_list(name, card_list):
    print name + ":"
    print
    for c in card_list:
        print " [ ] " + c
    print

def main():
    config_name = 'default'
    action = 'list'

    try:
        opts, args = getopt.getopt(sys.argv[1:], "" ,["config="])
        for opt, arg in opts:
            if opt == '--config':
                config_name = arg
    except getopt.GetoptError as e:
        print_error_and_exit(str(e))

    try:
        load_config(config_name)
    except:
        print_error_and_exit("Failed to load config '" + config_name + "'")

    if action == 'list':
        next_action_list, error_list = get_next_action_list()

        print_list('Next Actions', next_action_list)
        if (len(error_list) > 0):
            print_list('Errors', error_list)
    else:
        print_error_and_exit("Unrecognised action '" + action + "'")

if __name__ == '__main__':
    sys.exit(main())
<commit_msg>Finished code tidy-up and error handling<commit_after>import requests
import json
import ConfigParser
import sys
import getopt
from urlparse import urlparse

application_key = ""
auth_token = ""
gtd_board_id = ""

def print_error_and_exit(message):
    sys.stderr.write(message + "\n")
    sys.exit(1)

def trello_api_request(url):
    try:
        response = requests.get(url)
    except:
        print_error_and_exit("Failed API request to " + url)

    if response.status_code != 200:
        print_error_and_exit("HTTP " + str(response.status_code) + " response from " + url)

    try:
        json = response.json()
    except:
        print_error_and_exit("Could not parse JSON response from " + url)

    return json

def get_cards_in_list(board_id, list_name):
    lists_on_board = trello_api_request('https://api.trello.com/1/boards/' + board_id + '/lists?cards=none&key=' + application_key + '&token=' + auth_token)

    # Find the named list
    list_id = None
    for l in lists_on_board:
        if l['name'] == list_name:
            list_id = l['id']
            break

    if list_id == None:
        raise ValueError("No list with name '" + list_name + "' found")

    # List the cards on that list
    cards_in_list = trello_api_request('https://api.trello.com/1/lists/' + list_id + '/cards?key=' + application_key + '&token=' + auth_token)

    return cards_in_list

def get_next_action_list():
    next_action_list = []
    error_list = []

    try:
        project_card_list = get_cards_in_list(gtd_board_id, 'Projects')
    except ValueError as e:
        print_error_and_exit(str(e))

    for project_card in project_card_list:
        next_action_text = project_card['name'] + ' - '
        try:
            # The description of each card should contain the URL
            url = project_card['desc']

            # Parse the URL to get the short link
            url_bits = urlparse(url)
            # URLs all seem to be of the form /x/xyz123/nice-description
            path_bits = url_bits.path.split('/')
            short_id = path_bits[2]
            todo_card_list = get_cards_in_list(short_id, 'Todo')

            if len(todo_card_list) > 0:
                next_action_card = todo_card_list[0]
                next_action_text += next_action_card['name']
                next_action_list.append(next_action_text)
            else:
                error_list.append(project_card['name'] + " - Todo list is empty")
        except ValueError as e:
            error_list.append(project_card['name'] + " - " + str(e))

    # Now return all the non-project Next Actions so that there's a consolidated list
    next_action_card_list = get_cards_in_list(gtd_board_id, 'Next Actions')

    for next_action_card in next_action_card_list:
        next_action_list.append(next_action_card['name'])

    return next_action_list, error_list

def load_config(config_name):
    global application_key
    global auth_token
    global gtd_board_id

    config = ConfigParser.ConfigParser()
    config.read(".trellonextactions")

    gtd_board_id = config.get(config_name, 'board_id')
    application_key = config.get(config_name, 'application_key')
    auth_token = config.get(config_name, 'auth_token')

def print_list(name, card_list):
    print name + ":"
    print
    for c in card_list:
        print " [ ] " + c
    print

def main():
    config_name = 'default'
    action = 'list'

    try:
        opts, args = getopt.getopt(sys.argv[1:], "" ,["config="])
        for opt, arg in opts:
            if opt == '--config':
                config_name = arg
    except getopt.GetoptError as e:
        print_error_and_exit(str(e))

    try:
        load_config(config_name)
    except:
        print_error_and_exit("Failed to load config '" + config_name + "'")

    if action == 'list':
        next_action_list, error_list = get_next_action_list()

        print_list('Next Actions', next_action_list)
        if (len(error_list) > 0):
            print_list('Errors', error_list)
    else:
        print_error_and_exit("Unrecognised action '" + action + "'")

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


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

from django.shortcuts import get_object_or_404, render, redirect
from django.template import RequestContext
from django.core.context_processors import csrf
from django.views.decorators.csrf import csrf_exempt
from django.http import Http404, HttpResponse, HttpResponseForbidden, HttpResponseNotFound
from django.utils.encoding import smart_str
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.db import connections
from django.core.paginator import InvalidPage, EmptyPage, Paginator, PageNotAnInteger
from django.core.cache import cache
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import now

from generic.datatables import generic_list_json

from units.models import Accreditation, AccreditationLog
from app.utils import update_current_unit, get_current_unit
from app.ldaputils import get_attrs_of_sciper
from users.models import TruffeUser

@login_required
def accreds_list(request):
    """Display the list of accreds"""

    from units.models import Unit

    main_unit = Unit.objects.get(pk=settings.ROOT_UNIT_PK)

    main_unit.set_rights_can_select(lambda unit: Accreditation.static_rights_can('LIST', request.user, unit))
    main_unit.set_rights_can_edit(lambda unit: Accreditation.static_rights_can('CREATE', request.user, unit))
    main_unit.check_if_can_use_hidden(request.user)

    if request.GET.get('upk'):
        update_current_unit(request, request.GET.get('upk'))

    can_edit = Accreditation.static_rights_can('CREATE', request.user, get_current_unit(request))

    return render(request, 'units/accreds/list.html', {'main_unit': main_unit, 'can_edit': can_edit})

@login_required
@csrf_exempt
def accreds_list_json(request):
    """Display the list of accreds, json call for the list"""

    # Update current unit
    update_current_unit(request, request.GET.get('upk'))

    unit = get_current_unit(request)

    # Check unit access
    if not Accreditation.static_rights_can('LIST', request.user, unit):
        raise Http404

    # Filter by unit
    filter_ = lambda x: x.filter(unit=unit)

    # Si pas le droit de créer, filtrage des accreds invisibles
    if not Accreditation.static_rights_can('CREATE', request.user, get_current_unit(request)):
        filter__ = lambda x: x.filter(hidden_in_truffe=False)
    else:
        filter__ = lambda x: x

    # Filter old accreds, if needed
    if request.GET.get('h', '0') == '0':
        filter2 = lambda x: filter_(filter__(x)).filter(end_date=None)
    else:
        filter2 = lambda x: filter_(filter__(x))

    return generic_list_json(request, Accreditation, ['pk', 'user', 'get_role_or_display_name', 'start_date', 'no_epfl_sync', 'hidden_in_epfl', 'hidden_in_truffe', 'renewal_date', 'pk'], 'units/accreds/list_json.html', filter_fields=['user__first_name', 'user__last_name', 'role__name'], bonus_filter_function=filter2, columns_mapping={'get_role_or_display_name': 'role__name', 'user': 'user__first_name'})

@login_required
def accreds_logs_list(request):
    """Display the list of accreds"""

    from units.models import Unit

    main_unit = Unit.objects.get(pk=settings.ROOT_UNIT_PK)

    main_unit.set_rights_can_select(lambda unit: Accreditation.static_rights_can('LIST', request.user, unit))
    main_unit.set_rights_can_edit(lambda unit: Accreditation.static_rights_can('CREATE', request.user, unit))
    main_unit.check_if_can_use_hidden(request.user)

    if request.GET.get('upk'):
        update_current_unit(request, request.GET.get('upk'))

    return render(request, 'units/accreds/logs_list.html', {'main_unit': main_unit})

@login_required
@csrf_exempt
def accreds_logs_list_json(request):
    """Display the list of accreds, json call for the list"""

    # Update current unit
    update_current_unit(request, request.GET.get('upk'))

    unit = get_current_unit(request)

    # Check unit access
    if not Accreditation.static_rights_can('LIST', request.user, unit):
        raise Http404

    # Filter by unit
    filter_ = lambda x: x.filter(accreditation__unit=unit)

    # Si pas le droit de créer, filtrage des accreds invisibles
    if not Accreditation.static_rights_can('CREATE', request.user, get_current_unit(request)):
        filter__ = lambda x: x.filter(accreditation__hidden_in_truffe=False)
    else:
        filter__ = lambda x: x

    filter2 = lambda x: filter_(filter__(x))

    return generic_list_json(request, AccreditationLog, ['pk', 'accreditation__user', 'type', 'when', 'what'], 'units/accreds/logs_list_json.html', filter_fields=['accreditation__user__first_name', 'accreditation__user__last_name', 'accreditation__role__name', 'who__first_name', 'who__last_name'], bonus_filter_function=filter2, columns_mapping={'pk': 'accreditation__user__first_name'})

@login_required
def accreds_renew(request, pk):
    """Renew an accreds"""

    accreds = [get_object_or_404(Accreditation, pk=pk_, end_date=None) for pk_ in filter(lambda x: x, pk.split(','))]

    multi_obj = len(accreds) > 1

    for accred in accreds:
        if not accred.rights_can('EDIT', request.user):
            raise Http404

    if request.method == 'POST':
        for accred in accreds:
            accred.renewal_date = now()
            accred.save()

            AccreditationLog(accreditation=accred, who=request.user, type='renewed').save()

        if multi_obj:
            messages.success(request, _(u'Accréditations renouvelées !'))
        else:
            messages.success(request, _(u'Accréditation renouvelée !'))

        return redirect('units.views.accreds_list')

    return render(request, 'units/accreds/renew.html', {'accreds': accreds, 'multi_obj': multi_obj})

@login_required
def accreds_edit(request, pk):

    accred = get_object_or_404(Accreditation, pk=pk)

    base_role = accred.role
    old_accred_data = accred.__dict__.copy()

    if not accred.rights_can('EDIT', request.user):
        raise Http404

    from units.forms2 import AccreditationEditForm
    from units.models import Role

    done = False
    cannot_last_prez = False

    if request.method == 'POST':  # If the form has been submitted...
        form = AccreditationEditForm(request.POST, instance=accred)

        if form.is_valid():  # If the form is valid

            if base_role.pk == settings.PRESIDENT_ROLE_PK and not accred.rights_can('INGORE_PREZ', request.user) and accred.unit.accreditation_set.filter(role__pk=settings.PRESIDENT_ROLE_PK, end_date=None).count() <= 1 and form.cleaned_data['role'].pk != settings.PRESIDENT_ROLE_PK:
                cannot_last_prez = True
            else:

                accred = form.save(commit=False)

                if accred.role.pk != base_role.pk:
                    # On termine l'accrédiation

                    old_accred = get_object_or_404(Accreditation, pk=pk)
                    old_accred.end_date = now()
                    old_accred.need_validation = False
                    old_accred.save()

                    AccreditationLog(accreditation=old_accred, who=request.user, type='deleted').save()

                    # Et on clone la nouvelle
                    accred.pk = None
                    accred.end_date = None
                    accred.need_validation = False
                    accred.save()
                    accred.check_if_validation_needed(request)

                    accred.user.clear_rights_cache()

                    AccreditationLog(accreditation=accred, who=request.user, type='created').save()

                else:
                    changes = ""  # NB: Pas traduit, au cas ou besion de parsing

                    if accred.display_name != old_accred_data['display_name']:
                        changes += "DisplayName \"%s\" -> \"%s\"\n" % (old_accred_data['display_name'], accred.display_name,)

                    if accred.no_epfl_sync != old_accred_data['no_epfl_sync']:
                        if accred.no_epfl_sync:
                            changes += 'Now NoEpflSync\n'
                        else:
                            changes += 'Now EpflSync\n'

                    if accred.hidden_in_epfl != old_accred_data['hidden_in_epfl']:
                        if accred.hidden_in_epfl:
                            changes += 'Now EpflHidden\n'
                        else:
                            changes += 'Now EpflShown\n'

                    if accred.hidden_in_truffe != old_accred_data['hidden_in_truffe']:
                        if accred.hidden_in_truffe:
                            changes += 'Now TruffeHidden\n'
                        else:
                            changes += 'Now TruffeShown\n'

                    AccreditationLog(accreditation=accred, who=request.user, type='edited', what=changes).save()

                accred.save()

                accred.user.clear_rights_cache()

                messages.success(request, _(u'Accréditation sauvegardée !'))

                done = True

    else:
        form = AccreditationEditForm(instance=accred)

    validables = Role.objects.filter(deleted=False, need_validation=True)

    return render(request, 'units/accreds/edit.html', {'form': form, 'done': done, 'cannot_last_prez': cannot_last_prez, 'validables': validables})

@login_required
def accreds_delete(request, pk):
    """Delete an accred"""

    accreds = [get_object_or_404(Accreditation, pk=pk_, end_date=None) for pk_ in filter(lambda x: x, pk.split(','))]

    multi_obj = len(accreds) > 1

    cannot_last_prez = False
    cannot_last_prez_accred = None

    for accred in accreds:

        if not accred.rights_can('DELETE', request.user):
            raise Http404

        if accred.role.pk == settings.PRESIDENT_ROLE_PK and not accred.rights_can('INGORE_PREZ', request.user) and accred.unit.accreditation_set.filter(role__pk=settings.PRESIDENT_ROLE_PK, end_date=None).count() <= 1:
            cannot_last_prez = True
            cannot_last_prez_accred = accred

    if not cannot_last_prez and request.method == 'POST':

        for accred in accreds:
            accred.end_date = now()
            accred.save()

            AccreditationLog(accreditation=accred, who=request.user, type='deleted').save()

            accred.user.clear_rights_cache()

        if multi_obj:
            messages.success(request, _(u'Accréditations supprimées !'))
        else:
            messages.success(request, _(u'Accréditation supprimée !'))

        return redirect('units.views.accreds_list')

    return render(request, 'units/accreds/delete.html', {'accreds': accreds, 'cannot_last_prez': cannot_last_prez, 'multi_obj': multi_obj, 'cannot_last_prez_accred': cannot_last_prez_accred})

@login_required
def accreds_validate(request, pk):
    """Validate an accred"""

    accreds = [get_object_or_404(Accreditation, pk=pk_, end_date=None) for pk_ in filter(lambda x: x, pk.split(','))]

    multi_obj = len(accreds) > 1

    for accred in accreds:
        if not accred.rights_can('VALIDATE', request.user):
            raise Http404

    if request.method == 'POST':

        for accred in accreds:
            accred.need_validation = False
            accred.save()

            accred.user.clear_rights_cache()

            AccreditationLog(accreditation=accred, who=request.user, type='validated').save()

            from notifications.utils import notify_people
            dest_users = accred.unit.users_with_access('ACCREDITATION', no_parent=True)
            notify_people(request, 'Accreds.Validated', 'accreds_validated', accred, dest_users)

        if multi_obj:
            messages.success(request, _(u'Accréditations validées !'))
        else:
            messages.success(request, _(u'Accréditation validée !'))

        return redirect('units.views.accreds_list')

    return render(request, 'units/accreds/validate.html', {'accreds': accreds, 'multi_obj': multi_obj})

@login_required
def accreds_add(request):

    update_current_unit(request, request.GET.get('upk'))
    unit = get_current_unit(request)

    if not Accreditation.static_rights_can('CREATE', request.user, unit):
        raise Http404

    from units.forms2 import AccreditationAddForm
    from units.models import Role

    done = False

    if request.method == 'POST':  # If the form has been submitted...
        form = AccreditationAddForm(request.user, request.POST)

        if form.is_valid():  # If the form is valid
            accred = form.save(commit=False)

            accred.unit = unit

            # Try to find the user. If he dosen't exists, create it.
            try:
                user = TruffeUser.objects.get(username=form.cleaned_data['user'].strip())
            except TruffeUser.DoesNotExist:
                user = TruffeUser()

                user.username = form.cleaned_data['user'].strip()

                user.last_name, user.first_name, user.email = get_attrs_of_sciper(user.username)

                user.is_active = True

                user.save()

            accred.user = user
            accred.save()

            AccreditationLog(accreditation=accred, who=request.user, type='created').save()

            # Check if validation is needed
            accred.check_if_validation_needed(request)
            accred.save()

            accred.user.clear_rights_cache()

            messages.success(request, _(u'Accréditation sauvegardée !'))

            done = True

    else:
        form = AccreditationAddForm(request.user)

    validables = Role.objects.filter(deleted=False, need_validation=True)

    return render(request, 'units/accreds/add.html', {'form': form, 'done': done, 'unit': unit, 'validables': validables})
<commit_msg>Order role accreds<commit_after># -*- coding: utf-8 -*-

from django.shortcuts import get_object_or_404, render, redirect
from django.template import RequestContext
from django.core.context_processors import csrf
from django.views.decorators.csrf import csrf_exempt
from django.http import Http404, HttpResponse, HttpResponseForbidden, HttpResponseNotFound
from django.utils.encoding import smart_str
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.db import connections
from django.core.paginator import InvalidPage, EmptyPage, Paginator, PageNotAnInteger
from django.core.cache import cache
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import now

from generic.datatables import generic_list_json

from units.models import Accreditation, AccreditationLog
from app.utils import update_current_unit, get_current_unit
from app.ldaputils import get_attrs_of_sciper
from users.models import TruffeUser

@login_required
def accreds_list(request):
    """Display the list of accreds"""

    from units.models import Unit

    main_unit = Unit.objects.get(pk=settings.ROOT_UNIT_PK)

    main_unit.set_rights_can_select(lambda unit: Accreditation.static_rights_can('LIST', request.user, unit))
    main_unit.set_rights_can_edit(lambda unit: Accreditation.static_rights_can('CREATE', request.user, unit))
    main_unit.check_if_can_use_hidden(request.user)

    if request.GET.get('upk'):
        update_current_unit(request, request.GET.get('upk'))

    can_edit = Accreditation.static_rights_can('CREATE', request.user, get_current_unit(request))

    return render(request, 'units/accreds/list.html', {'main_unit': main_unit, 'can_edit': can_edit})

@login_required
@csrf_exempt
def accreds_list_json(request):
    """Display the list of accreds, json call for the list"""

    # Update current unit
    update_current_unit(request, request.GET.get('upk'))

    unit = get_current_unit(request)

    # Check unit access
    if not Accreditation.static_rights_can('LIST', request.user, unit):
        raise Http404

    # Filter by unit
    filter_ = lambda x: x.filter(unit=unit)

    # Si pas le droit de créer, filtrage des accreds invisibles
    if not Accreditation.static_rights_can('CREATE', request.user, get_current_unit(request)):
        filter__ = lambda x: x.filter(hidden_in_truffe=False)
    else:
        filter__ = lambda x: x

    # Filter old accreds, if needed
    if request.GET.get('h', '0') == '0':
        filter2 = lambda x: filter_(filter__(x)).filter(end_date=None)
    else:
        filter2 = lambda x: filter_(filter__(x))

    return generic_list_json(request, Accreditation, ['pk', 'user', 'get_role_or_display_name', 'start_date', 'no_epfl_sync', 'hidden_in_epfl', 'hidden_in_truffe', 'renewal_date', 'pk'], 'units/accreds/list_json.html', filter_fields=['user__first_name', 'user__last_name', 'role__name'], bonus_filter_function=filter2, columns_mapping={'get_role_or_display_name': 'role__ordre', 'user': 'user__first_name'})

@login_required
def accreds_logs_list(request):
    """Display the list of accreds"""

    from units.models import Unit

    main_unit = Unit.objects.get(pk=settings.ROOT_UNIT_PK)

    main_unit.set_rights_can_select(lambda unit: Accreditation.static_rights_can('LIST', request.user, unit))
    main_unit.set_rights_can_edit(lambda unit: Accreditation.static_rights_can('CREATE', request.user, unit))
    main_unit.check_if_can_use_hidden(request.user)

    if request.GET.get('upk'):
        update_current_unit(request, request.GET.get('upk'))

    return render(request, 'units/accreds/logs_list.html', {'main_unit': main_unit})

@login_required
@csrf_exempt
def accreds_logs_list_json(request):
    """Display the list of accreds, json call for the list"""

    # Update current unit
    update_current_unit(request, request.GET.get('upk'))

    unit = get_current_unit(request)

    # Check unit access
    if not Accreditation.static_rights_can('LIST', request.user, unit):
        raise Http404

    # Filter by unit
    filter_ = lambda x: x.filter(accreditation__unit=unit)

    # Si pas le droit de créer, filtrage des accreds invisibles
    if not Accreditation.static_rights_can('CREATE', request.user, get_current_unit(request)):
        filter__ = lambda x: x.filter(accreditation__hidden_in_truffe=False)
    else:
        filter__ = lambda x: x

    filter2 = lambda x: filter_(filter__(x))

    return generic_list_json(request, AccreditationLog, ['pk', 'accreditation__user', 'type', 'when', 'what'], 'units/accreds/logs_list_json.html', filter_fields=['accreditation__user__first_name', 'accreditation__user__last_name', 'accreditation__role__name', 'who__first_name', 'who__last_name'], bonus_filter_function=filter2, columns_mapping={'pk': 'accreditation__user__first_name'})

@login_required
def accreds_renew(request, pk):
    """Renew an accreds"""

    accreds = [get_object_or_404(Accreditation, pk=pk_, end_date=None) for pk_ in filter(lambda x: x, pk.split(','))]

    multi_obj = len(accreds) > 1

    for accred in accreds:
        if not accred.rights_can('EDIT', request.user):
            raise Http404

    if request.method == 'POST':
        for accred in accreds:
            accred.renewal_date = now()
            accred.save()

            AccreditationLog(accreditation=accred, who=request.user, type='renewed').save()

        if multi_obj:
            messages.success(request, _(u'Accréditations renouvelées !'))
        else:
            messages.success(request, _(u'Accréditation renouvelée !'))

        return redirect('units.views.accreds_list')

    return render(request, 'units/accreds/renew.html', {'accreds': accreds, 'multi_obj': multi_obj})

@login_required
def accreds_edit(request, pk):

    accred = get_object_or_404(Accreditation, pk=pk)

    base_role = accred.role
    old_accred_data = accred.__dict__.copy()

    if not accred.rights_can('EDIT', request.user):
        raise Http404

    from units.forms2 import AccreditationEditForm
    from units.models import Role

    done = False
    cannot_last_prez = False

    if request.method == 'POST':  # If the form has been submitted...
        form = AccreditationEditForm(request.POST, instance=accred)

        if form.is_valid():  # If the form is valid

            if base_role.pk == settings.PRESIDENT_ROLE_PK and not accred.rights_can('INGORE_PREZ', request.user) and accred.unit.accreditation_set.filter(role__pk=settings.PRESIDENT_ROLE_PK, end_date=None).count() <= 1 and form.cleaned_data['role'].pk != settings.PRESIDENT_ROLE_PK:
                cannot_last_prez = True
            else:

                accred = form.save(commit=False)

                if accred.role.pk != base_role.pk:
                    # On termine l'accrédiation

                    old_accred = get_object_or_404(Accreditation, pk=pk)
                    old_accred.end_date = now()
                    old_accred.need_validation = False
                    old_accred.save()

                    AccreditationLog(accreditation=old_accred, who=request.user, type='deleted').save()

                    # Et on clone la nouvelle
                    accred.pk = None
                    accred.end_date = None
                    accred.need_validation = False
                    accred.save()
                    accred.check_if_validation_needed(request)

                    accred.user.clear_rights_cache()

                    AccreditationLog(accreditation=accred, who=request.user, type='created').save()

                else:
                    changes = ""  # NB: Pas traduit, au cas ou besion de parsing

                    if accred.display_name != old_accred_data['display_name']:
                        changes += "DisplayName \"%s\" -> \"%s\"\n" % (old_accred_data['display_name'], accred.display_name,)

                    if accred.no_epfl_sync != old_accred_data['no_epfl_sync']:
                        if accred.no_epfl_sync:
                            changes += 'Now NoEpflSync\n'
                        else:
                            changes += 'Now EpflSync\n'

                    if accred.hidden_in_epfl != old_accred_data['hidden_in_epfl']:
                        if accred.hidden_in_epfl:
                            changes += 'Now EpflHidden\n'
                        else:
                            changes += 'Now EpflShown\n'

                    if accred.hidden_in_truffe != old_accred_data['hidden_in_truffe']:
                        if accred.hidden_in_truffe:
                            changes += 'Now TruffeHidden\n'
                        else:
                            changes += 'Now TruffeShown\n'

                    AccreditationLog(accreditation=accred, who=request.user, type='edited', what=changes).save()

                accred.save()

                accred.user.clear_rights_cache()

                messages.success(request, _(u'Accréditation sauvegardée !'))

                done = True

    else:
        form = AccreditationEditForm(instance=accred)

    validables = Role.objects.filter(deleted=False, need_validation=True)

    return render(request, 'units/accreds/edit.html', {'form': form, 'done': done, 'cannot_last_prez': cannot_last_prez, 'validables': validables})

@login_required
def accreds_delete(request, pk):
    """Delete an accred"""

    accreds = [get_object_or_404(Accreditation, pk=pk_, end_date=None) for pk_ in filter(lambda x: x, pk.split(','))]

    multi_obj = len(accreds) > 1

    cannot_last_prez = False
    cannot_last_prez_accred = None

    for accred in accreds:

        if not accred.rights_can('DELETE', request.user):
            raise Http404

        if accred.role.pk == settings.PRESIDENT_ROLE_PK and not accred.rights_can('INGORE_PREZ', request.user) and accred.unit.accreditation_set.filter(role__pk=settings.PRESIDENT_ROLE_PK, end_date=None).count() <= 1:
            cannot_last_prez = True
            cannot_last_prez_accred = accred

    if not cannot_last_prez and request.method == 'POST':

        for accred in accreds:
            accred.end_date = now()
            accred.save()

            AccreditationLog(accreditation=accred, who=request.user, type='deleted').save()

            accred.user.clear_rights_cache()

        if multi_obj:
            messages.success(request, _(u'Accréditations supprimées !'))
        else:
            messages.success(request, _(u'Accréditation supprimée !'))

        return redirect('units.views.accreds_list')

    return render(request, 'units/accreds/delete.html', {'accreds': accreds, 'cannot_last_prez': cannot_last_prez, 'multi_obj': multi_obj, 'cannot_last_prez_accred': cannot_last_prez_accred})

@login_required
def accreds_validate(request, pk):
    """Validate an accred"""

    accreds = [get_object_or_404(Accreditation, pk=pk_, end_date=None) for pk_ in filter(lambda x: x, pk.split(','))]

    multi_obj = len(accreds) > 1

    for accred in accreds:
        if not accred.rights_can('VALIDATE', request.user):
            raise Http404

    if request.method == 'POST':

        for accred in accreds:
            accred.need_validation = False
            accred.save()

            accred.user.clear_rights_cache()

            AccreditationLog(accreditation=accred, who=request.user, type='validated').save()

            from notifications.utils import notify_people
            dest_users = accred.unit.users_with_access('ACCREDITATION', no_parent=True)
            notify_people(request, 'Accreds.Validated', 'accreds_validated', accred, dest_users)

        if multi_obj:
            messages.success(request, _(u'Accréditations validées !'))
        else:
            messages.success(request, _(u'Accréditation validée !'))

        return redirect('units.views.accreds_list')

    return render(request, 'units/accreds/validate.html', {'accreds': accreds, 'multi_obj': multi_obj})

@login_required
def accreds_add(request):

    update_current_unit(request, request.GET.get('upk'))
    unit = get_current_unit(request)

    if not Accreditation.static_rights_can('CREATE', request.user, unit):
        raise Http404

    from units.forms2 import AccreditationAddForm
    from units.models import Role

    done = False

    if request.method == 'POST':  # If the form has been submitted...
        form = AccreditationAddForm(request.user, request.POST)

        if form.is_valid():  # If the form is valid
            accred = form.save(commit=False)

            accred.unit = unit

            # Try to find the user. If he dosen't exists, create it.
            try:
                user = TruffeUser.objects.get(username=form.cleaned_data['user'].strip())
            except TruffeUser.DoesNotExist:
                user = TruffeUser()

                user.username = form.cleaned_data['user'].strip()

                user.last_name, user.first_name, user.email = get_attrs_of_sciper(user.username)

                user.is_active = True

                user.save()

            accred.user = user
            accred.save()

            AccreditationLog(accreditation=accred, who=request.user, type='created').save()

            # Check if validation is needed
            accred.check_if_validation_needed(request)
            accred.save()

            accred.user.clear_rights_cache()

            messages.success(request, _(u'Accréditation sauvegardée !'))

            done = True

    else:
        form = AccreditationAddForm(request.user)

    validables = Role.objects.filter(deleted=False, need_validation=True)

    return render(request, 'units/accreds/add.html', {'form': form, 'done': done, 'unit': unit, 'validables': validables})
<|endoftext|>


<commit_before>from django.db import models

__all__ = ['VisibilityManagerMixin', 'VisibilityManager']

class VisibilityManagerMixin(object):
    """
    This manager should be used with a model that implements the Hideable
    mixin.
    """

    def __init__(self, *args, **kwargs):
        self.visible = kwargs.pop('visible', True)
        super().__init__(*args, **kwargs)

    def get_queryset(self):
        return super().get_queryset()
            .filter(hidden__isnull=self.visible)

class VisibilityManager(VisibilityManagerMixin, models.Manager):
    pass
<commit_msg>Changed .pop to [] to induce exception<commit_after>from django.db import models

__all__ = ['VisibilityManager', 'VisibilityManagerMixin']

class VisibilityManagerMixin(object):
    """
    This manager should be used with a model that implements the Hideable
    mixin.
    """

    def __init__(self, *args, **kwargs):
        self.visible = kwargs['visible']
        super().__init__(*args, **kwargs)

    def get_queryset(self):
        return super().get_queryset()
            .filter(hidden__isnull=self.visible)

class VisibilityManager(VisibilityManagerMixin, models.Manager):
    pass
<|endoftext|>


<commit_before>
import Adafruit_BluefruitLE
from Adafruit_BluefruitLE.services import UART as OriginalUART
# from ble import uart
from ble.uart import UART
from ble.readdata import Device
import time
import atexit
import logging
log = logging.getLogger(__name__)

class App (object):
  """ A high level application object.

  Any application needing to talk to Dexcom G4 + Share will need
  to perform operations to setup the ble data transport.  This class
  mixes the UART, ble code, and provides helpful prolog and epilog
  routines that run before and after main, respectively.
  """
  def __init__ (self, **kwds):
    self.disconnect_on_after = kwds.get('disconnect_on_after', False)
    pass
  def setup_ble (self):
    self.remote = None
    self.ble = Adafruit_BluefruitLE.get_provider()
    # Initialize the BLE system.  MUST be called before other BLE calls!
    self.ble.initialize()
    # Get the first available BLE network adapter and make sure it's powered on.
    self.adapter = self.ble.get_default_adapter()
    self.adapter.power_on()
    log.info('Using adapter: {0}'.format(self.adapter.name))
    self.dexcom = None
    pass
  def setup_dexcom (self, serial=None, mac=None):
    # Once connected do everything else in a try/finally to make sure the device
    # is disconnected when done.
    try:
        # Wait for service discovery to complete for the UART service.  Will
        # time out after 60 seconds (specify timeout_sec parameter to override).
        # print device._device.GattServices
        log.info('Discovering services...')
        UART.discover(self.remote)

        # Once service discovery is complete create an instance of the service
        # and start interacting with it.
        self.uart = UART(self.remote, SERIAL=serial)

        self.dexcom = Device(self.uart)
        # log.info("DEXCOM", self.dexcom)
        if not self.dexcom:
          self.dexcom = Device(self.uart)
    except:
        # Make sure device is disconnected on exit.
        if self.disconnect_on_after:
          self.remote.disconnect()
  def prolog (self, clear_cached_data=True, disconnect_devices=True, scan_devices=True, connect=True, mac=None):
    """
    Things to do before running the main part of the application.
    """
    # Clear any cached data because both bluez and CoreBluetooth have issues with
    # caching data and it going stale.
    if clear_cached_data:
      self.ble.clear_cached_data()

    if disconnect_devices:
      # Disconnect any currently connected UART devices.  Good for cleaning up and
      # starting from a fresh state.
      log.info('Disconnecting any connected UART devices...')
      UART.disconnect_devices()

    if scan_devices:
      # Scan for UART devices.
      log.info('Searching for UART device...')
      try:
          if mac:
            self.remote = self.select_mac(mac=mac)
          else:
            self.adapter.start_scan()
            # Search for the first UART device found (will time out after 60 seconds
            # but you can specify an optional timeout_sec parameter to change it).
            self.remote = UART.find_device()
          if self.remote is None:
              raise RuntimeError('Failed to find UART device!')
      finally:
          # Make sure scanning is stopped before exiting.
          if self.adapter.is_scanning:
            self.adapter.stop_scan()

    if connect and not self.remote.is_connected:
      log.info('Connecting to device...')
      self.remote.connect()  # Will time out after 60 seconds, specify timeout_sec parameter
                        # to change the timeout.
    log.info(self.remote.name)
    # device._device.Pair( )
    # log.info(self.ble._print_tree( ))
    for service in self.remote.list_services( ):
      log.info(service, service.uuid)
    log.info("ADVERTISED")
    log.info(self.remote.advertised)

    pass
  def select_mac (self, mac=None, **kwds):
    for device in self.enumerate_dexcoms(**kwds):
      if str(device.id) == mac:
        return device
  def enumerate_dexcoms (self, timeout_secs=10):
    self.adapter.start_scan()
    # Use atexit.register to call the adapter stop_scan function before quiting.
    # This is good practice for calling cleanup code in this main function as
    # a try/finally block might not be called since this is a background thread.
    def maybe_stop ( ):
      if self.adapter.is_scanning:
        self.adapter.stop_scan( )
    # atexit.register(maybe_stop)
    log.info('Searching for UART devices...')

    # print('Press Ctrl-C to quit (will take ~30 seconds on OSX).')
    # Enter a loop and print out whenever a new UART device is found.
    start = time.time( )
    now = time.time( )
    known_uarts = set()
    while (now - start) < timeout_secs:
        # Call UART.find_devices to get a list of any UART devices that
        # have been found.  This call will quickly return results and does
        # not wait for devices to appear.
        found = set(UART.find_devices())
        # Check for new devices that haven't been seen yet and print out
        # their name and ID (MAC address on Linux, GUID on OSX).
        new = found - known_uarts
        for device in new:
            log.info('Found UART: {0} [{1}]'.format(device.name, device.id))
        known_uarts.update(new)
        # Sleep for a second and see if new devices have appeared.
        time.sleep(1.0)
        now = time.time( )
    self.adapter.stop_scan( )
    return known_uarts

  def epilog (self):
    """
    Things to do after running the main part of the application.
    """
    # Make sure device is disconnected on exit.
    if self.disconnect_on_after and self.remote.is_connected:
      self.remote.disconnect()
    # self.ble._gobject_mainloop.quit( )
    pass
  def set_handler (self, handler):
    self.handler = handler
  def run (self):
    self.ble.run_mainloop_with(self.main)
    pass
  def main (self):
    """
    Subclasses should replace this method.
    """
<commit_msg>tweak logging<commit_after>
import Adafruit_BluefruitLE
from Adafruit_BluefruitLE.services import UART as OriginalUART
# from ble import uart
from ble.uart import UART
from ble.readdata import Device
import time
import atexit
import logging
log = logging.getLogger(__name__)

class App (object):
  """ A high level application object.

  Any application needing to talk to Dexcom G4 + Share will need
  to perform operations to setup the ble data transport.  This class
  mixes the UART, ble code, and provides helpful prolog and epilog
  routines that run before and after main, respectively.
  """
  def __init__ (self, **kwds):
    self.disconnect_on_after = kwds.get('disconnect_on_after', False)
    pass
  def setup_ble (self):
    self.remote = None
    self.ble = Adafruit_BluefruitLE.get_provider()
    # Initialize the BLE system.  MUST be called before other BLE calls!
    self.ble.initialize()
    # Get the first available BLE network adapter and make sure it's powered on.
    self.adapter = self.ble.get_default_adapter()
    self.adapter.power_on()
    log.info('Using adapter: {0}'.format(self.adapter.name))
    self.dexcom = None
    pass
  def setup_dexcom (self, serial=None, mac=None):
    # Once connected do everything else in a try/finally to make sure the device
    # is disconnected when done.
    try:
        # Wait for service discovery to complete for the UART service.  Will
        # time out after 60 seconds (specify timeout_sec parameter to override).
        # print device._device.GattServices
        log.info('Discovering services...')
        UART.discover(self.remote)

        # Once service discovery is complete create an instance of the service
        # and start interacting with it.
        self.uart = UART(self.remote, SERIAL=serial)

        self.dexcom = Device(self.uart)
        # log.info("DEXCOM", self.dexcom)
        if not self.dexcom:
          self.dexcom = Device(self.uart)
    except:
        # Make sure device is disconnected on exit.
        if self.disconnect_on_after:
          self.remote.disconnect()
  def prolog (self, clear_cached_data=True, disconnect_devices=True, scan_devices=True, connect=True, mac=None):
    """
    Things to do before running the main part of the application.
    """
    # Clear any cached data because both bluez and CoreBluetooth have issues with
    # caching data and it going stale.
    if clear_cached_data:
      self.ble.clear_cached_data()

    if disconnect_devices:
      # Disconnect any currently connected UART devices.  Good for cleaning up and
      # starting from a fresh state.
      log.info('Disconnecting any connected UART devices...')
      UART.disconnect_devices()

    if scan_devices:
      # Scan for UART devices.
      log.info('Searching for UART device...')
      try:
          if mac:
            self.remote = self.select_mac(mac=mac)
          else:
            self.adapter.start_scan()
            # Search for the first UART device found (will time out after 60 seconds
            # but you can specify an optional timeout_sec parameter to change it).
            self.remote = UART.find_device()
          if self.remote is None:
              raise RuntimeError('Failed to find UART device!')
      finally:
          # Make sure scanning is stopped before exiting.
          if self.adapter.is_scanning:
            self.adapter.stop_scan()

    if connect and not self.remote.is_connected:
      log.info('Connecting to device...')
      self.remote.connect()  # Will time out after 60 seconds, specify timeout_sec parameter
                        # to change the timeout.
    log.info(self.remote.name)
    # device._device.Pair( )
    # log.info(self.ble._print_tree( ))
    for service in self.remote.list_services( ):
      log.info("services: %s %s", service, service.uuid)
    log.info("ADVERTISED")
    log.info(self.remote.advertised)

    pass
  def select_mac (self, mac=None, **kwds):
    for device in self.enumerate_dexcoms(**kwds):
      if str(device.id) == mac:
        return device
  def enumerate_dexcoms (self, timeout_secs=10):
    self.adapter.start_scan()
    # Use atexit.register to call the adapter stop_scan function before quiting.
    # This is good practice for calling cleanup code in this main function as
    # a try/finally block might not be called since this is a background thread.
    def maybe_stop ( ):
      if self.adapter.is_scanning:
        self.adapter.stop_scan( )
    # atexit.register(maybe_stop)
    log.info('Searching for UART devices...')

    # print('Press Ctrl-C to quit (will take ~30 seconds on OSX).')
    # Enter a loop and print out whenever a new UART device is found.
    start = time.time( )
    now = time.time( )
    known_uarts = set()
    while (now - start) < timeout_secs:
        # Call UART.find_devices to get a list of any UART devices that
        # have been found.  This call will quickly return results and does
        # not wait for devices to appear.
        found = set(UART.find_devices())
        # Check for new devices that haven't been seen yet and print out
        # their name and ID (MAC address on Linux, GUID on OSX).
        new = found - known_uarts
        for device in new:
            log.info('Found UART: {0} [{1}]'.format(device.name, device.id))
        known_uarts.update(new)
        # Sleep for a second and see if new devices have appeared.
        time.sleep(1.0)
        now = time.time( )
    self.adapter.stop_scan( )
    return known_uarts

  def epilog (self):
    """
    Things to do after running the main part of the application.
    """
    # Make sure device is disconnected on exit.
    if self.disconnect_on_after and self.remote.is_connected:
      self.remote.disconnect()
    # self.ble._gobject_mainloop.quit( )
    pass
  def set_handler (self, handler):
    self.handler = handler
  def run (self):
    self.ble.run_mainloop_with(self.main)
    pass
  def main (self):
    """
    Subclasses should replace this method.
    """
<|endoftext|>


<commit_before>
<commit_msg>[update]: import directories on top __init__.py<commit_after>import pkg_resources

from clib import converts
from clib import functions
from clib import links
from clib import training
from clib import transforms
from clib import utils

__version__ = pkg_resources.get_distribution('clib').version
<|endoftext|>


<commit_before>
from io import BytesIO
import logging

from .base import WebSocketBase, WebsocketBinaryHelperMixin, \
    BinaryUploadHelper, ST_NORMAL

from fluxclient.laser.laser_svg import LaserSvg

logger = logging.getLogger("WS.LP")

MODE_PRESET = "preset"
MODE_MANUALLY = "manually"

class WebsocketLaserSvgParser(WebsocketBinaryHelperMixin, WebSocketBase):
    operation = None

    m_laser_svg = LaserSvg()

    def on_text_message(self, message):
        try:
            if not self.operation:
                self.set_params(message)
                self.send_text('{"status": "ok"}')
            elif self.operation and not self.has_binary_helper():
                cmd, params = message.rstrip().split(" ", 1)

                if cmd == "upload":
                    self.begin_recv_svg(params, 'upload', None)
                elif cmd == "get":
                    self.get(params)
                elif cmd == "compute":
                    self.compute(params)
                elif cmd == "go":
                    self.go(params)
                else:
                    raise ValueError('Undefine command %s' % (cmd))
            else:
                raise RuntimeError("RESOURCE_BUSY")

        except ValueError:
            logger.exception("Laser svg argument error")
            self.send_fatal("BAD_PARAM_TYPE")

        except RuntimeError as e:
            self.send_fatal(e.args[0])

    def set_params(self, params):
        options = params.split(" ")

        if options[0] == "0":
            self.operation = MODE_PRESET

            self.operation = options[1]
            self.material = options[2]
            # raise RuntimeError("TODO: parse operation and material")
            self.laser_speed = 100.0
            self.duty_cycle = 100.0

        elif options[0] == "1":
            self.operation = MODE_MANUALLY

            self.laser_speed = float(options[1])
            self.duty_cycle = float(options[2])
        else:
            raise RuntimeError("BAD_PARAM_TYPE")

    def begin_recv_svg(self, message, flag, *args):
        name, file_length = message.split(" ")
        helper = BinaryUploadHelper(int(file_length), self.end_recv_svg, name, flag, args[0])
        self.set_binary_helper(helper)
        self.send_text('{"status": "continue"}')

    def end_recv_svg(self, buf, name, *args):
        if args[0] == 'upload':
            self.m_laser_svg.preprocess(buf, name)
            self.send_text('{"status": "ok"}')
        elif args[0] == 'compute':
            self.m_laser_svg.compute(buf[:args[1][-2]], name, args[1][:-2] + [buf[args[1][-2]:]])
            self.send_text('{"status": "ok"}')

    def get(self, name):
        self.send_text('{"status": "continue", "length" : %d}' % len(self.m_laser_svg.svgs[name]))
        self.send_binary(self.m_laser_svg.svgs[name])

    def compute(self, params):
        options = params.split(' ')
        name = options[0]
        w, h = int(options[1]), int(options[2])
        x1, y1, x2, y2 = (float(o) for o in options[3:7])
        rotation = float(options[7])
        svg_length = int(options[8])
        bitmap_length = int(options[9])
        self.begin_recv_svg('%s %d' % (name, svg_length + bitmap_length), 'compute', [w, h, x1, y1, x2, y2, rotation, svg_length, bitmap_length])

    def go(self, params):
        names = params.split(' ')
        output_binary = self.m_laser_svg.gcode_generate(names).encode()
        self.send_text('{"status": "complete","length": %d}' % len(output_binary))
        self.send_binary(output_binary)
<commit_msg>minor: wrong type transform bug<commit_after>
from io import BytesIO
import logging

from .base import WebSocketBase, WebsocketBinaryHelperMixin, \
    BinaryUploadHelper, ST_NORMAL

from fluxclient.laser.laser_svg import LaserSvg

logger = logging.getLogger("WS.LP")

MODE_PRESET = "preset"
MODE_MANUALLY = "manually"

class WebsocketLaserSvgParser(WebsocketBinaryHelperMixin, WebSocketBase):
    operation = None

    m_laser_svg = LaserSvg()

    def on_text_message(self, message):
        try:
            if not self.operation:
                self.set_params(message)
                self.send_text('{"status": "ok"}')
            elif self.operation and not self.has_binary_helper():
                cmd, params = message.rstrip().split(" ", 1)

                if cmd == "upload":
                    self.begin_recv_svg(params, 'upload', None)
                elif cmd == "get":
                    self.get(params)
                elif cmd == "compute":
                    self.compute(params)
                elif cmd == "go":
                    self.go(params)
                else:
                    raise ValueError('Undefine command %s' % (cmd))
            else:
                raise RuntimeError("RESOURCE_BUSY")

        except ValueError:
            logger.exception("Laser svg argument error")
            self.send_fatal("BAD_PARAM_TYPE")

        except RuntimeError as e:
            self.send_fatal(e.args[0])

    def set_params(self, params):
        options = params.split(" ")

        if options[0] == "0":
            self.operation = MODE_PRESET

            self.operation = options[1]
            self.material = options[2]
            # raise RuntimeError("TODO: parse operation and material")
            self.laser_speed = 100.0
            self.duty_cycle = 100.0

        elif options[0] == "1":
            self.operation = MODE_MANUALLY

            self.laser_speed = float(options[1])
            self.duty_cycle = float(options[2])
        else:
            raise RuntimeError("BAD_PARAM_TYPE")

    def begin_recv_svg(self, message, flag, *args):
        name, file_length = message.split(" ")
        helper = BinaryUploadHelper(int(file_length), self.end_recv_svg, name, flag, args[0])
        self.set_binary_helper(helper)
        self.send_text('{"status": "continue"}')

    def end_recv_svg(self, buf, name, *args):
        if args[0] == 'upload':
            self.m_laser_svg.preprocess(buf, name)
            self.send_text('{"status": "ok"}')
        elif args[0] == 'compute':
            self.m_laser_svg.compute(buf[:args[1][-2]], name, args[1][:-2] + [buf[args[1][-2]:]])
            self.send_text('{"status": "ok"}')

    def get(self, name):
        self.send_text('{"status": "continue", "length" : %d}' % len(self.m_laser_svg.svgs[name]))
        self.send_binary(self.m_laser_svg.svgs[name])

    def compute(self, params):
        options = params.split(' ')
        name = options[0]
        w, h = float(options[1]), float(options[2])
        x1, y1, x2, y2 = (float(o) for o in options[3:7])
        rotation = float(options[7])
        svg_length = int(options[8])
        bitmap_length = int(options[9])
        self.begin_recv_svg('%s %d' % (name, svg_length + bitmap_length), 'compute', [w, h, x1, y1, x2, y2, rotation, svg_length, bitmap_length])

    def go(self, params):
        names = params.split(' ')
        output_binary = self.m_laser_svg.gcode_generate(names).encode()
        self.send_text('{"status": "complete","length": %d}' % len(output_binary))
        self.send_binary(output_binary)
<|endoftext|>


<commit_before>from collections import namedtuple
import itertools

PageLink = namedtuple('PageLink', 'string, page_number clickable')

class PaginatorBase(object):

    def __init__(self, page=1, show_per_page=20):

        self.skip = (page - 1) * show_per_page
        self.show_per_page = show_per_page
        self.current_page = page
        self.limit = show_per_page

    def _previous_pages_count(self):
        'A generator of previous page integers.'
        skip = self.skip
        if skip == 0:
            return 0
        count, remainder = divmod(skip, self.limit)
        return count

    def _subsequent_pages_count(self):
        count, remainder = divmod(self.count, self.limit)
        if remainder:
            count += 1
        return count

    def previous_pages_numbers(self):
        'A generator of previous page integers.'
        count = self._previous_pages_count() + 1
        for i in reversed(range(1, count)):
            yield i

    def subsequent_pages_numbers(self):
        for page in xrange(self.current_page + 1,
                           self._subsequent_pages_count() + 1):
            yield page

    @property
    def last_page(self):
        last_page, remainder = divmod(self.count, self.limit)
        if remainder:
            last_page += 1
        return last_page

    @property
    def next_page(self):
        return self.current_page + 1

    @property
    def previous_page(self):
        return self.current_page - 1

    @property
    def range_start(self):
        '''"Showing 40-50 of 234 results
                    ^
        '''
        start = (self.current_page - 1) * self.show_per_page
        if start == 0:
            return 1
        else:
            return start

    @property
    def range_end(self):
        '''"Showing 40 - 50 of 234 results
                         ^
        '''
        count = self.count
        range_end = self.range_start + self.limit
        if count < range_end:
            range_end = count
        return range_end

    @property
    def total_count(self):
        '''"Showing 40 - 50 of 234 results
                               ^
        '''
        return self.count

    @property
    def has_next(self):
        return self.current_page != self.last_page

    @property
    def has_previous(self):
        return self.current_page != 1

    def pagination_data(self, max_number_of_links=11):
        '''Returns a generator of tuples (string, page_number, clickable),
        where `string` is the text of the html link, `page_number` is
        the number of the page the link points to, and `clickable` is
        a boolean indicating whether the link is clickable or not.
        '''
        div, mod = divmod(max_number_of_links, 2)
        if not mod == 1:
            msg = 'Max number of links must be odd, was %r.'
            raise ValueError(msg % max_number_of_links)

        midpoint = (max_number_of_links - 1) / 2
        current_page = self.current_page
        last_page = self.last_page

        show_link_firstpage = midpoint < current_page
        show_link_previouspage = 1 < current_page
        show_link_lastpage = current_page < (self.last_page - midpoint)
        show_link_nextpage = current_page < last_page

        extra_room_previous = midpoint - current_page
        if extra_room_previous < 0:
            extra_room_previous = 0
        if not show_link_firstpage:
            extra_room_previous += 1
        if not show_link_previouspage:
            extra_room_previous += 1

        extra_room_subsequent = current_page - last_page + midpoint
        extra_room_subsequent = max([extra_room_subsequent, 0])
        if not show_link_nextpage:
            extra_room_subsequent += 1
        if not show_link_lastpage:
            extra_room_subsequent += 1

        if self.current_page == 1:
            yield PageLink(string=1, page_number=1, clickable=False)
        else:
            # The  "first page" link.
            if show_link_firstpage:
                #[<<] [<] [7] [8] [9] 10 [11] ...'
                #  ^
                yield PageLink(string=u"\u00AB", page_number=1, clickable=True)

            if show_link_previouspage:
                # The "previous page" link.
                #[<<] [<] [7] [8] [9] 10 [11] ...'
                #      ^
                yield PageLink(string=u"\u2039",
                               page_number=self.previous_page,
                               clickable=True)

        # Up to `midpoint + extra_room_subsequent` previous page numbers.
        previous = itertools.islice(self.previous_pages_numbers(),
                                    midpoint + extra_room_subsequent)
        previous = list(previous)[::-1]

        for page_number in previous:
            yield PageLink(string=page_number,
                           page_number=page_number, clickable=True)

        # The current page, clickable.
        if current_page != 1:
            yield PageLink(string=current_page,
                           page_number=current_page, clickable=False)

        # Up to `midpoint + extra_room_previous` subsequent page numbers.
        subsequent_count = midpoint + extra_room_previous
        _subsequent_pages_count = self._subsequent_pages_count
        if _subsequent_pages_count < subsequent_count:
            subsequent_count = _subsequent_pages_count

        for page_number in itertools.islice(self.subsequent_pages_numbers(),
                                            subsequent_count):
            yield PageLink(string=page_number,
                           page_number=page_number, clickable=True)

        if show_link_nextpage:
            yield PageLink(string=u"\u203A",
                           page_number=current_page + 1,
                           clickable=True)

        if show_link_lastpage:
            yield PageLink(string=u"\u00BB",
                           page_number=last_page,
                           clickable=True)

class CursorPaginator(PaginatorBase):

    def __init__(self, cursor, *args, **kwargs):
        super(CursorPaginator, self).__init__(*args, **kwargs)
        self.cursor = cursor
        self.count = cursor.count()
        self._cached = False

    def __iter__(self):
        'The specific page of records.'
        if self._cached:
            for record in self._cache:
                yield record
            return

        else:
            cache = []
        for record in self.cursor.skip(self.skip).limit(self.limit):
            yield record
            cache.append(record)

        self._cached = True
        self._cache = cache

class IteratorPaginator(PaginatorBase):
    'Huh huh...that rhymes.'

    def __init__(self, iterable, *args, **kwargs):
        super(IteratorPaginator, self).__init__(*args, **kwargs)
        iterable = list(iterable)
        self.count = len(iterable)
        self.iterable = iterable

    def __iter__(self):
        return iter(self.iterable[self.skip: (self.skip + self.limit)])

    def __len__(self):
        count = self.count
        limit = self.limit
        if limit < count:
            return limit
        else:
            return count
<commit_msg>models: fix end of pagination range<commit_after>from collections import namedtuple
import itertools

PageLink = namedtuple('PageLink', 'string, page_number clickable')

class PaginatorBase(object):

    def __init__(self, page=1, show_per_page=20):

        self.skip = (page - 1) * show_per_page
        self.show_per_page = show_per_page
        self.current_page = page
        self.limit = show_per_page

    def _previous_pages_count(self):
        'A generator of previous page integers.'
        skip = self.skip
        if skip == 0:
            return 0
        count, remainder = divmod(skip, self.limit)
        return count

    def _subsequent_pages_count(self):
        count, remainder = divmod(self.count, self.limit)
        if remainder:
            count += 1
        return count

    def previous_pages_numbers(self):
        'A generator of previous page integers.'
        count = self._previous_pages_count() + 1
        for i in reversed(range(1, count)):
            yield i

    def subsequent_pages_numbers(self):
        for page in xrange(self.current_page + 1,
                           self._subsequent_pages_count() + 1):
            yield page

    @property
    def last_page(self):
        last_page, remainder = divmod(self.count, self.limit)
        if remainder:
            last_page += 1
        return last_page

    @property
    def next_page(self):
        return self.current_page + 1

    @property
    def previous_page(self):
        return self.current_page - 1

    @property
    def range_start(self):
        '''"Showing 40-50 of 234 results
                    ^
        '''
        start = (self.current_page - 1) * self.show_per_page
        if start == 0:
            return 1
        else:
            return start

    @property
    def range_end(self):
        '''"Showing 40 - 50 of 234 results
                         ^
        '''
        count = self.count
        range_end = self.range_start + self.limit - 1
        if count < range_end:
            range_end = count
        return range_end

    @property
    def total_count(self):
        '''"Showing 40 - 50 of 234 results
                               ^
        '''
        return self.count

    @property
    def has_next(self):
        return self.current_page != self.last_page

    @property
    def has_previous(self):
        return self.current_page != 1

    def pagination_data(self, max_number_of_links=11):
        '''Returns a generator of tuples (string, page_number, clickable),
        where `string` is the text of the html link, `page_number` is
        the number of the page the link points to, and `clickable` is
        a boolean indicating whether the link is clickable or not.
        '''
        div, mod = divmod(max_number_of_links, 2)
        if not mod == 1:
            msg = 'Max number of links must be odd, was %r.'
            raise ValueError(msg % max_number_of_links)

        midpoint = (max_number_of_links - 1) / 2
        current_page = self.current_page
        last_page = self.last_page

        show_link_firstpage = midpoint < current_page
        show_link_previouspage = 1 < current_page
        show_link_lastpage = current_page < (self.last_page - midpoint)
        show_link_nextpage = current_page < last_page

        extra_room_previous = midpoint - current_page
        if extra_room_previous < 0:
            extra_room_previous = 0
        if not show_link_firstpage:
            extra_room_previous += 1
        if not show_link_previouspage:
            extra_room_previous += 1

        extra_room_subsequent = current_page - last_page + midpoint
        extra_room_subsequent = max([extra_room_subsequent, 0])
        if not show_link_nextpage:
            extra_room_subsequent += 1
        if not show_link_lastpage:
            extra_room_subsequent += 1

        if self.current_page == 1:
            yield PageLink(string=1, page_number=1, clickable=False)
        else:
            # The  "first page" link.
            if show_link_firstpage:
                #[<<] [<] [7] [8] [9] 10 [11] ...'
                #  ^
                yield PageLink(string=u"\u00AB", page_number=1, clickable=True)

            if show_link_previouspage:
                # The "previous page" link.
                #[<<] [<] [7] [8] [9] 10 [11] ...'
                #      ^
                yield PageLink(string=u"\u2039",
                               page_number=self.previous_page,
                               clickable=True)

        # Up to `midpoint + extra_room_subsequent` previous page numbers.
        previous = itertools.islice(self.previous_pages_numbers(),
                                    midpoint + extra_room_subsequent)
        previous = list(previous)[::-1]

        for page_number in previous:
            yield PageLink(string=page_number,
                           page_number=page_number, clickable=True)

        # The current page, clickable.
        if current_page != 1:
            yield PageLink(string=current_page,
                           page_number=current_page, clickable=False)

        # Up to `midpoint + extra_room_previous` subsequent page numbers.
        subsequent_count = midpoint + extra_room_previous
        _subsequent_pages_count = self._subsequent_pages_count
        if _subsequent_pages_count < subsequent_count:
            subsequent_count = _subsequent_pages_count

        for page_number in itertools.islice(self.subsequent_pages_numbers(),
                                            subsequent_count):
            yield PageLink(string=page_number,
                           page_number=page_number, clickable=True)

        if show_link_nextpage:
            yield PageLink(string=u"\u203A",
                           page_number=current_page + 1,
                           clickable=True)

        if show_link_lastpage:
            yield PageLink(string=u"\u00BB",
                           page_number=last_page,
                           clickable=True)

class CursorPaginator(PaginatorBase):

    def __init__(self, cursor, *args, **kwargs):
        super(CursorPaginator, self).__init__(*args, **kwargs)
        self.cursor = cursor
        self.count = cursor.count()
        self._cached = False

    def __iter__(self):
        'The specific page of records.'
        if self._cached:
            for record in self._cache:
                yield record
            return

        else:
            cache = []
        for record in self.cursor.skip(self.skip).limit(self.limit):
            yield record
            cache.append(record)

        self._cached = True
        self._cache = cache

class IteratorPaginator(PaginatorBase):
    'Huh huh...that rhymes.'

    def __init__(self, iterable, *args, **kwargs):
        super(IteratorPaginator, self).__init__(*args, **kwargs)
        iterable = list(iterable)
        self.count = len(iterable)
        self.iterable = iterable

    def __iter__(self):
        return iter(self.iterable[self.skip: (self.skip + self.limit)])

    def __len__(self):
        count = self.count
        limit = self.limit
        if limit < count:
            return limit
        else:
            return count
<|endoftext|>


<commit_before>import random
from collections import defaultdict

from billy import db
from billy.utils import metadata

from django.http import Http404
from django.views.decorators.cache import never_cache
from django.shortcuts import render_to_response
from django.utils.datastructures import SortedDict

def keyfunc(obj):
    try:
        return int(obj['district'])
    except ValueError:
        return obj['district']

def browse_index(request, template='billy/index.html'):
    rows = []
    total_missing_ids = 0
    total_active = 0

    for meta in list(db.metadata.find()) + [{'_id':'total', 'name':'total'}]:
        row = {}
        row['id'] = meta['_id']
        row['name'] = meta['name']

        counts = db.counts.find_one({'_id': row['id']})
        if counts:
            counts = counts['value']
            row['bills'] = counts['bills']
            row['votes'] = counts['votes']
            row['versions'] = counts['versions']
            if counts['actions']:
                row['typed_actions'] = (float(counts['categorized']) /
                                        counts['actions_this_term'] * 100)
            if counts['bills']:
                row['subjects'] = (float(counts['subjects']) /
                                   counts['bills'] * 100)
            if counts['sponsors']:
                row['sponsor_ids'] = (float(counts['idd_sponsors']) /
                                      counts['sponsors'] * 100)
            if counts['voters']:
                row['voter_ids'] = (float(counts['idd_voters']) /
                                    counts['voters'] * 100)

        com_counts = db.committee_counts.find_one({'_id': row['id']})
        if com_counts:
            com_counts = com_counts['value']
            row['committees'] = com_counts['committees']
            if counts['members']:
                row['member_ids'] = (float(com_counts['idd_members']) /
                                     com_counts['members'] * 100)

        if row['id'] != 'total':
            level = meta['level']
            s_spec = {'level': level, level: row['id']}
            row['bill_types'] = len(db.bills.find(s_spec).distinct('type')) > 1
            row['legislators'] = db.legislators.find(s_spec).count()
            row['events'] = db.events.find(s_spec).count()
            id_counts = _get_leg_id_stats(level, row['id'])
            active_legs = db.legislators.find({'level': level,
                                               level: row['id'],
                                               'active': True}).count()

            if not active_legs:
                row['external_ids'] = 0
            else:
                missing_ids = float(id_counts['missing_pvs'] +
                                    id_counts['missing_tdata'])
                row['external_ids'] = (1 - (missing_ids /
                                            (active_legs * 2))) * 100
                total_missing_ids += missing_ids
                total_active += active_legs

            missing_bill_sources = db.bills.find({'level': level,
                                                  level: row['id'],
                                              'sources': {'$size': 0}}).count()
            missing_leg_sources = db.legislators.find({'level': level,
                                                       level: row['id'],
                                              'sources': {'$size': 0}}).count()
            row['missing_sources'] = ''
            if missing_bill_sources:
                row['missing_sources'] += 'bills'
            if missing_leg_sources:
                row['missing_sources'] += ' legislators'
        else:
            row['bill_types'] = 'n/a'
            row['legislators'] = db.legislators.find().count()
            row['committees'] = db.committees.find().count()
            row['events'] = db.events.find().count()

        rows.append(row)

    rows.sort(key=lambda x: x['id'] if x['id'] != 'total' else 'zz')

    # set total external ids
    rows[-1]['external_ids'] = (1 - (total_missing_ids /
                                     (total_active * 2))) * 100

    return render_to_response(template, {'rows': rows})

def _bill_stats_for_session(level, abbr, session):
    context = {}
    context['upper_bill_count'] = db.bills.find({'level': level,
                                                 level: abbr,
                                                 'session': session,
                                                 'chamber': 'upper'}).count()
    context['lower_bill_count'] = db.bills.find({'level': level,
                                                 level: abbr,
                                                 'session': session,
                                                 'chamber': 'lower'}).count()
    context['bill_count'] = (context['upper_bill_count'] +
                             context['lower_bill_count'])
    context['ns_bill_count'] = db.bills.find({'level': level,
                                              level: abbr,
                                              'session': session,
                                           'sources': {'$size': 0}}).count()
    types = defaultdict(int)
    action_types = defaultdict(int)
    total_actions = 0
    versions = 0

    for bill in db.bills.find({'level': level, level: abbr,
                               'session': session},
                              {'type': 1, 'actions.type': 1, 'versions': 1}):
        for t in bill['type']:
            types[t] += 1
        for a in bill['actions']:
            for at in a['type']:
                action_types[at] += 1
                total_actions += 1
        versions += len(bill.get('versions', []))
    context['versions'] = versions

    context['types'] = dict(types)
    context['action_types'] = dict(action_types)
    if total_actions:
        context['action_cat_percent'] = ((total_actions -
                                          action_types['other']) /
                                         float(total_actions) * 100)

    return context

def _get_leg_id_stats(level, abbr):
    context = {}
    context['missing_pvs'] = db.legislators.find({'level': level,
                             level: abbr,
                             'active': True,
                             'votesmart_id': {'$exists': False}}).count()
    context['missing_tdata'] = db.legislators.find({'level': level,
         level: abbr, 'active': True,
         'transparencydata_id': {'$exists': False}}).count()
    return context

def overview(request, abbr):
    meta = metadata(abbr)
    if not meta:
        raise Http404

    context = {}
    context['metadata'] = SortedDict(sorted(meta.items()))

    # types
    latest_session = meta['terms'][-1]['sessions'][-1]
    context['session'] = latest_session

    level = meta['level']

    context.update(_bill_stats_for_session(level, abbr, latest_session))

    # legislators
    context['upper_leg_count'] = db.legislators.find({'level': level,
                                                      level: abbr,
                                                      'active': True,
                                                  'chamber': 'upper'}).count()
    context['lower_leg_count'] = db.legislators.find({'level': level,
                                                      level: abbr,
                                                      'active': True,
                                                  'chamber': 'lower'}).count()
    context['leg_count'] = (context['upper_leg_count'] +
                            context['lower_leg_count'])
    context['inactive_leg_count'] = db.legislators.find({'level': level,
                                                         level: abbr,
                                                     'active': False}).count()
    context['ns_leg_count'] = db.legislators.find({'level': level,
                             level: abbr,
                             'active': True,
                             'sources': {'$size': 0}}).count()
    context.update(_get_leg_id_stats(level, abbr))

    # committees
    context['upper_com_count'] = db.committees.find({'level': level,
                                                     level: abbr,
                                                  'chamber': 'upper'}).count()
    context['lower_com_count'] = db.committees.find({'level': level,
                                                     level: abbr,
                                                  'chamber': 'lower'}).count()
    context['joint_com_count'] = db.committees.find({'level': level,
                                                     level: abbr,
                                                  'chamber': 'joint'}).count()
    context['com_count'] = (context['upper_com_count'] +
                            context['lower_com_count'] +
                            context['joint_com_count'])
    context['ns_com_count'] = db.committees.find({'level': level,
                                                  level: abbr,
                             'sources': {'$size': 0}}).count()

    return render_to_response('billy/state_index.html', context)

def bills(request, abbr):
    meta = metadata(abbr)
    level = meta['level']
    if not meta:
        raise Http404

    sessions = []
    for term in meta['terms']:
        for session in term['sessions']:
            stats = _bill_stats_for_session(level, abbr, session)
            stats['session'] = session
            sessions.append(stats)

    return render_to_response('billy/bills.html',
                              {'sessions': sessions, 'metadata': meta})

@never_cache
def random_bill(request, abbr):
    meta = metadata(abbr)
    if not meta:
        raise Http404

    level = meta['level']
    latest_session = meta['terms'][-1]['sessions'][-1]

    spec = {'level': level, level: abbr.lower(), 'session': latest_session}

    count = db.bills.find(spec).count()
    bill = db.bills.find(spec)[random.randint(0, count - 1)]

    return render_to_response('billy/bill.html', {'bill': bill})

def bill(request, abbr, session, id):
    level = metadata(abbr)['level']
    bill = db.bills.find_one({'level': level, level: abbr,
                              'session':session, 'bill_id':id.upper()})
    if not bill:
        raise Http404

    return render_to_response('billy/bill.html', {'bill': bill})

def legislators(request, abbr):
    meta = metadata(abbr)
    level = metadata(abbr)['level']

    upper_legs = db.legislators.find({'level': level, level: abbr.lower(),
                                      'active': True, 'chamber': 'upper'})
    lower_legs = db.legislators.find({'level': level, level: abbr.lower(),
                                      'active': True, 'chamber': 'lower'})
    inactive_legs = db.legislators.find({'level': level, level: abbr.lower(),
                                         'active': False})
    upper_legs = sorted(upper_legs, key=keyfunc)
    lower_legs = sorted(lower_legs, key=keyfunc)
    inactive_legs = sorted(inactive_legs, key=lambda x: x['last_name'])

    return render_to_response('billy/legislators.html', {
        'upper_legs': upper_legs,
        'lower_legs': lower_legs,
        'inactive_legs': inactive_legs,
        'metadata': meta,
    })

def legislator(request, id):
    leg = db.legislators.find_one({'_all_ids': id})
    if not leg:
        raise Http404

    meta = metadata(leg[leg['level']])

    return render_to_response('billy/legislator.html', {'leg': leg,
                                                        'metadata': meta})

def committees(request, abbr):
    meta = metadata(abbr)
    level = metadata(abbr)['level']

    upper_coms = db.committees.find({'level': level, level: abbr.lower(),
                                     'chamber': 'upper'})
    lower_coms = db.committees.find({'level': level, level: abbr.lower(),
                                      'chamber': 'lower'})
    joint_coms = db.committees.find({'level': level, level: abbr.lower(),
                                      'chamber': 'joint'})
    upper_coms = sorted(upper_coms)
    lower_coms = sorted(lower_coms)
    joint_coms = sorted(joint_coms)

    return render_to_response('billy/committees.html', {
        'upper_coms': upper_coms,
        'lower_coms': lower_coms,
        'joint_coms': joint_coms,
        'metadata': meta,
    })
<commit_msg>fix for com_counts view<commit_after>import random
from collections import defaultdict

from billy import db
from billy.utils import metadata

from django.http import Http404
from django.views.decorators.cache import never_cache
from django.shortcuts import render_to_response
from django.utils.datastructures import SortedDict

def keyfunc(obj):
    try:
        return int(obj['district'])
    except ValueError:
        return obj['district']

def browse_index(request, template='billy/index.html'):
    rows = []
    total_missing_ids = 0
    total_active = 0

    for meta in list(db.metadata.find()) + [{'_id':'total', 'name':'total'}]:
        row = {}
        row['id'] = meta['_id']
        row['name'] = meta['name']

        counts = db.counts.find_one({'_id': row['id']})
        if counts:
            counts = counts['value']
            row['bills'] = counts['bills']
            row['votes'] = counts['votes']
            row['versions'] = counts['versions']
            if counts['actions']:
                row['typed_actions'] = (float(counts['categorized']) /
                                        counts['actions_this_term'] * 100)
            if counts['bills']:
                row['subjects'] = (float(counts['subjects']) /
                                   counts['bills'] * 100)
            if counts['sponsors']:
                row['sponsor_ids'] = (float(counts['idd_sponsors']) /
                                      counts['sponsors'] * 100)
            if counts['voters']:
                row['voter_ids'] = (float(counts['idd_voters']) /
                                    counts['voters'] * 100)

        com_counts = db.committee_counts.find_one({'_id': row['id']})
        if com_counts:
            com_counts = com_counts['value']
            row['committees'] = com_counts['committees']
            if com_counts['members']:
                row['member_ids'] = (float(com_counts['idd_members']) /
                                     com_counts['members'] * 100)

        if row['id'] != 'total':
            level = meta['level']
            s_spec = {'level': level, level: row['id']}
            row['bill_types'] = len(db.bills.find(s_spec).distinct('type')) > 1
            row['legislators'] = db.legislators.find(s_spec).count()
            row['events'] = db.events.find(s_spec).count()
            id_counts = _get_leg_id_stats(level, row['id'])
            active_legs = db.legislators.find({'level': level,
                                               level: row['id'],
                                               'active': True}).count()

            if not active_legs:
                row['external_ids'] = 0
            else:
                missing_ids = float(id_counts['missing_pvs'] +
                                    id_counts['missing_tdata'])
                row['external_ids'] = (1 - (missing_ids /
                                            (active_legs * 2))) * 100
                total_missing_ids += missing_ids
                total_active += active_legs

            missing_bill_sources = db.bills.find({'level': level,
                                                  level: row['id'],
                                              'sources': {'$size': 0}}).count()
            missing_leg_sources = db.legislators.find({'level': level,
                                                       level: row['id'],
                                              'sources': {'$size': 0}}).count()
            row['missing_sources'] = ''
            if missing_bill_sources:
                row['missing_sources'] += 'bills'
            if missing_leg_sources:
                row['missing_sources'] += ' legislators'
        else:
            row['bill_types'] = 'n/a'
            row['legislators'] = db.legislators.find().count()
            row['committees'] = db.committees.find().count()
            row['events'] = db.events.find().count()

        rows.append(row)

    rows.sort(key=lambda x: x['id'] if x['id'] != 'total' else 'zz')

    # set total external ids
    rows[-1]['external_ids'] = (1 - (total_missing_ids /
                                     (total_active * 2))) * 100

    return render_to_response(template, {'rows': rows})

def _bill_stats_for_session(level, abbr, session):
    context = {}
    context['upper_bill_count'] = db.bills.find({'level': level,
                                                 level: abbr,
                                                 'session': session,
                                                 'chamber': 'upper'}).count()
    context['lower_bill_count'] = db.bills.find({'level': level,
                                                 level: abbr,
                                                 'session': session,
                                                 'chamber': 'lower'}).count()
    context['bill_count'] = (context['upper_bill_count'] +
                             context['lower_bill_count'])
    context['ns_bill_count'] = db.bills.find({'level': level,
                                              level: abbr,
                                              'session': session,
                                           'sources': {'$size': 0}}).count()
    types = defaultdict(int)
    action_types = defaultdict(int)
    total_actions = 0
    versions = 0

    for bill in db.bills.find({'level': level, level: abbr,
                               'session': session},
                              {'type': 1, 'actions.type': 1, 'versions': 1}):
        for t in bill['type']:
            types[t] += 1
        for a in bill['actions']:
            for at in a['type']:
                action_types[at] += 1
                total_actions += 1
        versions += len(bill.get('versions', []))
    context['versions'] = versions

    context['types'] = dict(types)
    context['action_types'] = dict(action_types)
    if total_actions:
        context['action_cat_percent'] = ((total_actions -
                                          action_types['other']) /
                                         float(total_actions) * 100)

    return context

def _get_leg_id_stats(level, abbr):
    context = {}
    context['missing_pvs'] = db.legislators.find({'level': level,
                             level: abbr,
                             'active': True,
                             'votesmart_id': {'$exists': False}}).count()
    context['missing_tdata'] = db.legislators.find({'level': level,
         level: abbr, 'active': True,
         'transparencydata_id': {'$exists': False}}).count()
    return context

def overview(request, abbr):
    meta = metadata(abbr)
    if not meta:
        raise Http404

    context = {}
    context['metadata'] = SortedDict(sorted(meta.items()))

    # types
    latest_session = meta['terms'][-1]['sessions'][-1]
    context['session'] = latest_session

    level = meta['level']

    context.update(_bill_stats_for_session(level, abbr, latest_session))

    # legislators
    context['upper_leg_count'] = db.legislators.find({'level': level,
                                                      level: abbr,
                                                      'active': True,
                                                  'chamber': 'upper'}).count()
    context['lower_leg_count'] = db.legislators.find({'level': level,
                                                      level: abbr,
                                                      'active': True,
                                                  'chamber': 'lower'}).count()
    context['leg_count'] = (context['upper_leg_count'] +
                            context['lower_leg_count'])
    context['inactive_leg_count'] = db.legislators.find({'level': level,
                                                         level: abbr,
                                                     'active': False}).count()
    context['ns_leg_count'] = db.legislators.find({'level': level,
                             level: abbr,
                             'active': True,
                             'sources': {'$size': 0}}).count()
    context.update(_get_leg_id_stats(level, abbr))

    # committees
    context['upper_com_count'] = db.committees.find({'level': level,
                                                     level: abbr,
                                                  'chamber': 'upper'}).count()
    context['lower_com_count'] = db.committees.find({'level': level,
                                                     level: abbr,
                                                  'chamber': 'lower'}).count()
    context['joint_com_count'] = db.committees.find({'level': level,
                                                     level: abbr,
                                                  'chamber': 'joint'}).count()
    context['com_count'] = (context['upper_com_count'] +
                            context['lower_com_count'] +
                            context['joint_com_count'])
    context['ns_com_count'] = db.committees.find({'level': level,
                                                  level: abbr,
                             'sources': {'$size': 0}}).count()

    return render_to_response('billy/state_index.html', context)

def bills(request, abbr):
    meta = metadata(abbr)
    level = meta['level']
    if not meta:
        raise Http404

    sessions = []
    for term in meta['terms']:
        for session in term['sessions']:
            stats = _bill_stats_for_session(level, abbr, session)
            stats['session'] = session
            sessions.append(stats)

    return render_to_response('billy/bills.html',
                              {'sessions': sessions, 'metadata': meta})

@never_cache
def random_bill(request, abbr):
    meta = metadata(abbr)
    if not meta:
        raise Http404

    level = meta['level']
    latest_session = meta['terms'][-1]['sessions'][-1]

    spec = {'level': level, level: abbr.lower(), 'session': latest_session}

    count = db.bills.find(spec).count()
    bill = db.bills.find(spec)[random.randint(0, count - 1)]

    return render_to_response('billy/bill.html', {'bill': bill})

def bill(request, abbr, session, id):
    level = metadata(abbr)['level']
    bill = db.bills.find_one({'level': level, level: abbr,
                              'session':session, 'bill_id':id.upper()})
    if not bill:
        raise Http404

    return render_to_response('billy/bill.html', {'bill': bill})

def legislators(request, abbr):
    meta = metadata(abbr)
    level = metadata(abbr)['level']

    upper_legs = db.legislators.find({'level': level, level: abbr.lower(),
                                      'active': True, 'chamber': 'upper'})
    lower_legs = db.legislators.find({'level': level, level: abbr.lower(),
                                      'active': True, 'chamber': 'lower'})
    inactive_legs = db.legislators.find({'level': level, level: abbr.lower(),
                                         'active': False})
    upper_legs = sorted(upper_legs, key=keyfunc)
    lower_legs = sorted(lower_legs, key=keyfunc)
    inactive_legs = sorted(inactive_legs, key=lambda x: x['last_name'])

    return render_to_response('billy/legislators.html', {
        'upper_legs': upper_legs,
        'lower_legs': lower_legs,
        'inactive_legs': inactive_legs,
        'metadata': meta,
    })

def legislator(request, id):
    leg = db.legislators.find_one({'_all_ids': id})
    if not leg:
        raise Http404

    meta = metadata(leg[leg['level']])

    return render_to_response('billy/legislator.html', {'leg': leg,
                                                        'metadata': meta})

def committees(request, abbr):
    meta = metadata(abbr)
    level = metadata(abbr)['level']

    upper_coms = db.committees.find({'level': level, level: abbr.lower(),
                                     'chamber': 'upper'})
    lower_coms = db.committees.find({'level': level, level: abbr.lower(),
                                      'chamber': 'lower'})
    joint_coms = db.committees.find({'level': level, level: abbr.lower(),
                                      'chamber': 'joint'})
    upper_coms = sorted(upper_coms)
    lower_coms = sorted(lower_coms)
    joint_coms = sorted(joint_coms)

    return render_to_response('billy/committees.html', {
        'upper_coms': upper_coms,
        'lower_coms': lower_coms,
        'joint_coms': joint_coms,
        'metadata': meta,
    })
<|endoftext|>