<commit_before>from time_tracking.forms import ClockForm
from time_tracking.templatetags import clockformats
from expenses.templatetags import moneyformats
from time_tracking.middleware import CurrentUserMiddleware
from time_tracking.models import Clock, Project, Activity, ClockOptions, ActivityOptions, TimeTrackingGroup
from django import forms
from django.conf import settings
from django.contrib import admin
from django.http import HttpResponse
from django.utils.translation import ugettext_lazy as _, ugettext
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.core.exceptions import PermissionDenied
import datetime

class ActivityAdmin(admin.ModelAdmin):
    list_display = ('__unicode__', 'activity_type', 'time_factor')

class ClockOptionsAdmin(admin.ModelAdmin):
    list_display = ('username', 'display_balance', 'display_closing', 'hours_per_week', 'unpaid_break', 'weekday_1', 'weekday_2', 'weekday_3', 'weekday_4', 'weekday_5', 'weekday_6', 'weekday_7')

class ActivityOptionsAdmin(admin.ModelAdmin):
    list_display = ('activity', 'username', 'rate_formatted')

    def rate_formatted(self, obj):
        return moneyformats.money(obj.rate)
    rate_formatted.short_description = _('rate')
    rate_formatted.admin_order_field = 'rate'

class ClockInForm(forms.Form):

    def __init__(self, *args, **kwargs):
        super(ClockInForm, self).__init__(*args, **kwargs)
        # Field is added on __init__ due to current-user-related queryset
        self.fields['project'] = forms.ModelChoiceField(label=_('Project'),
            queryset=Project.get_queryset_for_current_user(), required=False)

class ClockAdmin(admin.ModelAdmin):
    date_hierarchy = 'start'
    list_display = ('status_icon', 'weekday', 'start_date', 'start_time', 'end_time', 'hours_rounded', 'hours_credited_rounded', 'activity', 'rate_formatted', 'cost_formatted', 'project', 'comment')
    list_display_links = ('status_icon', 'weekday', 'start_date',)
    form = ClockForm
    ordering = ['-start']

    if 'billing' in settings.INSTALLED_APPS:
        actions = ['bill_selected']

    def queryset(self, request):
        """
        Filter the objects displayed in the change_list to only
        display those for the currently signed in user.
        """
        qs = super(ClockAdmin, self).queryset(request)
        if not request.user.has_perm('time_tracking.can_set_user'):
            qs = qs.filter(user=request.user)
        return qs

    def bill_selected(self, request, queryset):
        from billing.models import ClockBill
        bill = ClockBill()
        bill.save()
        if queryset.filter(bill=None).count() != queryset.count():
            self.message_user(request, _('Some entries were already billed and were not added to this bill.'))
        for obj in queryset.filter(bill=None):
            obj.bill = bill
            if not obj.billed_rate:
                obj.billed_rate = obj.get_rate() or 0
            if not obj.billed_time_factor:
                obj.billed_time_factor = obj.activity.time_factor
            obj.save()
        return HttpResponseRedirect(bill.get_admin_url())
    bill_selected.short_description = _('Create bill with selected %(verbose_name_plural)s')

    def add_view(self, request, form_url='', extra_context=None):
        if not request.user.has_perm('time_tracking.can_set_user'):
            self.exclude = ('user',)
        else:
            self.exclude = ()
        return super(ClockAdmin, self).add_view(request, form_url, extra_context)

    def change_view(self, request, object_id, extra_context=None):
        if not request.user.has_perm('time_tracking.can_set_user'):
            self.exclude = ('user',)
        else:
            self.exclude = ()

        return super(ClockAdmin, self).change_view(request, object_id, extra_context)

    def test_view(self, request, extra_context=None):
        request.user.message_set.create(message="yay")
        return super(ClockAdmin, self).changelist_view(request, extra_context)

    def changelist_view(self, request, extra_context=None):
        if not request.user.has_perm('time_tracking.can_set_user'):
            if 'user' in self.list_display:
                list_display = list(self.list_display)
                list_display.remove('user')
                self.list_display = tuple(list_display)
            self.list_filter = ['start', 'project', 'activity']
        else:
            if 'user' not in self.list_display:
                self.list_display += ('user',)
            self.list_filter = ['start', 'project', 'activity', 'user']

        from django.contrib.admin.views.main import ChangeList
        cl = ChangeList(request, self.model, self.list_display, self.list_display_links,
            self.list_filter, self.date_hierarchy, self.search_fields,
            self.list_select_related, self.list_per_page, self.list_max_show_all, self.list_editable, self)
        clocked_in_time = Clock.clocked_in_time(request.user)
        if clocked_in_time and clocked_in_time.project:
            # TODO this is not working
            initial = {'project': clocked_in_time.project}
        else:
            initial = {'project': Project.get_latest_for_current_user()}
        extra_context = {
            'time_info': Clock.summarize(request.user, cl.get_query_set()),
            'clock_in_form': ClockInForm(initial=initial),
        }

        return super(ClockAdmin, self).changelist_view(request, extra_context)

    def get_urls(self):
        from django.conf.urls.defaults import patterns, url
        urls = super(ClockAdmin, self).get_urls()
        url_patterns = patterns('',
            url(r'^in/$', self.admin_site.admin_view(self.clock_in), name="time_tracking_clock_in"),
            url(r'^out/$', self.admin_site.admin_view(self.clock_out), name="time_tracking_clock_out"),
        )
        url_patterns.extend(urls)
        return url_patterns

    def clock_in(self, request):
        if not self.has_add_permission(request):
            raise PermissionDenied
        else:
            clocked_in_time = Clock.clocked_in_time(request.user)
            project = None
            if request.method == 'POST':
                form = ClockInForm(request.POST)
                if not form.is_valid():
                    raise Exception(forms.ValidationError)
                if form.cleaned_data:
                    project = form.cleaned_data['project']
                else:
                    raise forms.ValidationError('Invalid project')

            can_clock_in = not clocked_in_time
            if clocked_in_time:
                if not project or clocked_in_time.project == project:
                    messages.add_message(request, messages.WARNING, _("Please clock out first. Clocked in: %s") % clocked_in_time.__unicode__())
                else:
                    clocked_in_time.clock_out()
                    messages.add_message(request, messages.SUCCESS, _("Clocked out: %s") % clocked_in_time.__unicode__())
                    can_clock_in = True

            if can_clock_in:
                try:
                    clock_in_time = Clock.clock_in(request.user, project)
                    if project:
                        messages.add_message(request, messages.SUCCESS, _("Clocked into %(project)s: %(clock)s") %
                        {'clock': clock_in_time.__unicode__(), 'project': project.__unicode__()})
                    else:
                        messages.add_message(request, messages.SUCCESS, _("Clocked in: %(clock)s") %
                            {'clock': clock_in_time.__unicode__()})
                except ValueError:
                    messages.add_message(request, messages.WARNING, _("In order to be able to clock in, you'll have to create a first entry."))

            return HttpResponseRedirect('../')

    def clock_out(self, request):
        if not self.has_change_permission(request):
            raise PermissionDenied
        else:
            clocked_in_time = Clock.clocked_in_time(request.user)
            if (clocked_in_time != None):
                clocked_in_time.clock_out()
                messages.add_message(request, messages.SUCCESS, _("Clocked out: %s") % clocked_in_time.__unicode__())
            else:
                messages.add_message(request, messages.WARNING, _("Please clock in first."))

            return HttpResponseRedirect('../')

    def cost_formatted(self, obj):
        return moneyformats.money(obj.get_cost())
    cost_formatted.short_description = _('cost')

    def rate_formatted(self, obj):
        return moneyformats.money(obj.get_rate())
    rate_formatted.short_description = _('rate')

class ProjectAdmin(admin.ModelAdmin):
    list_display = ('name', 'group_names', 'status', 'budget_formatted', 'hours_sum_formatted', 'cost_sum_formatted', 'balance_formatted', 'coverage_formatted')

    def group_names(self, obj):
        return ', '.join([group.__unicode__() for group in obj.groups.all()])
    group_names.short_description = _('groups')

    def budget_formatted(self, obj):
        return moneyformats.money(obj.budget)
    budget_formatted.short_description = _('budget')
    budget_formatted.admin_order_field = 'budget'

    def hours_sum_formatted(self, obj):
        return clockformats.hours(obj.sum_hours(), units=False)
    hours_sum_formatted.short_description = _('hours spent')

    def cost_sum_formatted(self, obj):
        return moneyformats.money(obj.sum_cost())
    cost_sum_formatted.short_description = _('budget spent')

    def balance_formatted(self, obj):
        return moneyformats.money(obj.balance())
    balance_formatted.short_description = _('balance')

    def coverage_formatted(self, obj):
        return moneyformats.percent(obj.coverage())
    coverage_formatted.short_description = _('coverage')

class TimeTrackingGroupAdmin(admin.ModelAdmin):
    list_display = ('name', 'user_names', 'clock_sum')

    def user_names(self, obj):
        return ', '.join([user.__unicode__() for user in obj.user_set.all()])
    user_names.short_description = _('users')

    def clock_sum(self, obj):
        return ''
        #return money(Expense.objects.filter(expense_group=obj).aggregate(Sum('amount'))['amount__sum'])
    clock_sum.short_description = _('total')

admin.site.register(Clock, ClockAdmin)
admin.site.register(Project, ProjectAdmin)
admin.site.register(ClockOptions, ClockOptionsAdmin)
admin.site.register(ActivityOptions, ActivityOptionsAdmin)
admin.site.register(Activity, ActivityAdmin)
admin.site.register(TimeTrackingGroup, TimeTrackingGroupAdmin)
<commit_msg>Updated ChangeList get_queryset<commit_after>from time_tracking.forms import ClockForm
from time_tracking.templatetags import clockformats
from expenses.templatetags import moneyformats
from time_tracking.middleware import CurrentUserMiddleware
from time_tracking.models import Clock, Project, Activity, ClockOptions, ActivityOptions, TimeTrackingGroup
from django import forms
from django.conf import settings
from django.contrib import admin
from django.http import HttpResponse
from django.utils.translation import ugettext_lazy as _, ugettext
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.core.exceptions import PermissionDenied
import datetime

class ActivityAdmin(admin.ModelAdmin):
    list_display = ('__unicode__', 'activity_type', 'time_factor')

class ClockOptionsAdmin(admin.ModelAdmin):
    list_display = ('username', 'display_balance', 'display_closing', 'hours_per_week', 'unpaid_break', 'weekday_1', 'weekday_2', 'weekday_3', 'weekday_4', 'weekday_5', 'weekday_6', 'weekday_7')

class ActivityOptionsAdmin(admin.ModelAdmin):
    list_display = ('activity', 'username', 'rate_formatted')

    def rate_formatted(self, obj):
        return moneyformats.money(obj.rate)
    rate_formatted.short_description = _('rate')
    rate_formatted.admin_order_field = 'rate'

class ClockInForm(forms.Form):

    def __init__(self, *args, **kwargs):
        super(ClockInForm, self).__init__(*args, **kwargs)
        # Field is added on __init__ due to current-user-related queryset
        self.fields['project'] = forms.ModelChoiceField(label=_('Project'),
            queryset=Project.get_queryset_for_current_user(), required=False)

class ClockAdmin(admin.ModelAdmin):
    date_hierarchy = 'start'
    list_display = ('status_icon', 'weekday', 'start_date', 'start_time', 'end_time', 'hours_rounded', 'hours_credited_rounded', 'activity', 'rate_formatted', 'cost_formatted', 'project', 'comment')
    list_display_links = ('status_icon', 'weekday', 'start_date',)
    form = ClockForm
    ordering = ['-start']

    if 'billing' in settings.INSTALLED_APPS:
        actions = ['bill_selected']

    def queryset(self, request):
        """
        Filter the objects displayed in the change_list to only
        display those for the currently signed in user.
        """
        qs = super(ClockAdmin, self).queryset(request)
        if not request.user.has_perm('time_tracking.can_set_user'):
            qs = qs.filter(user=request.user)
        return qs

    def bill_selected(self, request, queryset):
        from billing.models import ClockBill
        bill = ClockBill()
        bill.save()
        if queryset.filter(bill=None).count() != queryset.count():
            self.message_user(request, _('Some entries were already billed and were not added to this bill.'))
        for obj in queryset.filter(bill=None):
            obj.bill = bill
            if not obj.billed_rate:
                obj.billed_rate = obj.get_rate() or 0
            if not obj.billed_time_factor:
                obj.billed_time_factor = obj.activity.time_factor
            obj.save()
        return HttpResponseRedirect(bill.get_admin_url())
    bill_selected.short_description = _('Create bill with selected %(verbose_name_plural)s')

    def add_view(self, request, form_url='', extra_context=None):
        if not request.user.has_perm('time_tracking.can_set_user'):
            self.exclude = ('user',)
        else:
            self.exclude = ()
        return super(ClockAdmin, self).add_view(request, form_url, extra_context)

    def change_view(self, request, object_id, extra_context=None):
        if not request.user.has_perm('time_tracking.can_set_user'):
            self.exclude = ('user',)
        else:
            self.exclude = ()

        return super(ClockAdmin, self).change_view(request, object_id, extra_context)

    def test_view(self, request, extra_context=None):
        request.user.message_set.create(message="yay")
        return super(ClockAdmin, self).changelist_view(request, extra_context)

    def changelist_view(self, request, extra_context=None):
        if not request.user.has_perm('time_tracking.can_set_user'):
            if 'user' in self.list_display:
                list_display = list(self.list_display)
                list_display.remove('user')
                self.list_display = tuple(list_display)
            self.list_filter = ['start', 'project', 'activity']
        else:
            if 'user' not in self.list_display:
                self.list_display += ('user',)
            self.list_filter = ['start', 'project', 'activity', 'user']

        from django.contrib.admin.views.main import ChangeList
        cl = ChangeList(request, self.model, self.list_display, self.list_display_links,
            self.list_filter, self.date_hierarchy, self.search_fields,
            self.list_select_related, self.list_per_page, self.list_max_show_all, self.list_editable, self)
        clocked_in_time = Clock.clocked_in_time(request.user)
        if clocked_in_time and clocked_in_time.project:
            # TODO this is not working
            initial = {'project': clocked_in_time.project}
        else:
            initial = {'project': Project.get_latest_for_current_user()}
        extra_context = {
            'time_info': Clock.summarize(request.user, cl.get_queryset(request)),
            'clock_in_form': ClockInForm(initial=initial),
        }

        return super(ClockAdmin, self).changelist_view(request, extra_context)

    def get_urls(self):
        from django.conf.urls.defaults import patterns, url
        urls = super(ClockAdmin, self).get_urls()
        url_patterns = patterns('',
            url(r'^in/$', self.admin_site.admin_view(self.clock_in), name="time_tracking_clock_in"),
            url(r'^out/$', self.admin_site.admin_view(self.clock_out), name="time_tracking_clock_out"),
        )
        url_patterns.extend(urls)
        return url_patterns

    def clock_in(self, request):
        if not self.has_add_permission(request):
            raise PermissionDenied
        else:
            clocked_in_time = Clock.clocked_in_time(request.user)
            project = None
            if request.method == 'POST':
                form = ClockInForm(request.POST)
                if not form.is_valid():
                    raise Exception(forms.ValidationError)
                if form.cleaned_data:
                    project = form.cleaned_data['project']
                else:
                    raise forms.ValidationError('Invalid project')

            can_clock_in = not clocked_in_time
            if clocked_in_time:
                if not project or clocked_in_time.project == project:
                    messages.add_message(request, messages.WARNING, _("Please clock out first. Clocked in: %s") % clocked_in_time.__unicode__())
                else:
                    clocked_in_time.clock_out()
                    messages.add_message(request, messages.SUCCESS, _("Clocked out: %s") % clocked_in_time.__unicode__())
                    can_clock_in = True

            if can_clock_in:
                try:
                    clock_in_time = Clock.clock_in(request.user, project)
                    if project:
                        messages.add_message(request, messages.SUCCESS, _("Clocked into %(project)s: %(clock)s") %
                        {'clock': clock_in_time.__unicode__(), 'project': project.__unicode__()})
                    else:
                        messages.add_message(request, messages.SUCCESS, _("Clocked in: %(clock)s") %
                            {'clock': clock_in_time.__unicode__()})
                except ValueError:
                    messages.add_message(request, messages.WARNING, _("In order to be able to clock in, you'll have to create a first entry."))

            return HttpResponseRedirect('../')

    def clock_out(self, request):
        if not self.has_change_permission(request):
            raise PermissionDenied
        else:
            clocked_in_time = Clock.clocked_in_time(request.user)
            if (clocked_in_time != None):
                clocked_in_time.clock_out()
                messages.add_message(request, messages.SUCCESS, _("Clocked out: %s") % clocked_in_time.__unicode__())
            else:
                messages.add_message(request, messages.WARNING, _("Please clock in first."))

            return HttpResponseRedirect('../')

    def cost_formatted(self, obj):
        return moneyformats.money(obj.get_cost())
    cost_formatted.short_description = _('cost')

    def rate_formatted(self, obj):
        return moneyformats.money(obj.get_rate())
    rate_formatted.short_description = _('rate')

class ProjectAdmin(admin.ModelAdmin):
    list_display = ('name', 'group_names', 'status', 'budget_formatted', 'hours_sum_formatted', 'cost_sum_formatted', 'balance_formatted', 'coverage_formatted')

    def group_names(self, obj):
        return ', '.join([group.__unicode__() for group in obj.groups.all()])
    group_names.short_description = _('groups')

    def budget_formatted(self, obj):
        return moneyformats.money(obj.budget)
    budget_formatted.short_description = _('budget')
    budget_formatted.admin_order_field = 'budget'

    def hours_sum_formatted(self, obj):
        return clockformats.hours(obj.sum_hours(), units=False)
    hours_sum_formatted.short_description = _('hours spent')

    def cost_sum_formatted(self, obj):
        return moneyformats.money(obj.sum_cost())
    cost_sum_formatted.short_description = _('budget spent')

    def balance_formatted(self, obj):
        return moneyformats.money(obj.balance())
    balance_formatted.short_description = _('balance')

    def coverage_formatted(self, obj):
        return moneyformats.percent(obj.coverage())
    coverage_formatted.short_description = _('coverage')

class TimeTrackingGroupAdmin(admin.ModelAdmin):
    list_display = ('name', 'user_names', 'clock_sum')

    def user_names(self, obj):
        return ', '.join([user.__unicode__() for user in obj.user_set.all()])
    user_names.short_description = _('users')

    def clock_sum(self, obj):
        return ''
        #return money(Expense.objects.filter(expense_group=obj).aggregate(Sum('amount'))['amount__sum'])
    clock_sum.short_description = _('total')

admin.site.register(Clock, ClockAdmin)
admin.site.register(Project, ProjectAdmin)
admin.site.register(ClockOptions, ClockOptionsAdmin)
admin.site.register(ActivityOptions, ActivityOptionsAdmin)
admin.site.register(Activity, ActivityAdmin)
admin.site.register(TimeTrackingGroup, TimeTrackingGroupAdmin)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import
import logging
import urllib2
from urllib import urlencode

from .response_handler import XMLResponse
from .error import HTTPError
__all__ = ['HTTPClientBase', 'HTTPClient']

class HTTPClientBase(object):
    def __init__(self, host):
        super(HTTPClientBase, self).__init__()
        self.host = host

    def get(self, uri, qry=None):
        raise NotImplementedError

    def post(self, uri, data):
        raise NotImplementedError

class HTTPClient(HTTPClientBase):
    """Used to handle POST and GET requests.

    This class really just handles building the request and transforming the
    response.

    Attributes:
        host (str): This will be used when building the URL.
        headers (dict): The headers that are sent in the requests.
        handle_response: This function is called for all requests and is passed
            the results of the request as a string.
    """

    def __init__(self, host, response_handler=None):
        """Init the HTTPClient

        Args:
            host (str): This is usually a domain.
            response_handler: This function must take 1 argument and return
                something.
        """
        super(HTTPClient, self).__init__(host)
        self.headers = {
            'Accept-Encoding': 'gzip, deflate',
            'User-Agent': 'Python:FunimationLater:v0.0.1'
        }
        if response_handler is None:
            self.handle_response = XMLResponse
        else:
            self.handle_response = response_handler
        self._log = logging.getLogger(__name__)

    def get(self, uri, qry=None):
        """Send a GET request to `host` + `uri`

        Args:
            uri (str): This will be concatenated to `host`.
            qry ([dict]): Optional query string to add to the URL.

        Returns: Whatever is returned by `handle_response`.
        """
        if qry:
            query = urlencode(qry) if isinstance(qry, dict) else qry
            uri = '{}?{}'.format(uri, query)
        return self._request(uri)

    def post(self, uri, data):
        """Send a POST request to `host` + `uri` with `data` as the body.

        Args:
            uri (str): This will be concatenated to `host`.
            data (dict): Data is urlencoded before the request is sent.

        Returns: Whatever is returned by `handle_response`.
        """
        return self._request(uri, urlencode(data))

    def add_headers(self, headers):
        """Add headers to all requests.

        Args:
            headers (dict): Will overwrite existing keys
        """
        if not isinstance(headers, dict):
            raise TypeError('argument must be of type `dict`')
        self.headers.update(headers)

    def _request(self, uri, data=None):
        req = self._create_request(uri)
        try:
            resp = urllib2.urlopen(req, data)
            handler = self.handle_response(resp.read(), req)
            return handler.handle()
        except urllib2.HTTPError as err:
            raise HTTPError(err.filename, err.code, err.msg, err.hdrs, err.fp)

    def _create_request(self, uri):
        """Builds :class:`urllib2.Request` object using `uri` and sets the
        headers to `headers`.

        Args:
            uri (str): This will be concatenated to `host`

        Returns:
            urllib2.Request: A request object that will be used by
                :class:`urllib2.urlopen`
        """
        req = urllib2.Request(self._build_url(uri), headers=self.headers)
        self._log.debug(
            'Calling %s on %s', req.get_method(), req.get_full_url())
        return req

    def _build_url(self, uri):
        if uri[0] == '/':
            return self.host + uri
        else:
            return self.host + '/' + uri
<commit_msg>If a full URL is used don't prepend the base URL.<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import
import logging
import urllib2
from urllib import urlencode

from .response_handler import XMLResponse
from .error import HTTPError
__all__ = ['HTTPClientBase', 'HTTPClient']

class HTTPClientBase(object):
    def __init__(self, host):
        super(HTTPClientBase, self).__init__()
        self.host = host

    def get(self, uri, qry=None):
        raise NotImplementedError

    def post(self, uri, data):
        raise NotImplementedError

class HTTPClient(HTTPClientBase):
    """Used to handle POST and GET requests.

    This class really just handles building the request and transforming the
    response.

    Attributes:
        host (str): This will be used when building the URL.
        headers (dict): The headers that are sent in the requests.
        handle_response: This function is called for all requests and is passed
            the results of the request as a string.
    """

    def __init__(self, host, response_handler=None):
        """Init the HTTPClient

        Args:
            host (str): This is usually a domain.
            response_handler: This function must take 1 argument and return
                something.
        """
        super(HTTPClient, self).__init__(host)
        self.headers = {
            'Accept-Encoding': 'gzip, deflate',
            'User-Agent': 'Python:FunimationLater:v0.0.1'
        }
        if response_handler is None:
            self.handle_response = XMLResponse
        else:
            self.handle_response = response_handler
        self._log = logging.getLogger(__name__)

    def get(self, uri, qry=None):
        """Send a GET request to `host` + `uri`

        Args:
            uri (str): This will be concatenated to `host`.
            qry ([dict]): Optional query string to add to the URL.

        Returns: Whatever is returned by `handle_response`.
        """
        if qry:
            query = urlencode(qry) if isinstance(qry, dict) else qry
            uri = '{}?{}'.format(uri, query)
        return self._request(uri)

    def post(self, uri, data):
        """Send a POST request to `host` + `uri` with `data` as the body.

        Args:
            uri (str): This will be concatenated to `host`.
            data (dict): Data is urlencoded before the request is sent.

        Returns: Whatever is returned by `handle_response`.
        """
        return self._request(uri, urlencode(data))

    def add_headers(self, headers):
        """Add headers to all requests.

        Args:
            headers (dict): Will overwrite existing keys
        """
        if not isinstance(headers, dict):
            raise TypeError('argument must be of type `dict`')
        self.headers.update(headers)

    def _request(self, uri, data=None):
        req = self._create_request(uri)
        try:
            resp = urllib2.urlopen(req, data)
            handler = self.handle_response(resp.read(), req)
            return handler.handle()
        except urllib2.HTTPError as err:
            raise HTTPError(err.filename, err.code, err.msg, err.hdrs, err.fp)

    def _create_request(self, uri):
        """Builds :class:`urllib2.Request` object using `uri` and sets the
        headers to `headers`.

        Args:
            uri (str): This will be concatenated to `host`

        Returns:
            urllib2.Request: A request object that will be used by
                :class:`urllib2.urlopen`
        """
        req = urllib2.Request(self._build_url(uri), headers=self.headers)
        self._log.debug(
            'Calling %s on %s', req.get_method(), req.get_full_url())
        return req

    def _build_url(self, uri):
        if uri.startswith('http'):
            return uri
        if uri[0] == '/':
            return self.host + uri
        else:
            return self.host + '/' + uri
<|endoftext|>


<commit_before>'''
Adaptation of tincan API for Python to work with latest tincan.
Contains lists of verbs and definition of activities specifically
for the COACH project.

Auth: Sander Latour, Auke Wiggers
Date: 29-07-2013
'''

from requests.auth import HTTPBasicAuth
from urlparse import urljoin
import requests
import json
import urllib
import uuid

class TinCan(object):
    VERSIONHEADER = "X-Experience-API-Version"
    VERSION = "1.0.0"
    VERBS = {'launched': {'id': 'http://adlnet.gov/expapi/verbs/launched',
                                                'display': {'en-US': 'launched'}},
                     'interacted': {'id': 'http://adlnet.gov/expapi/verbs/interacted',
                                                    'display': {'en-US': 'interacted'}},
                     'progressed': {'id': 'http://adlnet.gov/expapi/verbs/progressed',
                                                    'display': {'en-US': 'progressed'}},
                     'answered': {'id': 'http://adlnet.gov/expapi/verbs/answererd',
                                                'display': {'en-US': 'answered'}},
                     'suspended': {'id':    'http://adlnet.gov/expapi/verbs/suspended',
                                                 'display': {'en-US': 'suspended'}},
                     'completed': {'id':    'http://adlnet.gov/expapi/verbs/completed',
                                                 'display': {'en-US': 'completed'}}}
    ACTIVITY_TYPES = {
             'assessment': 'http://adlnet.gov/expapi/activities/assessment',
             'media': 'http://adlnet.gov/expapi/activities/media',
             'question': 'http://adlnet.gov/expapi/activities/question'
                                     }

    def __init__(self, userName, secret, endpoint, logger=None):
        self._userName = userName
        self._secret = secret
        self._endpoint = endpoint
        self.logger = logger

    def submitStatement(self, jsonObject):
        ##Attempts to submit a single statement
        try:
            ##Validates that the verb is valid
            #if(not dataValidation.validateVerb(jsonObject['verb'])):
            #    raise ValueError("INVALID VERB: "+jsonObject['verb'])

            resp = requests.post(self._endpoint,
                                        data=json.dumps(jsonObject),
                                        auth=HTTPBasicAuth(self._userName,self._secret),
                                        headers={"Content-Type":"application/json",
                                                         self.VERSIONHEADER:self.VERSION})

        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)

    def submitStatementList(self, jsonObjectList):
        ##Submits a list of Statements
        for statement in jsonObjectList:
            try:
                ##Validates that the verb is valid
                #if(not dataValidation.validateVerb(statement['verb'])):
                #    raise ValueError("INVALID VERB: "+statement['verb'])

                resp = requests.post(self._endpoint,
                                        data=json.dumps(statement),
                                        auth=HTTPBasicAuth(self._userName,self._secret),
                                        headers={"Content-Type":"application/json",
                                                         self.VERSIONHEADER:self.VERSION})
            except IOError as e:
                if self.logger is not None:
                    self.logger.error(e)
                else:
                    print e

    def getStatementByID(self, ID):
        ##Attempts to retrieve a statement by its ID
        try:
            url = self._endpoint+"?statementId="+ID
            resp = requests.get(url,
                                auth=HTTPBasicAuth(self._userName, self._secret),
                                headers={"Content-Type":"application/json",
                                                 self.VERSIONHEADER:self.VERSION})
            return resp.json()
        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)

    def getAllStatements(self):
        ##Attempts to retrieve every TinCan Statement from the End point
        try:
            endpoint = self._endpoint
            statements = []
            while endpoint is not None:
                try:
                    resp = requests.get(endpoint,
                                        auth=HTTPBasicAuth(self._userName, self._secret),
                                        headers={"Content-Type" : "application/json",
                                                         self.VERSIONHEADER : self.VERSION})
                except ConnectionError as e:
                    if self.logger is not None:
                        self.logger.error(e)
                    return statements
                result = resp.json()
                statements = statements + result["statements"]
                if "more" in result and result["more"]:
                    endpoint = urljoin(endpoint, result["more"])
                else:
                    endpoint = None
            return statements
        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)

    def getFilteredStatements(self, inputDict):
        queryObject = {}
        for key in ['result', 'agent', 'context', 'timestamp',
                                'verb', 'object',
                                'stored', 'authority', 'version', 'attachments']:
            if key in inputDict:
                queryObject[key] = inputDict[key]

        ##Encodes the query object into a query string
        url = self._endpoint +"?"+ urllib.urlencode(queryObject)
        ##If the URL Length exceeds max URL length then query using post
        if (len(url)> 2048):
            resp = requests.post(self._endpoint,
                                 data = queryObject,
                                 auth = HTTPBasicAuth(self._userName,self._secret),
                                 headers = {"Content-Type":"application/json",
                                                     self.VERSIONHEADER:self.VERSION})
            return resp.json()
        else:
            resp = requests.get(url,
                                auth = HTTPBasicAuth(self._userName,self._secret),
                                headers = {"Content-Type":"application/json",
                                                 self.VERSIONHEADER:self.VERSION})
            return resp.json()

<commit_msg>Tincan API now follows 'more' link for filtered queries.<commit_after>'''
Adaptation of tincan API for Python to work with latest tincan.
Contains lists of verbs and definition of activities specifically
for the COACH project.

Auth: Sander Latour, Auke Wiggers
Date: 29-07-2013
'''

from requests.auth import HTTPBasicAuth
from urlparse import urljoin
import requests
import json
import urllib
import uuid

class TinCan(object):
    VERSIONHEADER = "X-Experience-API-Version"
    VERSION = "1.0.0"
    VERBS = {'launched': {'id': 'http://adlnet.gov/expapi/verbs/launched',
                                                'display': {'en-US': 'launched'}},
                     'interacted': {'id': 'http://adlnet.gov/expapi/verbs/interacted',
                                                    'display': {'en-US': 'interacted'}},
                     'progressed': {'id': 'http://adlnet.gov/expapi/verbs/progressed',
                                                    'display': {'en-US': 'progressed'}},
                     'answered': {'id': 'http://adlnet.gov/expapi/verbs/answererd',
                                                'display': {'en-US': 'answered'}},
                     'suspended': {'id':    'http://adlnet.gov/expapi/verbs/suspended',
                                                 'display': {'en-US': 'suspended'}},
                     'completed': {'id':    'http://adlnet.gov/expapi/verbs/completed',
                                                 'display': {'en-US': 'completed'}}}
    ACTIVITY_TYPES = {
             'assessment': 'http://adlnet.gov/expapi/activities/assessment',
             'media': 'http://adlnet.gov/expapi/activities/media',
             'question': 'http://adlnet.gov/expapi/activities/question'
                                     }

    def __init__(self, userName, secret, endpoint, logger=None):
        self._userName = userName
        self._secret = secret
        self._endpoint = endpoint
        self.logger = logger

    def submitStatement(self, jsonObject):
        ##Attempts to submit a single statement
        try:
            ##Validates that the verb is valid
            #if(not dataValidation.validateVerb(jsonObject['verb'])):
            #    raise ValueError("INVALID VERB: "+jsonObject['verb'])

            resp = requests.post(self._endpoint,
                                        data=json.dumps(jsonObject),
                                        auth=HTTPBasicAuth(self._userName,self._secret),
                                        headers={"Content-Type":"application/json",
                                                         self.VERSIONHEADER:self.VERSION})

        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)

    def submitStatementList(self, jsonObjectList):
        ##Submits a list of Statements
        for statement in jsonObjectList:
            try:
                ##Validates that the verb is valid
                #if(not dataValidation.validateVerb(statement['verb'])):
                #    raise ValueError("INVALID VERB: "+statement['verb'])

                resp = requests.post(self._endpoint,
                                        data=json.dumps(statement),
                                        auth=HTTPBasicAuth(self._userName,self._secret),
                                        headers={"Content-Type":"application/json",
                                                         self.VERSIONHEADER:self.VERSION})
            except IOError as e:
                if self.logger is not None:
                    self.logger.error(e)
                else:
                    print e

    def getStatementByID(self, ID):
        ##Attempts to retrieve a statement by its ID
        try:
            url = self._endpoint+"?statementId="+ID
            resp = requests.get(url,
                                auth=HTTPBasicAuth(self._userName, self._secret),
                                headers={"Content-Type":"application/json",
                                                 self.VERSIONHEADER:self.VERSION})
            return resp.json()
        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)

    def getAllStatements(self):
        ##Attempts to retrieve every TinCan Statement from the End point
        try:
            endpoint = self._endpoint
            statements = []
            while endpoint is not None:
                try:
                    resp = requests.get(endpoint,
                                        auth=HTTPBasicAuth(self._userName, self._secret),
                                        headers={"Content-Type" : "application/json",
                                                         self.VERSIONHEADER : self.VERSION})
                except ConnectionError as e:
                    if self.logger is not None:
                        print "Error getting statements."
                        self.logger.error(e)
                    return statements
                result = resp.json()
                statements = statements + result["statements"]
                if "more" in result and result["more"]:
                    endpoint = urljoin(endpoint, result["more"])
                else:
                    endpoint = None
            return statements
        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)

    def getFilteredStatements(self, inputDict):
        ##Attempts to retrieve every TinCan Statement from the End point
        queryObject = {}
        for key in ['result', 'agent', 'context', 'timestamp',
                                'verb', 'object',
                                'stored', 'authority', 'version', 'attachments']:
            if key in inputDict:
                queryObject[key] = inputDict[key]
        self._endpoint = self._endpoint +"?"+ urllib.urlencode(queryObject)
        try:
            endpoint = self._endpoint
            statements = []
            while endpoint is not None:
                try:
                    if (len(endpoint)> 2048):
                        resp = requests.post(self._endpoint,
                                             data = queryObject,
                                             auth = HTTPBasicAuth(self._userName,self._secret),
                                             headers = {"Content-Type":"application/json",
                                                                 self.VERSIONHEADER:self.VERSION})
                    else:
                        resp = requests.get(endpoint,
                                            auth = HTTPBasicAuth(self._userName,self._secret),
                                            headers = {"Content-Type":"application/json",
                                                             self.VERSIONHEADER:self.VERSION})
                except ConnectionError as e:
                    if self.logger is not None:
                        print "Error getting statements."
                        self.logger.error(e)
                    return statements
                result = resp.json()
                statements = statements + result["statements"]
                if "more" in result and result["more"]:
                    endpoint = urljoin(endpoint, result["more"])
                else:
                    endpoint = None
            return statements
        except IOError as e:
            if self.logger is not None:
                self.logger.error(e)
<|endoftext|>


<commit_before><commit_msg>Добавил метод, уменьшающий энергию дракона.<commit_after><|endoftext|>


<commit_before># coding: utf-8

""" Astropy coordinate class for the Sagittarius coordinate system """

from __future__ import division, print_function

__author__ = "adrn <adrn@astro.columbia.edu>"

# Third-party
import numpy as np
from numpy import cos, sin

from astropy.coordinates import frame_transform_graph
from astropy.coordinates.angles import rotation_matrix
import astropy.coordinates as coord
import astropy.units as u

__all__ = ["Sagittarius"]

class Sagittarius(coord.BaseCoordinateFrame):
    """
    A Heliocentric spherical coordinate system defined by the orbit
    of the Sagittarius dwarf galaxy, as described in
    `this paper <http://adsabs.harvard.edu/abs/2003ApJ...599.1082M>`_
    and further explained at
    `this website <http://www.astro.virginia.edu/~srm4n/Sgr/>`_.

    For more information about this class, see the Astropy documentation
    on `Coordinate Frames <http://docs.astropy.org/en/latest/coordinates/frames.html>`_.

    Parameters
    ----------
    representation : `BaseRepresentation` or None
        A representation object or None to have no data (or use the other keywords)
    Lambda : `Angle`, optional, must be keyword
        The longitude-like angle corresponding to Sagittarius' orbit.
    Beta : `Angle`, optional, must be keyword
        The latitude-like angle corresponding to Sagittarius' orbit.
    distance : `Quantity`, optional, must be keyword
        The Distance for this object along the line-of-sight.

    """
    default_representation = coord.SphericalRepresentation

    frame_specific_representation_info = {
        'spherical': [coord.RepresentationMapping('lon', 'Lambda'),
                      coord.RepresentationMapping('lat', 'Beta'),
                      coord.RepresentationMapping('distance', 'distance')],
        'unitspherical': [coord.RepresentationMapping('lon', 'Lambda'),
                          coord.RepresentationMapping('lat', 'Beta')]
    }

# Define the Euler angles (from Law & Majewski 2010)
phi = np.radians(180+3.75)
theta = np.radians(90-13.46)
psi = np.radians(180+14.111534)

# Generate the rotation matrix using the x-convention (see Goldstein)
D = rotation_matrix(phi, "z", unit=u.radian)
C = rotation_matrix(theta, "x", unit=u.radian)
B = rotation_matrix(psi, "z", unit=u.radian)
R = np.array(B.dot(C).dot(D))

# Galactic to Sgr coordinates
@frame_transform_graph.transform(coord.StaticMatrixTransform, coord.Galactic, Sagittarius)
def galactic_to_sgr():
    """ Compute the transformation from Galactic spherical to
        heliocentric Orphan coordinates.
    """
    return R

# Sgr to Galactic coordinates
@frame_transform_graph.transform(coord.StaticMatrixTransform, Sagittarius, coord.Galactic)
def sgr_to_galactic():
    """ Compute the transformation from heliocentric Orphan coordinates to
        spherical Galactic.
    """
    return galactic_to_sgr().T
<commit_msg>fix flip z axis<commit_after># coding: utf-8

""" Astropy coordinate class for the Sagittarius coordinate system """

from __future__ import division, print_function

__author__ = "adrn <adrn@astro.columbia.edu>"

# Third-party
import numpy as np
from numpy import cos, sin

from astropy.coordinates import frame_transform_graph
from astropy.coordinates.angles import rotation_matrix
import astropy.coordinates as coord
import astropy.units as u

__all__ = ["Sagittarius"]

class Sagittarius(coord.BaseCoordinateFrame):
    """
    A Heliocentric spherical coordinate system defined by the orbit
    of the Sagittarius dwarf galaxy, as described in
    `this paper <http://adsabs.harvard.edu/abs/2003ApJ...599.1082M>`_
    and further explained at
    `this website <http://www.astro.virginia.edu/~srm4n/Sgr/>`_.

    For more information about this class, see the Astropy documentation
    on `Coordinate Frames <http://docs.astropy.org/en/latest/coordinates/frames.html>`_.

    Parameters
    ----------
    representation : `BaseRepresentation` or None
        A representation object or None to have no data (or use the other keywords)
    Lambda : `Angle`, optional, must be keyword
        The longitude-like angle corresponding to Sagittarius' orbit.
    Beta : `Angle`, optional, must be keyword
        The latitude-like angle corresponding to Sagittarius' orbit.
    distance : `Quantity`, optional, must be keyword
        The Distance for this object along the line-of-sight.

    """
    default_representation = coord.SphericalRepresentation

    frame_specific_representation_info = {
        'spherical': [coord.RepresentationMapping('lon', 'Lambda'),
                      coord.RepresentationMapping('lat', 'Beta'),
                      coord.RepresentationMapping('distance', 'distance')],
        'unitspherical': [coord.RepresentationMapping('lon', 'Lambda'),
                          coord.RepresentationMapping('lat', 'Beta')]
    }

# Define the Euler angles (from Law & Majewski 2010)
phi = np.radians(180+3.75)
theta = np.radians(90-13.46)
psi = np.radians(180+14.111534)

# Generate the rotation matrix using the x-convention (see Goldstein)
D = rotation_matrix(phi, "z", unit=u.radian)
C = rotation_matrix(theta, "x", unit=u.radian)
B = rotation_matrix(psi, "z", unit=u.radian)
A = np.diag([1.,1.,-1.])
R = np.array(A.dot(B).dot(C).dot(D))

# Galactic to Sgr coordinates
@frame_transform_graph.transform(coord.StaticMatrixTransform, coord.Galactic, Sagittarius)
def galactic_to_sgr():
    """ Compute the transformation from Galactic spherical to
        heliocentric Orphan coordinates.
    """
    return R

# Sgr to Galactic coordinates
@frame_transform_graph.transform(coord.StaticMatrixTransform, Sagittarius, coord.Galactic)
def sgr_to_galactic():
    """ Compute the transformation from heliocentric Orphan coordinates to
        spherical Galactic.
    """
    return galactic_to_sgr().T

# # Galactic to Sgr coordinates
# @frame_transform_graph.transform(coord.FunctionTransform, coord.Galactic, Sagittarius)
# def galactic_to_sgr(gal_coord, sgr_frame):
#     """ Compute the transformation from Galactic spherical to
#         heliocentric Sgr coordinates.
#     """

#     l = np.atleast_1d(gal_coord.l.radian)
#     b = np.atleast_1d(gal_coord.b.radian)

#     X = cos(b)*cos(l)
#     Y = cos(b)*sin(l)
#     Z = sin(b)

#     # Calculate X,Y,Z,distance in the Sgr system
#     Xs, Ys, Zs = sgr_matrix.dot(np.array([X, Y, Z]))
#     Zs = -Zs

#     # Calculate the angular coordinates lambda,beta
#     Lambda = np.arctan2(Ys, Xs)*u.radian
#     Lambda[Lambda < 0] = Lambda[Lambda < 0] + 2.*np.pi*u.radian
#     Beta = np.arcsin(Zs/np.sqrt(Xs*Xs+Ys*Ys+Zs*Zs))*u.radian

#     return Sagittarius(Lambda=Lambda, Beta=Beta,
#                        distance=gal_coord.distance)

# # Sgr to Galactic coordinates
# @frame_transform_graph.transform(coord.FunctionTransform, Sagittarius, coord.Galactic)
# def sgr_to_galactic(sgr_coord, gal_frame):
#     """ Compute the transformation from heliocentric Sgr coordinates to
#         spherical Galactic.
#     """
#     L = np.atleast_1d(sgr_coord.Lambda.radian)
#     B = np.atleast_1d(sgr_coord.Beta.radian)

#     Xs = cos(B)*cos(L)
#     Ys = cos(B)*sin(L)
#     Zs = sin(B)
#     Zs = -Zs

#     X, Y, Z = sgr_matrix.T.dot(np.array([Xs, Ys, Zs]))

#     l = np.arctan2(Y, X)*u.radian
#     b = np.arcsin(Z/np.sqrt(X*X+Y*Y+Z*Z))*u.radian

#     l[l<0] += 2*np.pi*u.radian

#     return coord.Galactic(l=l, b=b, distance=sgr_coord.distance)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""\
This is a python port of "Goose" orignialy licensed to Gravity.com
under one or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.

Python port was written by Xavier Grangier for Recrutae

Gravity.com licenses this file
to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import six
import requests

class NetworkError(RuntimeError):
    def __init__(self, status_code, reason):
        self.reason = reason
        self.status_code = status_code

class NetworkFetcher(object):

    def __init__(self, config):
        self.config = config
        self._connection = requests.Session()
        self._connection.headers = {'User-agent': self.config.browser_user_agent}

        self._url = None

    def get_url(self):
        return self._url

    def fetch(self, url):
        # utf-8 encode unicode url
        if isinstance(url, six.text_type) and six.PY2:
            url = url.encode('utf-8')

        response = self._connection.get(url, timeout=self.config.http_timeout)
        if response.ok:
            self._url = response.url
            text = response.content
        else:
            self._url = None
            text = None
            if self.config.strict:
                raise NetworkError(response.status_code, response.reason)

        return text
<commit_msg>Do not remove other headers when setting `User-agent`<commit_after># -*- coding: utf-8 -*-
"""\
This is a python port of "Goose" orignialy licensed to Gravity.com
under one or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.

Python port was written by Xavier Grangier for Recrutae

Gravity.com licenses this file
to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import six
import requests

class NetworkError(RuntimeError):
    def __init__(self, status_code, reason):
        self.reason = reason
        self.status_code = status_code

class NetworkFetcher(object):

    def __init__(self, config):
        self.config = config
        self._connection = requests.Session()
        self._connection.headers['User-agent'] = self.config.browser_user_agent

        self._url = None

    def get_url(self):
        return self._url

    def fetch(self, url):
        # utf-8 encode unicode url
        if isinstance(url, six.text_type) and six.PY2:
            url = url.encode('utf-8')

        response = self._connection.get(url, timeout=self.config.http_timeout)
        if response.ok:
            self._url = response.url
            text = response.content
        else:
            self._url = None
            text = None
            if self.config.strict:
                raise NetworkError(response.status_code, response.reason)

        return text
<|endoftext|>


<commit_before>#!/usr/bin/python
from __future__ import print_function

from argparse import ArgumentParser
import shutil
import os
import subprocess
import sys
import tarfile
import traceback

from utility import temp_dir

class WorkingDirectory:
    """Context manager for changing the current working directory"""
    def __init__(self, working_path):
        self.working_path = working_path

    def __enter__(self):
        self.savedPath = os.getcwd()
        os.chdir(self.working_path)

    def __exit__(self, etype, value, traceback):
        os.chdir(self.savedPath)

def run(*command, **kwargs):
    """Run a command and return the stdout and stderr output."""
    returncode = 0
    kwargs['stderr'] = subprocess.STDOUT
    try:
        output = subprocess.check_output(command, **kwargs)
    except subprocess.CalledProcessError as e:
        returncode = e.returncode
        output = e.output
    return returncode, output

def untar_gopath(tarfile_path, gopath, delete=False, verbose=False):
    """Untar the tarfile to the gopath."""
    with temp_dir() as tmp_dir:
        with tarfile.open(name=tarfile_path, mode='r:gz') as tar:
            tar.extractall(path=tmp_dir)
        if verbose:
            print('Extracted the Juju source.')
        dir_name = os.path.basename(tarfile_path).replace('.tar.gz', '')
        dir_path = os.path.join(tmp_dir, dir_name)
        shutil.move(dir_path, gopath)
        if verbose:
            print('Moved %s to %s' % (dir_name, gopath))
    if delete:
        os.unlink(tarfile_path)
        if verbose:
            print('Deleted %s' % tarfile_path)

def go_test_package(package, go_cmd, gopath, verbose=False):
    """Run the package unit tests."""
    # Set GOPATH and GOARCH to ensure the go command tests extracted
    # tarfile using the arch the win-agent is compiled with. The
    # default go env might be 386 used to create a win client.
    env = dict(os.environ)
    env['GOPATH'] = gopath
    env['GOARCH'] = 'amd64'
    package_dir = os.path.join(gopath, 'src', package.replace('/', os.sep))
    with WorkingDirectory(package_dir):
        if verbose:
            print('Running unit tests in %s' % package)
        returncode, output = run(go_cmd, 'test', './...', env=env)
        print(output)
        if verbose:
            if returncode == 0:
                print('SUCCESS')
            else:
                print('FAIL')
    return returncode

def parse_args(args=None):
    """Return parsed args for this program."""
    parser = ArgumentParser("Run go test against the content of a tarfile.")
    parser.add_argument(
        '-v', '--verbose', action='store_true', default=False,
        help='Increase verbosity.')
    parser.add_argument(
        '-g', '--go', default='go', help='The go comand.')
    parser.add_argument(
        '-p', '--package', default='github.com/juju/juju',
        help='The package to test.')
    parser.add_argument(
        '-r', '--remove-tarfile', action='store_true', default=False,
        help='Remove the tarfile after extraction.')
    parser.add_argument(
        'tarfile', help='The path to the gopath tarfile.')
    return parser.parse_args(args)

def main(argv=None):
    """Run go test against the content of a tarfile."""
    returncode = 0
    args = parse_args(argv)
    tarfile_path = args.tarfile
    tarfile_name = os.path.basename(tarfile_path)
    version = tarfile_name.split('_')[-1].replace('.tar.gz', '')
    try:
        raise ValueError('curtis wants fail.')
        if args.verbose:
            print('Testing juju %s from %s' % (version, tarfile_name))
        with temp_dir() as workspace:
            gopath = os.path.join(workspace, 'gogo')
            untar_gopath(
                tarfile_path, gopath, delete=args.remove_tarfile,
                verbose=args.verbose)
            returncode = go_test_package(
                args.package, args.go, gopath, verbose=args.verbose)
    except Exception as e:
        print(str(e))
        print(traceback.print_exc())
        return 3
    return returncode

if __name__ == '__main__':
    sys.exit(main())
<commit_msg>Remove errant raise of exception.<commit_after>#!/usr/bin/python
from __future__ import print_function

from argparse import ArgumentParser
import shutil
import os
import subprocess
import sys
import tarfile
import traceback

from utility import temp_dir

class WorkingDirectory:
    """Context manager for changing the current working directory"""
    def __init__(self, working_path):
        self.working_path = working_path

    def __enter__(self):
        self.savedPath = os.getcwd()
        os.chdir(self.working_path)

    def __exit__(self, etype, value, traceback):
        os.chdir(self.savedPath)

def run(*command, **kwargs):
    """Run a command and return the stdout and stderr output."""
    returncode = 0
    kwargs['stderr'] = subprocess.STDOUT
    try:
        output = subprocess.check_output(command, **kwargs)
    except subprocess.CalledProcessError as e:
        returncode = e.returncode
        output = e.output
    return returncode, output

def untar_gopath(tarfile_path, gopath, delete=False, verbose=False):
    """Untar the tarfile to the gopath."""
    with temp_dir() as tmp_dir:
        with tarfile.open(name=tarfile_path, mode='r:gz') as tar:
            tar.extractall(path=tmp_dir)
        if verbose:
            print('Extracted the Juju source.')
        dir_name = os.path.basename(tarfile_path).replace('.tar.gz', '')
        dir_path = os.path.join(tmp_dir, dir_name)
        shutil.move(dir_path, gopath)
        if verbose:
            print('Moved %s to %s' % (dir_name, gopath))
    if delete:
        os.unlink(tarfile_path)
        if verbose:
            print('Deleted %s' % tarfile_path)

def go_test_package(package, go_cmd, gopath, verbose=False):
    """Run the package unit tests."""
    # Set GOPATH and GOARCH to ensure the go command tests extracted
    # tarfile using the arch the win-agent is compiled with. The
    # default go env might be 386 used to create a win client.
    env = dict(os.environ)
    env['GOPATH'] = gopath
    env['GOARCH'] = 'amd64'
    package_dir = os.path.join(gopath, 'src', package.replace('/', os.sep))
    with WorkingDirectory(package_dir):
        if verbose:
            print('Running unit tests in %s' % package)
        returncode, output = run(go_cmd, 'test', './...', env=env)
        print(output)
        if verbose:
            if returncode == 0:
                print('SUCCESS')
            else:
                print('FAIL')
    return returncode

def parse_args(args=None):
    """Return parsed args for this program."""
    parser = ArgumentParser("Run go test against the content of a tarfile.")
    parser.add_argument(
        '-v', '--verbose', action='store_true', default=False,
        help='Increase verbosity.')
    parser.add_argument(
        '-g', '--go', default='go', help='The go comand.')
    parser.add_argument(
        '-p', '--package', default='github.com/juju/juju',
        help='The package to test.')
    parser.add_argument(
        '-r', '--remove-tarfile', action='store_true', default=False,
        help='Remove the tarfile after extraction.')
    parser.add_argument(
        'tarfile', help='The path to the gopath tarfile.')
    return parser.parse_args(args)

def main(argv=None):
    """Run go test against the content of a tarfile."""
    returncode = 0
    args = parse_args(argv)
    tarfile_path = args.tarfile
    tarfile_name = os.path.basename(tarfile_path)
    version = tarfile_name.split('_')[-1].replace('.tar.gz', '')
    try:
        if args.verbose:
            print('Testing juju %s from %s' % (version, tarfile_name))
        with temp_dir() as workspace:
            gopath = os.path.join(workspace, 'gogo')
            untar_gopath(
                tarfile_path, gopath, delete=args.remove_tarfile,
                verbose=args.verbose)
            returncode = go_test_package(
                args.package, args.go, gopath, verbose=args.verbose)
    except Exception as e:
        print(str(e))
        print(traceback.print_exc())
        return 3
    return returncode

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


<commit_before>from random import random, randint

class Chromosome:
    def __init__(self, tactics):
        self.chromosome = []
        chromosomeLength = randint(4, 15)
        print(chromosomeLength)
        for fragNum in range(chromosomeLength):
            tactic = tactics[randint(0, len(tactics)-1)]
            if len(self.chromosome) == 0:
                self.chromosome.append(tactic)
            else:
                while tactic[1] is False and (tactic == self.chromosome[-1]):
                    tactic = tactics[randint(0, len(tactics)-1)]
                self.chromosome.append(tactic)

    def showChromosome(self):
        print(self.chromosome)
<commit_msg>remove debug message<commit_after>from random import random, randint

class Chromosome:
    def __init__(self, tactics):
        self.chromosome = []
        chromosomeLength = randint(4, 15)
        for fragNum in range(chromosomeLength):
            tactic = tactics[randint(0, len(tactics)-1)]
            if len(self.chromosome) == 0:
                self.chromosome.append(tactic)
            else:
                while tactic[1] is False and (tactic == self.chromosome[-1]):
                    tactic = tactics[randint(0, len(tactics)-1)]
                self.chromosome.append(tactic)

    def showChromosome(self):
        print(self.chromosome)
<|endoftext|>


<commit_before>from datetime import date, datetime
import pickle
import os.path

from dateutil.relativedelta import relativedelta
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from tzlocal import get_localzone

from .serializers.event_serializer import EventSerializer
from .util.date_time_util import insure_localisation

def _get_default_credentials_path():
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir, 'credentials.json')
    return credential_path

class SendUpdatesMode:
    """ Possible values of the mode for sending updates or invitations to attendees.

    * ALL - Send updates to all participants. This is the default value.
    * EXTERNAL_ONLY - Send updates only to attendees not using google calendar.
    * NONE - Do not send updates.
    """

    ALL = "all"
    EXTERNAL_ONLY = "externalOnly"
    NONE = "none"

class GoogleCalendar:
    _READ_WRITE_SCOPES = 'https://www.googleapis.com/auth/calendar'
    _LIST_ORDERS = ("startTime", "updated")

    def __init__(self,
                 calendar='primary',
                 *,
                 credentials_path=None,
                 token_path=None,
                 read_only=False,
                 application_name=None
                 ):
        """Represents Google Calendar of the user.

        :param calendar:
                Users email address or name/id of the calendar. Default: primary calendar of the user
        :param credentials_path:
                Path to "credentials.json" file. Default: ~/.credentials
        :param token_path:
                Existing path to load the token from, or path to save the token after initial authentication flow.
                Default: "token.pickle" in the same directory as the credentials_path
        :param read_only:
                If require read only access. Default: False
        :param application_name:
                Name of the application. Default: None
        """
        credentials_path = credentials_path or _get_default_credentials_path()
        self._credentials_dir, self._credentials_file = os.path.split(credentials_path)

        self._scopes = [self._READ_WRITE_SCOPES + ('.readonly' if read_only else '')]
        self._application_name = application_name
        self._token_path = token_path or os.path.join(self._credentials_dir, 'token.pickle')

        self.calendar = calendar
        credentials = self._get_credentials()
        self.service = build('calendar', 'v3', credentials=credentials)

    def _get_credentials(self):
        _credentials_path = os.path.join(self._credentials_dir, self._credentials_file)

        credentials = None

        if os.path.exists(self._token_path):
            with open(self._token_path, 'rb') as token:
                credentials = pickle.load(token)

        if not credentials or not credentials.valid:
            if credentials and credentials.expired and credentials.refresh_token:
                credentials.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(_credentials_path, self._scopes)
                credentials = flow.run_local_server()

            with open(self._token_path, 'wb') as token:
                pickle.dump(credentials, token)

        return credentials

    def add_event(self, event, send_updates=SendUpdatesMode.NONE):
        """Creates event in the calendar

        :param event:
                Event object.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".

        :return:
                Created event object with id.
        """
        body = EventSerializer(event).get_json()
        event_json = (
            self.service.events()
            .insert(
                calendarId=self.calendar,
                body=body,
                conferenceDataVersion=1,
                sendUpdates=send_updates,
            )
            .execute()
        )
        return EventSerializer.to_object(event_json)

    def add_quick_event(self, event_string, send_updates=SendUpdatesMode.NONE):
        """Creates event in the calendar by string description.

        Example:
            Appointment at Somewhere on June 3rd 10am-10:25am

        :param event_string:
                String that describes an event
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".

        :return:
                Created event object with id.
        """
        event_json = (
            self.service.events()
            .quickAdd(
                calendarId=self.calendar, text=event_string, sendUpdates=send_updates,
            )
            .execute()
        )
        return EventSerializer.to_object(event_json)

    def update_event(self, event, send_updates=SendUpdatesMode.NONE):
        """Updates existing event in the calendar

        :param event:
                Event object with set event_id.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".

        :return:
                updated event object.
        """
        body = EventSerializer(event).get_json()
        event_json = (
            self.service.events()
            .update(
                calendarId=self.calendar,
                eventId=event.id,
                body=body,
                sendUpdates=send_updates,
            )
            .execute()
        )
        return EventSerializer.to_object(event_json)

    def move_event(
        self, event, destination_calendar_id, send_updates=SendUpdatesMode.NONE
    ):
        """Moves existing event from calendar to another calendar

        :param event:
                Event object with set event_id.
        :param destination_calendar_id:
                Id of the destination calendar.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".

        :return:
                moved event object.
        """
        moved_event_json = (
            self.service.events()
            .move(
                calendarId=self.calendar,
                eventId=event.id,
                destination=destination_calendar_id,
                sendUpdates=send_updates,
            )
            .execute()
        )
        return EventSerializer.to_object(moved_event_json)

    def delete_event(self, event, send_updates=SendUpdatesMode.NONE):
        """ Deletes an event.

        :param event:
                Event object with set event_id.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".
        """
        if event.id is None:
            raise ValueError("Event has to have event_id to be deleted.")
        self.service.events().delete(
            calendarId=self.calendar, eventId=event.id, sendUpdates=send_updates,
        ).execute()

    def get_events(self, time_min=None, time_max=None, order_by='startTime', timezone=str(get_localzone())):
        """ Lists events

        :param time_min:
                Staring date/datetime
        :param time_max:
                Ending date/datetime
        :param order_by:
                Order of the events. Possible values: "startTime", "updated".
        :param timezone:
                Timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
                the computers local timezone is used if it is configured. UTC is used otherwise.
        """
        time_min = time_min or datetime.now()
        time_max = time_max or time_min + relativedelta(years=1)

        if not isinstance(time_min, datetime):
            time_min = datetime.combine(time_min, datetime.min.time())

        if not isinstance(time_max, datetime):
            time_max = datetime.combine(time_max, datetime.max.time())

        time_min = insure_localisation(time_min, timezone).isoformat()
        time_max = insure_localisation(time_max, timezone).isoformat()

        page_token = None
        while True:
            events = self.service.events().list(calendarId=self.calendar,
                                                timeMin=time_min,
                                                timeMax=time_max,
                                                orderBy=order_by,
                                                singleEvents=True,
                                                pageToken=page_token).execute()
            for event_json in events['items']:
                event = EventSerializer(event_json).get_object()
                yield event
            page_token = events.get('nextPageToken')
            if not page_token:
                break

    def get_event(self, event_id: str):
        """ Returns the event with the corresponding event_id.

        :param event_id:
                The unique event ID.

        :return:
                The corresponding event object or None if
                no matching ID was found.
        """
        event_resource = (
            self.service.events()
            .get(calendarId=self.calendar, eventId=event_id)
            .execute()
        )

        return EventSerializer(event_resource).get_object()

    def list_event_colors(self):
        """List allowed event colors for the calendar."""
        return self.service.colors().get().execute()['event']

    def __iter__(self):
        return iter(self.get_events())

    def __getitem__(self, r):
        if isinstance(r, slice):
            time_min, time_max, order_by = r.start or None, r.stop or None, r.step or 'startTime'
        elif isinstance(r, (date, datetime)):
            time_min, time_max, order_by = r, None, 'startTime'
        else:
            return NotImplemented

        if (time_min and not isinstance(time_min, date)) \
                or (time_max and not isinstance(time_max, date)) \
                or not isinstance(order_by, str) or order_by not in self._LIST_ORDERS:
            raise ValueError('Calendar indexing is in the following format:  time_min[:time_max[:order_by]],'
                             ' where time_min and time_max are date/datetime objects'
                             ' and order_by is one of "startTime" or "updated" strings.')

        return self.get_events(time_min, time_max, order_by)
<commit_msg>Add additional parameters to all methods in GC<commit_after>from datetime import date, datetime
import pickle
import os.path

from dateutil.relativedelta import relativedelta
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from tzlocal import get_localzone

from .serializers.event_serializer import EventSerializer
from .util.date_time_util import insure_localisation

def _get_default_credentials_path():
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir, 'credentials.json')
    return credential_path

class SendUpdatesMode:
    """ Possible values of the mode for sending updates or invitations to attendees.

    * ALL - Send updates to all participants. This is the default value.
    * EXTERNAL_ONLY - Send updates only to attendees not using google calendar.
    * NONE - Do not send updates.
    """

    ALL = "all"
    EXTERNAL_ONLY = "externalOnly"
    NONE = "none"

class GoogleCalendar:
    _READ_WRITE_SCOPES = 'https://www.googleapis.com/auth/calendar'
    _LIST_ORDERS = ("startTime", "updated")

    def __init__(self,
                 calendar='primary',
                 *,
                 credentials_path=None,
                 token_path=None,
                 read_only=False,
                 application_name=None
                 ):
        """Represents Google Calendar of the user.

        :param calendar:
                Users email address or name/id of the calendar. Default: primary calendar of the user
        :param credentials_path:
                Path to "credentials.json" file. Default: ~/.credentials
        :param token_path:
                Existing path to load the token from, or path to save the token after initial authentication flow.
                Default: "token.pickle" in the same directory as the credentials_path
        :param read_only:
                If require read only access. Default: False
        :param application_name:
                Name of the application. Default: None
        """
        credentials_path = credentials_path or _get_default_credentials_path()
        self._credentials_dir, self._credentials_file = os.path.split(credentials_path)

        self._scopes = [self._READ_WRITE_SCOPES + ('.readonly' if read_only else '')]
        self._application_name = application_name
        self._token_path = token_path or os.path.join(self._credentials_dir, 'token.pickle')

        self.calendar = calendar
        credentials = self._get_credentials()
        self.service = build('calendar', 'v3', credentials=credentials)

    def _get_credentials(self):
        _credentials_path = os.path.join(self._credentials_dir, self._credentials_file)

        credentials = None

        if os.path.exists(self._token_path):
            with open(self._token_path, 'rb') as token:
                credentials = pickle.load(token)

        if not credentials or not credentials.valid:
            if credentials and credentials.expired and credentials.refresh_token:
                credentials.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(_credentials_path, self._scopes)
                credentials = flow.run_local_server()

            with open(self._token_path, 'wb') as token:
                pickle.dump(credentials, token)

        return credentials

    def add_event(self, event, send_updates=SendUpdatesMode.NONE, **kwargs):
        """Creates event in the calendar

        :param event:
                Event object.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/insert

        :return:
                Created event object with id.
        """
        body = EventSerializer(event).get_json()
        event_json = self.service.events().insert(
            calendarId=self.calendar,
            body=body,
            conferenceDataVersion=1,
            sendUpdates=send_updates,
            **kwargs
        ).execute()
        return EventSerializer.to_object(event_json)

    def add_quick_event(self, event_string, send_updates=SendUpdatesMode.NONE, **kwargs):
        """Creates event in the calendar by string description.

        Example:
            Appointment at Somewhere on June 3rd 10am-10:25am

        :param event_string:
                String that describes an event
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/quickAdd

        :return:
                Created event object with id.
        """
        event_json = self.service.events().quickAdd(
            calendarId=self.calendar,
            text=event_string,
            sendUpdates=send_updates,
            **kwargs
        ).execute()
        return EventSerializer.to_object(event_json)

    def update_event(self, event, send_updates=SendUpdatesMode.NONE, **kwargs):
        """Updates existing event in the calendar

        :param event:
                Event object with set event_id.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/update

        :return:
                Updated event object.
        """
        body = EventSerializer(event).get_json()
        event_json = self.service.events().update(
            calendarId=self.calendar,
            eventId=event.id,
            body=body,
            sendUpdates=send_updates,
            **kwargs
        ).execute()
        return EventSerializer.to_object(event_json)

    def move_event(self, event, destination_calendar_id, send_updates=SendUpdatesMode.NONE, **kwargs):
        """Moves existing event from calendar to another calendar

        :param event:
                Event object with set event_id.
        :param destination_calendar_id:
                Id of the destination calendar.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/move

        :return:
                Moved event object.
        """
        moved_event_json = self.service.events().move(
            calendarId=self.calendar,
            eventId=event.id,
            destination=destination_calendar_id,
            sendUpdates=send_updates,
            **kwargs
        ).execute()
        return EventSerializer.to_object(moved_event_json)

    def delete_event(self, event, send_updates=SendUpdatesMode.NONE, **kwargs):
        """ Deletes an event.

        :param event:
                Event object with set event_id.
        :param send_updates:
                Whether and how to send updates to attendees. See :py:class:`~gcsa.google_calendar.SendUpdatesMode`
                Default is "NONE".
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/delete
        """
        if event.id is None:
            raise ValueError("Event has to have event_id to be deleted.")
        self.service.events().delete(
            calendarId=self.calendar,
            eventId=event.id,
            sendUpdates=send_updates,
            **kwargs
        ).execute()

    def get_events(self, time_min=None, time_max=None, order_by='startTime', timezone=str(get_localzone()), **kwargs):
        """ Lists events

        :param time_min:
                Staring date/datetime
        :param time_max:
                Ending date/datetime
        :param order_by:
                Order of the events. Possible values: "startTime", "updated".
        :param timezone:
                Timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
                the computers local timezone is used if it is configured. UTC is used otherwise.
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/list

        :return:
                Iterable of event objects
        """
        time_min = time_min or datetime.now()
        time_max = time_max or time_min + relativedelta(years=1)

        if not isinstance(time_min, datetime):
            time_min = datetime.combine(time_min, datetime.min.time())

        if not isinstance(time_max, datetime):
            time_max = datetime.combine(time_max, datetime.max.time())

        time_min = insure_localisation(time_min, timezone).isoformat()
        time_max = insure_localisation(time_max, timezone).isoformat()

        page_token = None
        while True:
            events = self.service.events().list(
                calendarId=self.calendar,
                timeMin=time_min,
                timeMax=time_max,
                orderBy=order_by,
                singleEvents=True,
                pageToken=page_token,
                **kwargs
            ).execute()
            for event_json in events['items']:
                event = EventSerializer(event_json).get_object()
                yield event
            page_token = events.get('nextPageToken')
            if not page_token:
                break

    def get_event(self, event_id, **kwargs):
        """ Returns the event with the corresponding event_id.

        :param event_id:
                The unique event ID.
        :param kwargs:
                Additional API parameters. See https://developers.google.com/calendar/v3/reference/events/get

        :return:
                The corresponding event object or None if
                no matching ID was found.
        """
        event_resource = self.service.events().get(
            calendarId=self.calendar,
            eventId=event_id,
            **kwargs
        ).execute()

        return EventSerializer(event_resource).get_object()

    def list_event_colors(self):
        """List allowed event colors for the calendar."""
        return self.service.colors().get().execute()['event']

    def __iter__(self):
        return iter(self.get_events())

    def __getitem__(self, r):
        if isinstance(r, slice):
            time_min, time_max, order_by = r.start or None, r.stop or None, r.step or 'startTime'
        elif isinstance(r, (date, datetime)):
            time_min, time_max, order_by = r, None, 'startTime'
        else:
            return NotImplemented

        if (time_min and not isinstance(time_min, date)) \
                or (time_max and not isinstance(time_max, date)) \
                or not isinstance(order_by, str) or order_by not in self._LIST_ORDERS:
            raise ValueError('Calendar indexing is in the following format:  time_min[:time_max[:order_by]],'
                             ' where time_min and time_max are date/datetime objects'
                             ' and order_by is one of "startTime" or "updated" strings.')

        return self.get_events(time_min, time_max, order_by)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import csv
import itertools
import sqlite3

from gpn.connector import _Connector
from gpn.connector import _create_triggers

class Partition(object):
    def __init__(self, path=None, mode=0):
        """Get existing Partition or create a new one."""
        self._connect = _Connector(path, mode=mode)

    def select_cell(self, **kwds):
        connection = self._connect()
        cursor1 = connection.cursor()
        cursor2 = connection.cursor()

        for cell_id in self._select_cell_id(cursor1, **kwds):
            query = """
                SELECT hierarchy_value, label_value
                FROM cell
                NATURAL JOIN cell_label
                NATURAL JOIN label
                NATURAL JOIN hierarchy
                WHERE cell_id=?
                ORDER BY hierarchy_level
            """
            cursor2.execute(query, (cell_id,))
            yield dict(cursor2.fetchall())

        connection.close()

    @staticmethod
    def _select_cell_id(cursor, **kwds):
        query = """
            SELECT cell_id
            FROM cell_label
            NATURAL JOIN label
            NATURAL JOIN hierarchy
            WHERE hierarchy_value=? AND label_value=?
        """
        operation = [query] * len(kwds)
        operation = '\nINTERSECT\n'.join(operation)
        params = itertools.chain.from_iterable(kwds.items())
        params = list(params)

        cursor.execute(operation, params)
        return (x[0] for x in cursor)

    def insert_cells(self, filename):
        """Insert cells from given CSV filename."""
        with open(filename, 'r') as fh:
            self._insert_cells(fh)

    def _insert_cells(self, fh):
        """Insert cells from given CSV file object."""
        reader = csv.reader(fh)
        fieldnames = next(reader)  # Use header row as fieldnames.

        connection = self._connect()
        connection.isolation_level = None
        cursor = connection.cursor()
        cursor.execute('BEGIN TRANSACTION')

        complete = False
        try:
            # Temporarily drop triggers (too slow for bulk insert).
            cursor.execute('DROP TRIGGER CheckUniqueLabels_ins')
            cursor.execute('DROP TRIGGER CheckUniqueLabels_upd')
            cursor.execute('DROP TRIGGER CheckUniqueLabels_del')

            self._insert_hierarchies(cursor, fieldnames)

            if not self._get_unmapped_cell(cursor, fieldnames):
                items = [(x, 'UNMAPPED') for x in fieldnames]
                self._insert_one_cell(cursor, items)

            # Add all other cells.
            for row in reader:
                items = zip(fieldnames, row)
                self._insert_one_cell(cursor, items)

            # Check for duplicate label combinations.
            cursor.execute("""
                SELECT 1
                FROM (SELECT GROUP_CONCAT(label_id) AS label_combo
                      FROM (SELECT cell_id, label_id
                            FROM cell_label
                            ORDER BY cell_id, label_id)
                      GROUP BY cell_id)
                GROUP BY label_combo
                HAVING COUNT(*) > 1
            """)
            if cursor.fetchone():
                raise sqlite3.IntegrityError('CHECK constraint failed: cell_label')

            # Re-create "CheckUniqueLabel" triggers.
            for operation in _create_triggers:
                cursor.execute(operation)

            connection.commit()
            complete = True

        finally:
            if not complete:
                connection.rollback()
            connection.close()

    @staticmethod
    def _insert_hierarchies(cursor, fieldnames):
        cursor.execute('SELECT hierarchy_value FROM hierarchy ORDER BY hierarchy_level')
        hierarchies = [x[0] for x in cursor.fetchall()]
        if not hierarchies:
            query = 'INSERT INTO hierarchy (hierarchy_level, hierarchy_value) VALUES (?, ?)'
            cursor.executemany(query, enumerate(fieldnames))
        else:
            msg = ('Fieldnames must match hierarchy values.\n'
                   ' Found: %s\n Required: %s') % (', '.join(fieldnames),
                                                   ', '.join(hierarchies))
            assert set(hierarchies) == set(fieldnames), msg

    @staticmethod
    def _get_unmapped_cell(cursor, fieldnames):
        select_one = ("SELECT cell_id FROM cell_label "
                      "NATURAL JOIN label NATURAL JOIN hierarchy "
                      "WHERE label_value='UNMAPPED' AND hierarchy_value=?")
        operation = [select_one] * len(fieldnames)
        operation = '\nINTERSECT\n'.join(operation)
        cursor.execute(operation, fieldnames)
        result = cursor.fetchone()
        return result[0] if result else None

    @staticmethod
    def _insert_one_cell(cursor, items):
        """Performs insert-cell operation using given items."""
        items = list(items)

        # Insert cell record.
        cursor.execute('INSERT INTO cell DEFAULT VALUES')
        cell_id = cursor.lastrowid

        # Insert label records.
        operation = """
            INSERT OR IGNORE INTO label (hierarchy_id, label_value)
            SELECT hierarchy_id, ? AS label_value
            FROM hierarchy
            WHERE hierarchy_value=?
        """
        params = [(lbl, hrchy) for hrchy, lbl in items]
        cursor.executemany(operation, params)

        # Insert cell_label records.
        operation = """
            INSERT INTO cell_label (cell_id, hierarchy_id, label_id)
            SELECT ? as cell_id, hierarchy_id, label_id
            FROM label
            WHERE hierarchy_id IN (SELECT hierarchy_id
                                   FROM hierarchy
                                   WHERE hierarchy_value=?)
                  AND label_value=?
        """
        params = [(cell_id, hrchy, lbl) for hrchy, lbl in items]
        cursor.executemany(operation, params)
<commit_msg>Replace `get_unmapped_cell` with `select_cell_id`--cut redundancy.<commit_after># -*- coding: utf-8 -*-
import csv
import itertools
import sqlite3

from gpn.connector import _Connector
from gpn.connector import _create_triggers

class Partition(object):
    def __init__(self, path=None, mode=0):
        """Get existing Partition or create a new one."""
        self._connect = _Connector(path, mode=mode)

    def select_cell(self, **kwds):
        connection = self._connect()
        cursor1 = connection.cursor()
        cursor2 = connection.cursor()

        for cell_id in self._select_cell_id(cursor1, **kwds):
            query = """
                SELECT hierarchy_value, label_value
                FROM cell
                NATURAL JOIN cell_label
                NATURAL JOIN label
                NATURAL JOIN hierarchy
                WHERE cell_id=?
                ORDER BY hierarchy_level
            """
            cursor2.execute(query, (cell_id,))
            yield dict(cursor2.fetchall())

        connection.close()

    @staticmethod
    def _select_cell_id(cursor, **kwds):
        query = """
            SELECT cell_id
            FROM cell_label
            NATURAL JOIN label
            NATURAL JOIN hierarchy
            WHERE hierarchy_value=? AND label_value=?
        """
        operation = [query] * len(kwds)
        operation = '\nINTERSECT\n'.join(operation)
        params = itertools.chain.from_iterable(kwds.items())
        params = list(params)

        cursor.execute(operation, params)
        return (x[0] for x in cursor)

    def insert_cells(self, filename):
        """Insert cells from given CSV filename."""
        with open(filename, 'r') as fh:
            self._insert_cells(fh)

    def _insert_cells(self, fh):
        """Insert cells from given CSV file object."""
        reader = csv.reader(fh)
        fieldnames = next(reader)  # Use header row as fieldnames.

        connection = self._connect()
        connection.isolation_level = None
        cursor = connection.cursor()
        cursor.execute('BEGIN TRANSACTION')

        complete = False
        try:
            # Temporarily drop triggers (too slow for bulk insert).
            cursor.execute('DROP TRIGGER CheckUniqueLabels_ins')
            cursor.execute('DROP TRIGGER CheckUniqueLabels_upd')
            cursor.execute('DROP TRIGGER CheckUniqueLabels_del')

            self._insert_hierarchies(cursor, fieldnames)

            # Add "UNMAPPED" cell if not present.
            unmapped_items = [(x, 'UNMAPPED') for x in fieldnames]
            unmapped_dict = dict(unmapped_items)
            resultgen = self._select_cell_id(cursor, **unmapped_dict)
            if not list(resultgen):
                self._insert_one_cell(cursor, unmapped_items)

            # Add all other cells.
            for row in reader:
                items = zip(fieldnames, row)
                self._insert_one_cell(cursor, items)

            # Check for duplicate label combinations.
            cursor.execute("""
                SELECT 1
                FROM (SELECT GROUP_CONCAT(label_id) AS label_combo
                      FROM (SELECT cell_id, label_id
                            FROM cell_label
                            ORDER BY cell_id, label_id)
                      GROUP BY cell_id)
                GROUP BY label_combo
                HAVING COUNT(*) > 1
            """)
            if cursor.fetchone():
                raise sqlite3.IntegrityError('CHECK constraint failed: cell_label')

            # Re-create "CheckUniqueLabel" triggers.
            for operation in _create_triggers:
                cursor.execute(operation)

            connection.commit()
            complete = True

        finally:
            if not complete:
                connection.rollback()
            connection.close()

    @staticmethod
    def _insert_hierarchies(cursor, fieldnames):
        cursor.execute('SELECT hierarchy_value FROM hierarchy ORDER BY hierarchy_level')
        hierarchies = [x[0] for x in cursor.fetchall()]
        if not hierarchies:
            query = 'INSERT INTO hierarchy (hierarchy_level, hierarchy_value) VALUES (?, ?)'
            cursor.executemany(query, enumerate(fieldnames))
        else:
            msg = ('Fieldnames must match hierarchy values.\n'
                   ' Found: %s\n Required: %s') % (', '.join(fieldnames),
                                                   ', '.join(hierarchies))
            assert set(hierarchies) == set(fieldnames), msg

    @staticmethod
    def _insert_one_cell(cursor, items):
        """Performs insert-cell operation using given items."""
        items = list(items)

        # Insert cell record.
        cursor.execute('INSERT INTO cell DEFAULT VALUES')
        cell_id = cursor.lastrowid

        # Insert label records.
        operation = """
            INSERT OR IGNORE INTO label (hierarchy_id, label_value)
            SELECT hierarchy_id, ? AS label_value
            FROM hierarchy
            WHERE hierarchy_value=?
        """
        params = [(lbl, hrchy) for hrchy, lbl in items]
        cursor.executemany(operation, params)

        # Insert cell_label records.
        operation = """
            INSERT INTO cell_label (cell_id, hierarchy_id, label_id)
            SELECT ? as cell_id, hierarchy_id, label_id
            FROM label
            WHERE hierarchy_id IN (SELECT hierarchy_id
                                   FROM hierarchy
                                   WHERE hierarchy_value=?)
                  AND label_value=?
        """
        params = [(cell_id, hrchy, lbl) for hrchy, lbl in items]
        cursor.executemany(operation, params)
<|endoftext|>