<commit_before>"""Views for the topics application."""

from django.shortcuts import get_object_or_404
from django.views import generic
from django.http import JsonResponse, Http404
from general.templatetags.render_html_field import render_html_with_static

from .models import (
    Topic,
    CurriculumIntegration,
    UnitPlan,
    Lesson,
    ProgrammingExercise,
    ProgrammingExerciseLanguageImplementation,
    ConnectedGeneratedResource,
    GlossaryTerm,
)

class IndexView(generic.ListView):
    """View for the topics application homepage."""

    template_name = 'topics/index.html'
    context_object_name = 'all_topics'

    def get_queryset(self):
        """Get queryset of all topics.

        Returns:
            Queryset of Topic objects ordered by name.
        """
        return Topic.objects.order_by('name')

class TopicView(generic.DetailView):
    """View for a specific topic."""

    model = Topic
    template_name = 'topics/topic.html'
    slug_url_kwarg = 'topic_slug'

    def get_context_data(self, **kwargs):
        """Provide the context data for the topic view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(TopicView, self).get_context_data(**kwargs)
        # Add in a QuerySet of all the connected unit plans
        unit_plans = UnitPlan.objects.filter(topic=self.object).order_by('name').select_related()
        for unit_plan in unit_plans:
            unit_plan.lessons = unit_plan.lessons_by_age_group()
        context['unit_plans'] = unit_plans
        # Add in a QuerySet of all the connected curriculum integrations
        context['curriculum_integrations'] = CurriculumIntegration.objects.filter(topic=self.object).order_by('number')
        return context

class UnitPlanView(generic.DetailView):
    """View for a specific unit plan."""

    model = UnitPlan
    template_name = 'topics/unit_plan.html'
    context_object_name = 'unit_plan'

    def get_object(self, **kwargs):
        """Retrieve object for the unit plan view.

        Returns:
            UnitPlan object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            slug=self.kwargs.get('unit_plan_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the unit plan view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(UnitPlanView, self).get_context_data(**kwargs)
        # Loading object under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        # Add all the connected lessons
        context['lessons'] = self.object.unit_plan_lessons.order_by('min_age', 'max_age', 'number')
        return context

class LessonView(generic.DetailView):
    """View for a specific lesson."""

    model = Lesson
    template_name = 'topics/lesson.html'
    context_object_name = 'lesson'

    def get_object(self, **kwargs):
        """Retrieve object for the lesson view.

        Returns:
            Lesson object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            unit_plan__slug=self.kwargs.get('unit_plan_slug', None),
            slug=self.kwargs.get('lesson_slug', None),
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the lesson view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(LessonView, self).get_context_data(**kwargs)
        # Loading objects under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        context['unit_plan'] = self.object.unit_plan
        # Add all the connected programming exercises
        context['programming_exercises'] = self.object.programming_exercises.all()
        # Add all the connected curriculum areas
        context['lesson_curriculum_areas'] = self.object.curriculum_areas.all()
        # Add all the connected learning outcomes
        context['lesson_learning_outcomes'] = self.object.learning_outcomes.all()
        # Add all the connected generated resources
        related_resources = self.object.generated_resources.all()
        generated_resources = []
        for related_resource in related_resources:
            generated_resource = dict()
            generated_resource['slug'] = related_resource.slug
            generated_resource['name'] = related_resource.name
            generated_resource['thumbnail'] = related_resource.thumbnail_static_path
            relationship = ConnectedGeneratedResource.objects.get(resource=related_resource, lesson=self.object)
            generated_resource['description'] = relationship.description
            generated_resources.append(generated_resource)
        context['lesson_generated_resources'] = generated_resources

        return context

class ProgrammingExerciseList(generic.ListView):
    """View for listing all programming exercises for a lesson."""

    model = ProgrammingExercise
    template_name = 'topics/programming_exercise_lesson_list.html'
    context_object_name = 'all_programming_exercises'

    def get_queryset(self, **kwargs):
        """Retrieve all programming exercises for a topic.

        Returns:
            Queryset of ProgrammingExercise objects.
        """
        lesson_slug = self.kwargs.get('lesson_slug', None)
        exercises = ProgrammingExercise.objects.filter(lessons__slug=lesson_slug)
        return exercises.order_by('exercise_set_number', 'exercise_number')

    def get_context_data(self, **kwargs):
        """Provide the context data for the programming exercise list view.

        Returns:
            Dictionary of context data.
        """
        context = super(ProgrammingExerciseList, self).get_context_data(**kwargs)
        lesson = get_object_or_404(
            Lesson.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            unit_plan__slug=self.kwargs.get('unit_plan_slug', None),
            slug=self.kwargs.get('lesson_slug', None),
        )
        context['lesson'] = lesson
        context['unit_plan'] = lesson.unit_plan
        context['topic'] = lesson.topic
        return context

class ProgrammingExerciseView(generic.DetailView):
    """View for a specific programming exercise."""

    model = ProgrammingExercise
    template_name = 'topics/programming_exercise.html'
    context_object_name = 'programming_exercise'

    def get_object(self, **kwargs):
        """Retrieve object for the programming exercise view.

        Returns:
            ProgrammingExercise object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            slug=self.kwargs.get('programming_exercise_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the programming exercise view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(ProgrammingExerciseView, self).get_context_data(**kwargs)
        context['lessons'] = self.object.lessons.all()
        context['topic'] = self.object.topic
        # Add all the connected learning outcomes
        context['programming_exercise_learning_outcomes'] = self.object.learning_outcomes.all()
        context['implementations'] = self.object.implementations.all().order_by('-language__name').select_related()
        return context

class ProgrammingExerciseLanguageSolutionView(generic.DetailView):
    """View for a language implementation for a programming exercise."""

    model = ProgrammingExerciseLanguageImplementation
    template_name = 'topics/programming_exercise_language_solution.html'
    context_object_name = 'implementation'

    def get_object(self, **kwargs):
        """Retrieve object for the language implementation view.

        Returns:
            ProgrammingExerciseLanguageImplementation object, or raises 404
            error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            exercise__slug=self.kwargs.get('programming_exercise_slug', None),
            language__slug=self.kwargs.get('programming_language_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the language implementation view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(ProgrammingExerciseLanguageSolutionView, self).get_context_data(**kwargs)
        # Loading object under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        context['programming_exercise'] = self.object.exercise
        return context

class AllCurriculumIntegrationList(generic.ListView):
    """View for listing all curriculum integrations."""

    model = CurriculumIntegration
    template_name = 'topics/all_curriculum_integration_list.html'
    context_object_name = 'curriculum_integrations'

    def get_queryset(self, **kwargs):
        """Retrieve all curriculum integrations.

        Returns:
            Queryset of CurriculumIntegration objects.
        """
        return CurriculumIntegration.objects.select_related().order_by('topic__name', 'number')

class CurriculumIntegrationView(generic.DetailView):
    """View for a specific curriculum integration."""

    model = CurriculumIntegration
    queryset = CurriculumIntegration.objects.all()
    template_name = 'topics/curriculum_integration.html'
    context_object_name = 'integration'

    def get_object(self, **kwargs):
        """Retrieve object for the curriculum integration view.

        Returns:
            CurriculumIntegration object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            slug=self.kwargs.get('integration_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the curriculum integration view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(CurriculumIntegrationView, self).get_context_data(**kwargs)
        # Loading objects under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        # Add in a QuerySet of all the connected curriculum areas
        context['integration_curriculum_areas'] = self.object.curriculum_areas.all()
        # Add in a QuerySet of all the prerequisite lessons
        context['prerequisite_lessons'] = self.object.prerequisite_lessons.select_related().order_by(
            'unit_plan__name', 'number'
        )
        return context

class OtherResourcesView(generic.DetailView):
    """View for detailing other resources for a specific topic."""

    model = Topic
    template_name = 'topics/topic-other-resources.html'
    slug_url_kwarg = 'topic_slug'

class GlossaryList(generic.ListView):
    """Provide glossary view of all terms."""

    template_name = "topics/glossary.html"
    context_object_name = "glossary_terms"

    def get_queryset(self):
        """Get queryset of all glossary terms.

        Returns:
            Queryset of GlossaryTerm objects ordered by term.
        """
        return GlossaryTerm.objects.order_by("term")

def glossary_json(request, **kwargs):
    """Provide JSON data for glossary term.

    Args:
        request: The HTTP request.

    Returns:
        JSON response is sent containing data for the requested term.
    """
    # If term parameter, then return JSON
    if "term" in request.GET:
        glossary_slug = request.GET.get("term")
        glossary_item = get_object_or_404(
            GlossaryTerm,
            slug=glossary_slug
        )
        data = {
            "slug": glossary_slug,
            "term": glossary_item.term,
            "definition": render_html_with_static(glossary_item.definition)
        }
        return JsonResponse(data)
    else:
        raise Http404("Term parameter not specified.")
<commit_msg>Consistently order lessons on curriculum integration page<commit_after>"""Views for the topics application."""

from django.shortcuts import get_object_or_404
from django.views import generic
from django.http import JsonResponse, Http404
from general.templatetags.render_html_field import render_html_with_static

from .models import (
    Topic,
    CurriculumIntegration,
    UnitPlan,
    Lesson,
    ProgrammingExercise,
    ProgrammingExerciseLanguageImplementation,
    ConnectedGeneratedResource,
    GlossaryTerm,
)

class IndexView(generic.ListView):
    """View for the topics application homepage."""

    template_name = 'topics/index.html'
    context_object_name = 'all_topics'

    def get_queryset(self):
        """Get queryset of all topics.

        Returns:
            Queryset of Topic objects ordered by name.
        """
        return Topic.objects.order_by('name')

class TopicView(generic.DetailView):
    """View for a specific topic."""

    model = Topic
    template_name = 'topics/topic.html'
    slug_url_kwarg = 'topic_slug'

    def get_context_data(self, **kwargs):
        """Provide the context data for the topic view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(TopicView, self).get_context_data(**kwargs)
        # Add in a QuerySet of all the connected unit plans
        unit_plans = UnitPlan.objects.filter(topic=self.object).order_by('name').select_related()
        for unit_plan in unit_plans:
            unit_plan.lessons = unit_plan.lessons_by_age_group()
        context['unit_plans'] = unit_plans
        # Add in a QuerySet of all the connected curriculum integrations
        context['curriculum_integrations'] = CurriculumIntegration.objects.filter(topic=self.object).order_by('number')
        return context

class UnitPlanView(generic.DetailView):
    """View for a specific unit plan."""

    model = UnitPlan
    template_name = 'topics/unit_plan.html'
    context_object_name = 'unit_plan'

    def get_object(self, **kwargs):
        """Retrieve object for the unit plan view.

        Returns:
            UnitPlan object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            slug=self.kwargs.get('unit_plan_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the unit plan view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(UnitPlanView, self).get_context_data(**kwargs)
        # Loading object under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        # Add all the connected lessons
        context['lessons'] = self.object.unit_plan_lessons.order_by('min_age', 'max_age', 'number')
        return context

class LessonView(generic.DetailView):
    """View for a specific lesson."""

    model = Lesson
    template_name = 'topics/lesson.html'
    context_object_name = 'lesson'

    def get_object(self, **kwargs):
        """Retrieve object for the lesson view.

        Returns:
            Lesson object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            unit_plan__slug=self.kwargs.get('unit_plan_slug', None),
            slug=self.kwargs.get('lesson_slug', None),
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the lesson view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(LessonView, self).get_context_data(**kwargs)
        # Loading objects under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        context['unit_plan'] = self.object.unit_plan
        # Add all the connected programming exercises
        context['programming_exercises'] = self.object.programming_exercises.all()
        # Add all the connected curriculum areas
        context['lesson_curriculum_areas'] = self.object.curriculum_areas.all()
        # Add all the connected learning outcomes
        context['lesson_learning_outcomes'] = self.object.learning_outcomes.all()
        # Add all the connected generated resources
        related_resources = self.object.generated_resources.all()
        generated_resources = []
        for related_resource in related_resources:
            generated_resource = dict()
            generated_resource['slug'] = related_resource.slug
            generated_resource['name'] = related_resource.name
            generated_resource['thumbnail'] = related_resource.thumbnail_static_path
            relationship = ConnectedGeneratedResource.objects.get(resource=related_resource, lesson=self.object)
            generated_resource['description'] = relationship.description
            generated_resources.append(generated_resource)
        context['lesson_generated_resources'] = generated_resources

        return context

class ProgrammingExerciseList(generic.ListView):
    """View for listing all programming exercises for a lesson."""

    model = ProgrammingExercise
    template_name = 'topics/programming_exercise_lesson_list.html'
    context_object_name = 'all_programming_exercises'

    def get_queryset(self, **kwargs):
        """Retrieve all programming exercises for a topic.

        Returns:
            Queryset of ProgrammingExercise objects.
        """
        lesson_slug = self.kwargs.get('lesson_slug', None)
        exercises = ProgrammingExercise.objects.filter(lessons__slug=lesson_slug)
        return exercises.order_by('exercise_set_number', 'exercise_number')

    def get_context_data(self, **kwargs):
        """Provide the context data for the programming exercise list view.

        Returns:
            Dictionary of context data.
        """
        context = super(ProgrammingExerciseList, self).get_context_data(**kwargs)
        lesson = get_object_or_404(
            Lesson.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            unit_plan__slug=self.kwargs.get('unit_plan_slug', None),
            slug=self.kwargs.get('lesson_slug', None),
        )
        context['lesson'] = lesson
        context['unit_plan'] = lesson.unit_plan
        context['topic'] = lesson.topic
        return context

class ProgrammingExerciseView(generic.DetailView):
    """View for a specific programming exercise."""

    model = ProgrammingExercise
    template_name = 'topics/programming_exercise.html'
    context_object_name = 'programming_exercise'

    def get_object(self, **kwargs):
        """Retrieve object for the programming exercise view.

        Returns:
            ProgrammingExercise object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            slug=self.kwargs.get('programming_exercise_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the programming exercise view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(ProgrammingExerciseView, self).get_context_data(**kwargs)
        context['lessons'] = self.object.lessons.all()
        context['topic'] = self.object.topic
        # Add all the connected learning outcomes
        context['programming_exercise_learning_outcomes'] = self.object.learning_outcomes.all()
        context['implementations'] = self.object.implementations.all().order_by('-language__name').select_related()
        return context

class ProgrammingExerciseLanguageSolutionView(generic.DetailView):
    """View for a language implementation for a programming exercise."""

    model = ProgrammingExerciseLanguageImplementation
    template_name = 'topics/programming_exercise_language_solution.html'
    context_object_name = 'implementation'

    def get_object(self, **kwargs):
        """Retrieve object for the language implementation view.

        Returns:
            ProgrammingExerciseLanguageImplementation object, or raises 404
            error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            exercise__slug=self.kwargs.get('programming_exercise_slug', None),
            language__slug=self.kwargs.get('programming_language_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the language implementation view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(ProgrammingExerciseLanguageSolutionView, self).get_context_data(**kwargs)
        # Loading object under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        context['programming_exercise'] = self.object.exercise
        return context

class AllCurriculumIntegrationList(generic.ListView):
    """View for listing all curriculum integrations."""

    model = CurriculumIntegration
    template_name = 'topics/all_curriculum_integration_list.html'
    context_object_name = 'curriculum_integrations'

    def get_queryset(self, **kwargs):
        """Retrieve all curriculum integrations.

        Returns:
            Queryset of CurriculumIntegration objects.
        """
        return CurriculumIntegration.objects.select_related().order_by('topic__name', 'number')

class CurriculumIntegrationView(generic.DetailView):
    """View for a specific curriculum integration."""

    model = CurriculumIntegration
    queryset = CurriculumIntegration.objects.all()
    template_name = 'topics/curriculum_integration.html'
    context_object_name = 'integration'

    def get_object(self, **kwargs):
        """Retrieve object for the curriculum integration view.

        Returns:
            CurriculumIntegration object, or raises 404 error if not found.
        """
        return get_object_or_404(
            self.model.objects.select_related(),
            topic__slug=self.kwargs.get('topic_slug', None),
            slug=self.kwargs.get('integration_slug', None)
        )

    def get_context_data(self, **kwargs):
        """Provide the context data for the curriculum integration view.

        Returns:
            Dictionary of context data.
        """
        # Call the base implementation first to get a context
        context = super(CurriculumIntegrationView, self).get_context_data(**kwargs)
        # Loading objects under consistent context names for breadcrumbs
        context['topic'] = self.object.topic
        # Add in a QuerySet of all the connected curriculum areas
        context['integration_curriculum_areas'] = self.object.curriculum_areas.order_by("name")
        # Add in a QuerySet of all the prerequisite lessons
        context['prerequisite_lessons'] = self.object.prerequisite_lessons.select_related().order_by(
            'unit_plan__name',
            'min_age',
            'max_age',
            'number'
        )
        return context

class OtherResourcesView(generic.DetailView):
    """View for detailing other resources for a specific topic."""

    model = Topic
    template_name = 'topics/topic-other-resources.html'
    slug_url_kwarg = 'topic_slug'

class GlossaryList(generic.ListView):
    """Provide glossary view of all terms."""

    template_name = "topics/glossary.html"
    context_object_name = "glossary_terms"

    def get_queryset(self):
        """Get queryset of all glossary terms.

        Returns:
            Queryset of GlossaryTerm objects ordered by term.
        """
        return GlossaryTerm.objects.order_by("term")

def glossary_json(request, **kwargs):
    """Provide JSON data for glossary term.

    Args:
        request: The HTTP request.

    Returns:
        JSON response is sent containing data for the requested term.
    """
    # If term parameter, then return JSON
    if "term" in request.GET:
        glossary_slug = request.GET.get("term")
        glossary_item = get_object_or_404(
            GlossaryTerm,
            slug=glossary_slug
        )
        data = {
            "slug": glossary_slug,
            "term": glossary_item.term,
            "definition": render_html_with_static(glossary_item.definition)
        }
        return JsonResponse(data)
    else:
        raise Http404("Term parameter not specified.")
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright 2017 Stein & Gabelgaard ApS
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from openerp import api, fields, models, _

import logging
_logger = logging.getLogger(__name__)

class CamposEventParticipant(models.Model):

    _inherit = 'campos.event.participant'

    checkin_info_html = fields.Html('Check In Notes', compute='compute_checkin')
    checkin_ok = fields.Boolean('Check In possible', compute='compute_checkin')
    arrive_time = fields.Datetime('Arrival')
    checkin_completed = fields.Datetime('Check In Time')
    checkin_subcamp_id = fields.Many2one('campos.subcamp', 'Sub Camp', compute='_compute_checkin_subcamp_id', store=True)
    not_invoiced = fields.Boolean('Not invoiced', compute='compute_checkin')
    firstcampdate = fields.Date('First Camp Date', compute='_compute_firstcampdate', store=True)

    @api.multi
    #@api.depends()
    def compute_checkin(self):
        for par in self:
            ckr_clc = False
            checkin_ok = True
            infotext = []
            if par.clc_state:
                if par.clc_state != 'passed' and par.camp_age >= 18:
                    infotext.append(_('CLC not passed!'))
                    checkin_ok = False
            elif par.ckr_state != 'approved' and par.camp_age >= 15:
                infotext.append(_('CKR not yet approved!'))
                checkin_ok = False
            #Economy
            if par.signup_state in ['oncamp']:
                if par.registration_id.partner_id != par.partner_id:
                    infotext.append(_('Paid by: %s') % (par.registration_id.partner_id.name))
                elif par.registration_id.partner_id.credit > 0:
                    infotext.append(_('Unpaid invoices. Total due: DKK %.2f') % (par.registration_id.partner_id.credit))
                    checkin_ok = False
                elif par.registration_id.partner_id.credit == 0 and not par.sudo().no_invoicing and par.camp_price_total > 0:
                    if self.env['account.invoice'].search_count([('partner_id', '=', par.registration_id.partner_id.id), ('state', 'in', ['open','paid'])]) == 0:
                        par.not_invoiced = True
                        checkin_ok = False
                        infotext.append(_('Invoice not yet generated!'))
                    else:
                        infotext.append(_('Payment recived'))
                else:
                    if par.camp_price_total > 0:
                        infotext.append(_('Payment recived'))
                    else:
                        infotext.append(_('No Payment'))
            else:
                infotext.append(_('No Payment'))

            if len(par.jobber_pay_for_ids) > 1:
                infotext.append(_('Paying for: %s' % ', '.join(par.jobber_pay_for_ids.mapped('name'))))

            if len(par.jobber_child_ids) > 1:
                infotext.append(_('Children: %s' % ', '.join(par.jobber_child_ids.mapped('name'))))

            if not par.accomodation_ids:
                infotext.append(_('No accomonodation specified'))
                checkin_ok = False
            else:
                infotext.append(_('Check accomodation'))

            if not par.canteen_ids:
                infotext.append(_('No Catering specified'))
                checkin_ok = False
            else:
                infotext.append(_('Check catering'))

            #Infolines:
            if par.wristband_date:
                infotext.append(_(u'Skejser armbånd er udsendt/uddelt'))

            if checkin_ok:
                par.checkin_info_html = '
%s
' % '
'.join(infotext) if infotext else False
            else:
                par.checkin_info_html = '
%s
' % '
'.join(infotext) if infotext else False
            par.checkin_ok = checkin_ok

    @api.multi
    @api.depends('staff', 'jobber_child', 'accomodation_ids.accom_type_id', 'registration_id.subcamp_id', 'accomodation_ids.accom_group_id.subcamp_id')
    def _compute_checkin_subcamp_id(self):
        for par in self:
            if par.staff or par.jobber_child:
                if par.signup_state == 'oncamp':
                    if par.tocampdate < '2017-07-22':
                        par.checkin_subcamp_id = self.env['campos.subcamp'].browse(9)
                    else:
                        if par.accomodation_ids:
                            if par.accomodation_ids[0].accom_type_id.subcamp_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].subcamp_id
                            elif par.accomodation_ids[0].accom_type_id.group_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].registration_id.subcamp_id
                            elif par.accomodation_ids[0].accom_type_id.accomgroup_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].accom_group_id.subcamp_id
                            elif par.accomodation_ids[0].accom_type_id.camparea_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].camp_area_id.subcamp_id
                            else:
                                par.checkin_subcamp_id = par.accomodation_ids[0].accom_type_id.subcamp_id
                elif par.signup_state == 'groupsignup':
                    par.checkin_subcamp_id = par.registration_id.subcamp_id
            else:
                par.checkin_subcamp_id = par.registration_id.subcamp_id

    @api.multi
    @api.depends('camp_day_ids.will_participate','camp_day_ids.the_date')
    def _compute_firstcampdate(self):
        where_params = [tuple(self.ids)]
        self._cr.execute("""SELECT
                                participant_id as pat_id,
                                min(the_date) as firstcampdate
                            FROM campos_event_participant_day d
                            WHERE d.will_participate = 't' and participant_id in %s
                            GROUP BY participant_id;
                      """, where_params)
        for pat_id, firstcampdate in self._cr.fetchall():
            pat = self.browse(pat_id)
            pat.firstcampdate = firstcampdate

    @api.multi
    def action_checkin(self):
        self.ensure_one()
        self.state = 'arrived'
        self.arrive_time = fields.Datetime.now()
        self.suspend_security().generate_canteen_tickets()
        for c in self.jobber_child_ids:
            c.state = 'arrived'
            c.arrive_time = fields.Datetime.now()
            c.suspend_security().generate_canteen_tickets()

        if not self.checkin_ok and not self.env.user.has_group('campos_checkin.group_campos_checkin_mgr'):
            return self.env['warning_box'].info(title=_('Checkin'), message=_(u'Checkin for %s is not possible here\nGo to Løkkegård for Checkin.\n\nPlease show the location on the map for the ITS') %  (self.name))

        action = {
            'name': _("Checkin for %s") % (self.name),
            'view_mode': 'form',
            'view_type': 'form',
            'res_model': 'campos.checkin.wiz',
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            'target': 'new',
            'context': {
                'default_participant_id': self.id,
                },
        }
        _logger.info('ACTION: %s', action)
        return action

    @api.multi
    def action_cancel_checkin(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window.message',
            'title': _('Cancel Checkin'),
            'message': _("Change to 'Arrived' or 'Not yet arrived'"),
            'buttons': [
                {
                    'type': 'method',
                    'name': _('Arrived'),
                    'model': self._name,
                    'method': 'action_execute_cancel_checkin',
                    # list of arguments to pass positionally
                    'args': [self.ids],
                    # dictionary of keyword arguments
                    'kwargs': {'force_state': 'arrived'},
                },
                {
                    'type': 'method',
                    'name': _('Not yet arrived'),
                    'model': self._name,
                    'method': 'action_execute_cancel_checkin',
                    # list of arguments to pass positionally
                    'args': [self.ids],
                    # dictionary of keyword arguments
                    'kwargs': {'force_state': 'approved'},
                }
            ]
        }

    @api.multi
    def action_execute_cancel_checkin(self, force_state=None):
        self.ensure_one()
        if force_state:
            self.state = force_state
            if force_state == 'approved':
                self.arrive_time = False

    @api.multi
    def action_gen_invoice(self):
        self.ensure_one()
        par = self.suspend_security()
        ss = par.env['campos.fee.snapshot'].create({'code': 'CHECKIN',
                                                    'name': 'Checkin: %s' % par.name,
                                                    'execute_func': 'make_invoice_group',
                                                    'segment': 'jobber' if par.group_country_code2 == 'DK' else 'jobber_non_dk',
                                                    'single_reg_id': par.registration_id.id })

        par.registration_id.do_instant_snapshot(ss)
        if ss.ssreg_ids:
            if ss.ssreg_ids[0].invoice_id:
                view = ss.ssreg_ids[0].invoice_id.get_formview_id()
                action = {
                    'name': _("Invoice for %s") % (self.name),
                    'view_mode': 'form',
                    'view_type': 'form',
                    'views': [(view.id, 'form')],
                    'res_model': 'account.invoice',
                    'res_id' : ss.ssreg_ids[0].invoice_id.id,
                    'type': 'ir.actions.act_window',
                    'nodestroy': True,

                }
                _logger.info('ACTION: %s', action)
                return action
        return self.env['warning_box'].info(title=_('Checkin'), message=_('No invoice generated'))

    @api.model
    def recompute_to_from_dates(self):
        self._cr.execute("""SELECT
                                participant_id as par_id,
                                min(the_date) as x_tocampdate,
                                min(cep.tocampdate) as cep_tocamp,
                                max(the_date) as x_fromcampdate,
                                max(cep.fromcampdate) as cep_fromcamp
                            FROM campos_event_participant_day d
                            JOIN campos_event_participant cep ON cep.id = d.participant_id
                            JOIN res_partner p ON p.id=cep.partner_id
                            WHERE d.will_participate = 't' AND
                                cep.state <> 'deregistered' AND
                                p.participant = 't'
                  GROUP BY participant_id) cepd
WHERE (cepd.x_tocampdate <> cepd.cep_tocamp or cepd.x_fromcampdate <> cepd.cep_fromcamp);
                      """)
        for par_id, x_tocampdate, cep_tocamp, x_fromcampdate, cep_fromcamp in self._cr.fetchall():
            par = self.browse(par_id)
            if x_tocampdate != par.tocampdate:
                par.tocampdate = x_tocampdate
            if x_fromcampdate != par.fromcampdate:
                par.fromcampdate = x_fromcampdate
 <commit_msg>last camp date<commit_after># -*- coding: utf-8 -*-
# Copyright 2017 Stein & Gabelgaard ApS
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from openerp import api, fields, models, _

import logging
_logger = logging.getLogger(__name__)

class CamposEventParticipant(models.Model):

    _inherit = 'campos.event.participant'

    checkin_info_html = fields.Html('Check In Notes', compute='compute_checkin')
    checkin_ok = fields.Boolean('Check In possible', compute='compute_checkin')
    arrive_time = fields.Datetime('Arrival')
    checkin_completed = fields.Datetime('Check In Time')
    checkin_subcamp_id = fields.Many2one('campos.subcamp', 'Sub Camp', compute='_compute_checkin_subcamp_id', store=True)
    not_invoiced = fields.Boolean('Not invoiced', compute='compute_checkin')
    firstcampdate = fields.Date('First Camp Date', compute='_compute_firstcampdate', store=True)
    lastcampdate = fields.Date('Last Camp Date', compute='_compute_lastcampdate', store=True)

    @api.multi
    #@api.depends()
    def compute_checkin(self):
        for par in self:
            ckr_clc = False
            checkin_ok = True
            infotext = []
            if par.clc_state:
                if par.clc_state != 'passed' and par.camp_age >= 18:
                    infotext.append(_('CLC not passed!'))
                    checkin_ok = False
            elif par.ckr_state != 'approved' and par.camp_age >= 15:
                infotext.append(_('CKR not yet approved!'))
                checkin_ok = False
            #Economy
            if par.signup_state in ['oncamp']:
                if par.registration_id.partner_id != par.partner_id:
                    infotext.append(_('Paid by: %s') % (par.registration_id.partner_id.name))
                elif par.registration_id.partner_id.credit > 0:
                    infotext.append(_('Unpaid invoices. Total due: DKK %.2f') % (par.registration_id.partner_id.credit))
                    checkin_ok = False
                elif par.registration_id.partner_id.credit == 0 and not par.sudo().no_invoicing and par.camp_price_total > 0:
                    if self.env['account.invoice'].search_count([('partner_id', '=', par.registration_id.partner_id.id), ('state', 'in', ['open','paid'])]) == 0:
                        par.not_invoiced = True
                        checkin_ok = False
                        infotext.append(_('Invoice not yet generated!'))
                    else:
                        infotext.append(_('Payment recived'))
                else:
                    if par.camp_price_total > 0:
                        infotext.append(_('Payment recived'))
                    else:
                        infotext.append(_('No Payment'))
            else:
                infotext.append(_('No Payment'))

            if len(par.jobber_pay_for_ids) > 1:
                infotext.append(_('Paying for: %s' % ', '.join(par.jobber_pay_for_ids.mapped('name'))))

            if len(par.jobber_child_ids) > 1:
                infotext.append(_('Children: %s' % ', '.join(par.jobber_child_ids.mapped('name'))))

            if not par.accomodation_ids:
                infotext.append(_('No accomonodation specified'))
                checkin_ok = False
            else:
                infotext.append(_('Check accomodation'))

            if not par.canteen_ids:
                infotext.append(_('No Catering specified'))
                checkin_ok = False
            else:
                infotext.append(_('Check catering'))

            #Infolines:
            if par.wristband_date:
                infotext.append(_(u'Skejser armbånd er udsendt/uddelt'))

            if checkin_ok:
                par.checkin_info_html = '
%s
' % '
'.join(infotext) if infotext else False
            else:
                par.checkin_info_html = '
%s
' % '
'.join(infotext) if infotext else False
            par.checkin_ok = checkin_ok

    @api.multi
    @api.depends('staff', 'jobber_child', 'accomodation_ids.accom_type_id', 'registration_id.subcamp_id', 'accomodation_ids.accom_group_id.subcamp_id')
    def _compute_checkin_subcamp_id(self):
        for par in self:
            if par.staff or par.jobber_child:
                if par.signup_state == 'oncamp':
                    if par.tocampdate < '2017-07-22':
                        par.checkin_subcamp_id = self.env['campos.subcamp'].browse(9)
                    else:
                        if par.accomodation_ids:
                            if par.accomodation_ids[0].accom_type_id.subcamp_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].subcamp_id
                            elif par.accomodation_ids[0].accom_type_id.group_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].registration_id.subcamp_id
                            elif par.accomodation_ids[0].accom_type_id.accomgroup_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].accom_group_id.subcamp_id
                            elif par.accomodation_ids[0].accom_type_id.camparea_sel:
                                par.checkin_subcamp_id = par.accomodation_ids[0].camp_area_id.subcamp_id
                            else:
                                par.checkin_subcamp_id = par.accomodation_ids[0].accom_type_id.subcamp_id
                elif par.signup_state == 'groupsignup':
                    par.checkin_subcamp_id = par.registration_id.subcamp_id
            else:
                par.checkin_subcamp_id = par.registration_id.subcamp_id

    @api.multi
    @api.depends('camp_day_ids.will_participate','camp_day_ids.the_date')
    def _compute_firstcampdate(self):
        where_params = [tuple(self.ids)]
        self._cr.execute("""SELECT
                                participant_id as pat_id,
                                min(the_date) as firstcampdate
                            FROM campos_event_participant_day d
                            WHERE d.will_participate = 't' and participant_id in %s
                            GROUP BY participant_id;
                      """, where_params)
        for pat_id, firstcampdate in self._cr.fetchall():
            pat = self.browse(pat_id)
            pat.firstcampdate = firstcampdate

    @api.multi
    @api.depends('camp_day_ids.will_participate','camp_day_ids.the_date')
    def _compute_lastcampdate(self):
        where_params = [tuple(self.ids)]
        self._cr.execute("""SELECT
                                participant_id as pat_id,
                                max(the_date) as lastcampdate
                            FROM campos_event_participant_day d
                            WHERE d.will_participate = 't' and participant_id in %s
                            GROUP BY participant_id;
                      """, where_params)
        for pat_id, lastcampdate in self._cr.fetchall():
            pat = self.browse(pat_id)
            pat.lastcampdate = lastcampdate

    @api.multi
    def action_checkin(self):
        self.ensure_one()
        self.state = 'arrived'
        self.arrive_time = fields.Datetime.now()
        self.suspend_security().generate_canteen_tickets()
        for c in self.jobber_child_ids:
            c.state = 'arrived'
            c.arrive_time = fields.Datetime.now()
            c.suspend_security().generate_canteen_tickets()

        if not self.checkin_ok and not self.env.user.has_group('campos_checkin.group_campos_checkin_mgr'):
            return self.env['warning_box'].info(title=_('Checkin'), message=_(u'Checkin for %s is not possible here\nGo to Løkkegård for Checkin.\n\nPlease show the location on the map for the ITS') %  (self.name))

        action = {
            'name': _("Checkin for %s") % (self.name),
            'view_mode': 'form',
            'view_type': 'form',
            'res_model': 'campos.checkin.wiz',
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            'target': 'new',
            'context': {
                'default_participant_id': self.id,
                },
        }
        _logger.info('ACTION: %s', action)
        return action

    @api.multi
    def action_cancel_checkin(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window.message',
            'title': _('Cancel Checkin'),
            'message': _("Change to 'Arrived' or 'Not yet arrived'"),
            'buttons': [
                {
                    'type': 'method',
                    'name': _('Arrived'),
                    'model': self._name,
                    'method': 'action_execute_cancel_checkin',
                    # list of arguments to pass positionally
                    'args': [self.ids],
                    # dictionary of keyword arguments
                    'kwargs': {'force_state': 'arrived'},
                },
                {
                    'type': 'method',
                    'name': _('Not yet arrived'),
                    'model': self._name,
                    'method': 'action_execute_cancel_checkin',
                    # list of arguments to pass positionally
                    'args': [self.ids],
                    # dictionary of keyword arguments
                    'kwargs': {'force_state': 'approved'},
                }
            ]
        }

    @api.multi
    def action_execute_cancel_checkin(self, force_state=None):
        self.ensure_one()
        if force_state:
            self.state = force_state
            if force_state == 'approved':
                self.arrive_time = False

    @api.multi
    def action_gen_invoice(self):
        self.ensure_one()
        par = self.suspend_security()
        ss = par.env['campos.fee.snapshot'].create({'code': 'CHECKIN',
                                                    'name': 'Checkin: %s' % par.name,
                                                    'execute_func': 'make_invoice_group',
                                                    'segment': 'jobber' if par.group_country_code2 == 'DK' else 'jobber_non_dk',
                                                    'single_reg_id': par.registration_id.id })

        par.registration_id.do_instant_snapshot(ss)
        if ss.ssreg_ids:
            if ss.ssreg_ids[0].invoice_id:
                view = ss.ssreg_ids[0].invoice_id.get_formview_id()
                action = {
                    'name': _("Invoice for %s") % (self.name),
                    'view_mode': 'form',
                    'view_type': 'form',
                    'views': [(view.id, 'form')],
                    'res_model': 'account.invoice',
                    'res_id' : ss.ssreg_ids[0].invoice_id.id,
                    'type': 'ir.actions.act_window',
                    'nodestroy': True,

                }
                _logger.info('ACTION: %s', action)
                return action
        return self.env['warning_box'].info(title=_('Checkin'), message=_('No invoice generated'))

    @api.model
    def recompute_to_from_dates(self):
        self._cr.execute("""SELECT
                                participant_id as par_id,
                                min(the_date) as x_tocampdate,
                                min(cep.tocampdate) as cep_tocamp,
                                max(the_date) as x_fromcampdate,
                                max(cep.fromcampdate) as cep_fromcamp
                            FROM campos_event_participant_day d
                            JOIN campos_event_participant cep ON cep.id = d.participant_id
                            JOIN res_partner p ON p.id=cep.partner_id
                            WHERE d.will_participate = 't' AND
                                cep.state <> 'deregistered' AND
                                p.participant = 't'
                  GROUP BY participant_id) cepd
WHERE (cepd.x_tocampdate <> cepd.cep_tocamp or cepd.x_fromcampdate <> cepd.cep_fromcamp);
                      """)
        for par_id, x_tocampdate, cep_tocamp, x_fromcampdate, cep_fromcamp in self._cr.fetchall():
            par = self.browse(par_id)
            if x_tocampdate != par.tocampdate:
                par.tocampdate = x_tocampdate
            if x_fromcampdate != par.fromcampdate:
                par.fromcampdate = x_fromcampdate
 <|endoftext|>


<commit_before>#!/usr/bin/python

import lldb
import fblldbbase as fb
import fblldbobjcruntimehelpers as objc

import sys
import os
import re

def lldbcommands():
  return [
    FBWatchInstanceVariableCommand(),
    FBFrameworkAddressBreakpointCommand(),
    FBMethodBreakpointCommand(),
    FBMemoryWarningCommand(),
    FBFindInstancesCommand(),
    FBMethodBreakpointEnableCommand(),
    FBMethodBreakpointDisableCommand(),
    FBHeapFromCommand(),
    FBSequenceCommand(),
  ]

class FBWatchInstanceVariableCommand(fb.FBCommand):
  def name(self):
    return 'wivar'

  def description(self):
    return "Set a watchpoint for an object's instance variable."

  def args(self):
    return [
      fb.FBCommandArgument(arg='object', type='id', help='Object expression to be evaluated.'),
      fb.FBCommandArgument(arg='ivarName', help='Name of the instance variable to watch.')
    ]

  def run(self, arguments, options):
    commandForObject, ivarName = arguments

    objectAddress = int(fb.evaluateObjectExpression(commandForObject), 0)

    ivarOffsetCommand = '(ptrdiff_t)ivar_getOffset((void*)object_getInstanceVariable((id){}, "{}", 0))'.format(objectAddress, ivarName)
    ivarOffset = int(fb.evaluateExpression(ivarOffsetCommand), 0)

    # A multi-statement command allows for variables scoped to the command, not permanent in the session like $variables.
    ivarSizeCommand = ('unsigned int size = 0;'
                       'char *typeEncoding = (char *)ivar_getTypeEncoding((void*)class_getInstanceVariable((Class)object_getClass((id){}), "{}"));'
                       '(char *)NSGetSizeAndAlignment(typeEncoding, &size, 0);'
                       'size').format(objectAddress, ivarName)
    ivarSize = int(fb.evaluateExpression(ivarSizeCommand), 0)

    error = lldb.SBError()
    watchpoint = lldb.debugger.GetSelectedTarget().WatchAddress(objectAddress + ivarOffset, ivarSize, False, True, error)

    if error.Success():
      print 'Remember to delete the watchpoint using: watchpoint delete {}'.format(watchpoint.GetID())
    else:
      print 'Could not create the watchpoint: {}'.format(error.GetCString())

class FBFrameworkAddressBreakpointCommand(fb.FBCommand):
  def name(self):
    return 'binside'

  def description(self):
    return "Set a breakpoint for a relative address within the framework/library that's currently running. This does the work of finding the offset for the framework/library and sliding your address accordingly."

  def args(self):
    return [
      fb.FBCommandArgument(arg='address', type='string', help='Address within the currently running framework to set a breakpoint on.'),
    ]

  def run(self, arguments, options):
    library_address = int(arguments[0], 0)
    address = int(lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetModule().ResolveFileAddress(library_address))

    lldb.debugger.HandleCommand('breakpoint set --address {}'.format(address))

class FBMethodBreakpointCommand(fb.FBCommand):
  def name(self):
    return 'bmessage'

  def description(self):
    return "Set a breakpoint for a selector on a class, even if the class itself doesn't override that selector. It walks the hierarchy until it finds a class that does implement the selector and sets a conditional breakpoint there."

  def args(self):
    return [
      fb.FBCommandArgument(arg='expression', type='string', help='Expression to set a breakpoint on, e.g. "-[MyView setFrame:]", "+[MyView awesomeClassMethod]" or "-[0xabcd1234 setFrame:]"'),
    ]

  def run(self, arguments, options):
    expression = arguments[0]

    methodPattern = re.compile(r"""
      (?P<scope>[-+])?
      \[
        (?P<target>.*?)
        (?P<category>\(.+\))?
        \s+
        (?P<selector>.*)
      \]
""", re.VERBOSE)

    match = methodPattern.match(expression)

    if not match:
      print 'Failed to parse expression. Do you even Objective-C?!'
      return

    expressionForSelf = objc.functionPreambleExpressionForSelf()
    if not expressionForSelf:
      print 'Your architecture, {}, is truly fantastic. However, I don\'t currently support it.'.format(arch)
      return

    methodTypeCharacter = match.group('scope')
    classNameOrExpression = match.group('target')
    category = match.group('category')
    selector = match.group('selector')

    methodIsClassMethod = (methodTypeCharacter == '+')

    if not methodIsClassMethod:
      # The default is instance method, and methodTypeCharacter may not actually be '-'.
      methodTypeCharacter = '-'

    targetIsClass = False
    targetObject = fb.evaluateObjectExpression('({})'.format(classNameOrExpression), False)

    if not targetObject:
      # If the expression didn't yield anything then it's likely a class. Assume it is.
      # We will check again that the class does actually exist anyway.
      targetIsClass = True
      targetObject = fb.evaluateObjectExpression('[{} class]'.format(classNameOrExpression), False)

    targetClass = fb.evaluateObjectExpression('[{} class]'.format(targetObject), False)

    if not targetClass or int(targetClass, 0) == 0:
      print 'Couldn\'t find a class from the expression "{}". Did you typo?'.format(classNameOrExpression)
      return

    if methodIsClassMethod:
      targetClass = objc.object_getClass(targetClass)

    found = False
    nextClass = targetClass

    while not found and int(nextClass, 0) > 0:
      if classItselfImplementsSelector(nextClass, selector):
        found = True
      else:
        nextClass = objc.class_getSuperclass(nextClass)

    if not found:
      print 'There doesn\'t seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?'.format(selector)
      return

    breakpointClassName = objc.class_getName(nextClass)
    formattedCategory = category if category else ''
    breakpointFullName = '{}[{}{} {}]'.format(methodTypeCharacter, breakpointClassName, formattedCategory, selector)

    if targetIsClass:
      breakpointCondition = '(void*)object_getClass({}) == {}'.format(expressionForSelf, targetClass)
    else:
      breakpointCondition = '(void*){} == {}'.format(expressionForSelf, targetObject)

    print 'Setting a breakpoint at {} with condition {}'.format(breakpointFullName, breakpointCondition)

    if category:
      lldb.debugger.HandleCommand('breakpoint set --skip-prologue false --fullname "{}" --condition "{}"'.format(breakpointFullName, breakpointCondition))
    else:
      breakpointPattern = '{}\[{}(\(.+\))? {}\]'.format(methodTypeCharacter, breakpointClassName, selector)
      lldb.debugger.HandleCommand('breakpoint set --skip-prologue false --func-regex "{}" --condition "{}"'.format(breakpointPattern, breakpointCondition))

def classItselfImplementsSelector(klass, selector):
  thisMethod = objc.class_getInstanceMethod(klass, selector)
  if thisMethod == 0:
    return False

  superklass = objc.class_getSuperclass(klass)
  superMethod = objc.class_getInstanceMethod(superklass, selector)
  if thisMethod == superMethod:
    return False
  else:
    return True

class FBMemoryWarningCommand(fb.FBCommand):
  def name(self):
    return 'mwarning'

  def description(self):
    return 'simulate a memory warning'

  def run(self, arguments, options):
    fb.evaluateEffect('[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)]')

def switchBreakpointState(expression,on):

  expression_pattern = re.compile(r'{}'.format(expression),re.I)

  target = lldb.debugger.GetSelectedTarget()
  for breakpoint in target.breakpoint_iter():
    if breakpoint.IsEnabled() != on and (expression_pattern.search(str(breakpoint))):
      print str(breakpoint)
      breakpoint.SetEnabled(on)
    for location in breakpoint:
      if location.IsEnabled() != on and (expression_pattern.search(str(location)) or expression == hex(location.GetAddress()) ):
        print str(location)
        location.SetEnabled(on)

class FBMethodBreakpointEnableCommand(fb.FBCommand):
  def name(self):
    return 'benable'

  def description(self):
    return """
    Enable a set of breakpoints for a regular expression

    Examples:

          * benable ***address***
          benable 0x0000000104514dfc
          benable 0x183e23564

          #use `benable *filename*` to switch all breakpoints in this file to `enable`
          benable SUNNetService.m

          #use `benable ***module(AppName)***` to switch all breakpoints in this module to `enable`
          benable UIKit
          benable Foundation

    """

  def args(self):
    return [
      fb.FBCommandArgument(arg='expression', type='string', help='Expression to enable breakpoint'),
    ]

  def run(self, arguments, options):
    expression = arguments[0]
    switchBreakpointState(expression,True)

class FBMethodBreakpointDisableCommand(fb.FBCommand):
  def name(self):
    return 'bdisable'

  def description(self):
    return """
    Disable a set of breakpoints for a regular expression

    Examples:

          * bdisable ***address***
          bdisable 0x0000000104514dfc
          bdisable 0x183e23564

          #use `bdisable *filename*` to switch all breakpoints in this file to `disable`
          bdisable SUNNetService.m

          #use `bdisable ***module(AppName)***` to switch all breakpoints in this module to `disable`
          bdisable UIKit
          bdisable Foundation

    """
  def args(self):
    return [
      fb.FBCommandArgument(arg='expression', type='string', help='Expression to disable breakpoint'),
    ]

  def run(self, arguments, options):
    expression = arguments[0]
    switchBreakpointState(expression,False)

class FBFindInstancesCommand(fb.FBCommand):
  def name(self):
    return 'findinstances'

  def args(self):
    return [
      fb.FBCommandArgument(arg='type', help='Class or protocol name'),
      fb.FBCommandArgument(arg='query', default=' ', # space is a hack to mark optional
                           help='Query expression, uses NSPredicate syntax')
    ]

  def description(self):
    return """
    Find instances of specified ObjC classes.

    This command scans memory and uses heuristics to identify instances of
    Objective-C classes. This includes Swift classes that descend from NSObject.

    Basic examples:

        findinstances UIScrollView
        findinstances *UIScrollView
        findinstances UIScrollViewDelegate

    These basic searches find instances of the given class or protocol. By
    default, subclasses of the class or protocol are included in the results. To
    find exact class instances, add a `*` prefix, for example: *UIScrollView.

    Advanced examples:

        # Find views that are either: hidden, invisible, or not in a window
        findinstances UIView hidden == true || alpha == 0 || window == nil
        # Find views that have either a zero width or zero height
        findinstances UIView layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0
        # Find leaf views that have no subviews
        findinstances UIView subviews.@count == 0
        # Find dictionaries that have keys that might be passwords or passphrases
        findinstances NSDictionary any @allKeys beginswith 'pass'

    These examples make use of a filter. The filter is implemented with
    NSPredicate, see its documentaiton for more details. Basic NSPredicate
    expressions have relatively predicatable syntax. There are some exceptions
    as seen above, see https://github.com/facebook/chisel/wiki/findinstances.
    """

  def lex(self, commandLine):
    # Can't use default shlex splitting because it strips quotes, which results
    # in invalid NSPredicate syntax. Split the input into type and rest (query).
    return commandLine.split(' ', 1)

  def run(self, arguments, options):
    if not self.loadChiselIfNecessary():
      return

    if len(arguments) == 0 or not arguments[0].strip():
      print 'Usage: findinstances <classOrProtocol> [<predicate>]; Run `help findinstances`'
      return

    query = arguments[0]
    predicate = arguments[1].strip()
    # Escape double quotes and backslashes.
    predicate = re.sub('([\\"])', r'\\\1', predicate)
    call = '(void)PrintInstances("{}", "{}")'.format(query, predicate)
    fb.evaluateExpressionValue(call)

  def loadChiselIfNecessary(self):
    target = lldb.debugger.GetSelectedTarget()
    if target.module['Chisel']:
      return True

    path = self.chiselLibraryPath()
    if not os.path.exists(path):
      print 'Chisel library missing: ' + path
      return False

    module = fb.evaluateExpressionValue('(void*)dlopen("{}", 2)'.format(path))
    if module.unsigned != 0 or target.module['Chisel']:
      return True

    # `errno` is a macro that expands to a call to __error(). In development,
    # lldb was not getting a correct value for `errno`, so `__error()` is used.
    errno = fb.evaluateExpressionValue('*(int*)__error()').value
    error = fb.evaluateExpressionValue('(char*)dlerror()')
    if errno == 50:
      # KERN_CODESIGN_ERROR from <mach/kern_return.h>
      print 'Error loading Chisel: Code signing failure; Must re-run codesign'
    elif error.unsigned != 0:
      print 'Error loading Chisel: ' + error.summary
    elif errno != 0:
      error = fb.evaluateExpressionValue('(char*)strerror({})'.format(errno))
      if error.unsigned != 0:
        print 'Error loading Chisel: ' + error.summary
      else:
        print 'Error loading Chisel (errno {})'.format(errno)
    else:
      print 'Unknown error loading Chisel'

    return False

  def chiselLibraryPath(self):
    # script os.environ['CHISEL_LIBRARY_PATH'] = '/path/to/custom/Chisel'
    path = os.getenv('CHISEL_LIBRARY_PATH')
    if path and os.path.exists(path):
      return path

    source_path = sys.modules[__name__].__file__
    source_dir = os.path.dirname(source_path)
    # ugh: ../.. is to back out of commands/, then back out of libexec/
    return os.path.join(source_dir, '..', '..', 'lib', 'Chisel.framework', 'Chisel')

class FBHeapFromCommand(fb.FBCommand):
  def name(self):
    return 'heapfrom'

  def description(self):
    return 'Show all nested heap pointers contained within a given variable.'

  def run(self, arguments, options):
    # This command is like `expression --synthetic-type false`, except only showing nested heap references.
    var = self.context.frame.var(arguments[0])
    if not var or not var.IsValid():
      self.result.SetError('No variable named "{}"'.format(arguments[0]))
      return

    # Use the actual underlying structure of the variable, not the human friendly (synthetic) one.
    root = var.GetNonSyntheticValue()

    # Traversal of SBValue tree to get leaf nodes, which is where heap pointers will be.
    leafs = []
    queue = [root]
    while queue:
        node = queue.pop(0)
        if node.num_children == 0:
            leafs.append(node)
        else:
            queue += [node.GetChildAtIndex(i) for i in range(node.num_children)]

    pointers = {}
    for node in leafs:
        # Assumption: an addr that has no value means a pointer.
        if node.addr and not node.value:
            pointers[node.load_addr] = node.path

    options = lldb.SBExpressionOptions()
    options.SetLanguage(lldb.eLanguageTypeC)
    def isHeap(addr):
        lookup = '(int)malloc_size({})'.format(addr)
        return self.context.frame.EvaluateExpression(lookup, options).unsigned != 0

    allocations = (addr for addr in pointers if isHeap(addr))
    for addr in allocations:
        print >>self.result, '0x{addr:x} {path}'.format(addr=addr, path=pointers[addr])
    if not allocations:
        print >>self.result, "No heap addresses found"

class FBSequenceCommand(fb.FBCommand):
  def name(self):
    return 'sequence'

  def description(self):
    return 'Run commands in sequence, stopping on any error.'

  def lex(self, commandLine):
    return commandLine.split(';')

  def run(self, arguments, options):
    interpreter = lldb.debugger.GetCommandInterpreter()
    # The full unsplit command is in position 0.
    sequence = arguments[1:]
    for command in sequence:
      command = command.split()
      if not command:
        continue
      object = lldb.SBCommandReturnObject()
      interpreter.HandleCommand(command, self.context, object)
      if object.GetOutput():
        print >>self.result, object.GetOutput().strip()

      if not object.Succeeded():
        if object.GetError():
          self.result.SetError(object.GetError())
        self.result.SetStatus(object.GetStatus())
        return
<commit_msg>Call strip not split<commit_after>#!/usr/bin/python

import lldb
import fblldbbase as fb
import fblldbobjcruntimehelpers as objc

import sys
import os
import re

def lldbcommands():
  return [
    FBWatchInstanceVariableCommand(),
    FBFrameworkAddressBreakpointCommand(),
    FBMethodBreakpointCommand(),
    FBMemoryWarningCommand(),
    FBFindInstancesCommand(),
    FBMethodBreakpointEnableCommand(),
    FBMethodBreakpointDisableCommand(),
    FBHeapFromCommand(),
    FBSequenceCommand(),
  ]

class FBWatchInstanceVariableCommand(fb.FBCommand):
  def name(self):
    return 'wivar'

  def description(self):
    return "Set a watchpoint for an object's instance variable."

  def args(self):
    return [
      fb.FBCommandArgument(arg='object', type='id', help='Object expression to be evaluated.'),
      fb.FBCommandArgument(arg='ivarName', help='Name of the instance variable to watch.')
    ]

  def run(self, arguments, options):
    commandForObject, ivarName = arguments

    objectAddress = int(fb.evaluateObjectExpression(commandForObject), 0)

    ivarOffsetCommand = '(ptrdiff_t)ivar_getOffset((void*)object_getInstanceVariable((id){}, "{}", 0))'.format(objectAddress, ivarName)
    ivarOffset = int(fb.evaluateExpression(ivarOffsetCommand), 0)

    # A multi-statement command allows for variables scoped to the command, not permanent in the session like $variables.
    ivarSizeCommand = ('unsigned int size = 0;'
                       'char *typeEncoding = (char *)ivar_getTypeEncoding((void*)class_getInstanceVariable((Class)object_getClass((id){}), "{}"));'
                       '(char *)NSGetSizeAndAlignment(typeEncoding, &size, 0);'
                       'size').format(objectAddress, ivarName)
    ivarSize = int(fb.evaluateExpression(ivarSizeCommand), 0)

    error = lldb.SBError()
    watchpoint = lldb.debugger.GetSelectedTarget().WatchAddress(objectAddress + ivarOffset, ivarSize, False, True, error)

    if error.Success():
      print 'Remember to delete the watchpoint using: watchpoint delete {}'.format(watchpoint.GetID())
    else:
      print 'Could not create the watchpoint: {}'.format(error.GetCString())

class FBFrameworkAddressBreakpointCommand(fb.FBCommand):
  def name(self):
    return 'binside'

  def description(self):
    return "Set a breakpoint for a relative address within the framework/library that's currently running. This does the work of finding the offset for the framework/library and sliding your address accordingly."

  def args(self):
    return [
      fb.FBCommandArgument(arg='address', type='string', help='Address within the currently running framework to set a breakpoint on.'),
    ]

  def run(self, arguments, options):
    library_address = int(arguments[0], 0)
    address = int(lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetModule().ResolveFileAddress(library_address))

    lldb.debugger.HandleCommand('breakpoint set --address {}'.format(address))

class FBMethodBreakpointCommand(fb.FBCommand):
  def name(self):
    return 'bmessage'

  def description(self):
    return "Set a breakpoint for a selector on a class, even if the class itself doesn't override that selector. It walks the hierarchy until it finds a class that does implement the selector and sets a conditional breakpoint there."

  def args(self):
    return [
      fb.FBCommandArgument(arg='expression', type='string', help='Expression to set a breakpoint on, e.g. "-[MyView setFrame:]", "+[MyView awesomeClassMethod]" or "-[0xabcd1234 setFrame:]"'),
    ]

  def run(self, arguments, options):
    expression = arguments[0]

    methodPattern = re.compile(r"""
      (?P<scope>[-+])?
      \[
        (?P<target>.*?)
        (?P<category>\(.+\))?
        \s+
        (?P<selector>.*)
      \]
""", re.VERBOSE)

    match = methodPattern.match(expression)

    if not match:
      print 'Failed to parse expression. Do you even Objective-C?!'
      return

    expressionForSelf = objc.functionPreambleExpressionForSelf()
    if not expressionForSelf:
      print 'Your architecture, {}, is truly fantastic. However, I don\'t currently support it.'.format(arch)
      return

    methodTypeCharacter = match.group('scope')
    classNameOrExpression = match.group('target')
    category = match.group('category')
    selector = match.group('selector')

    methodIsClassMethod = (methodTypeCharacter == '+')

    if not methodIsClassMethod:
      # The default is instance method, and methodTypeCharacter may not actually be '-'.
      methodTypeCharacter = '-'

    targetIsClass = False
    targetObject = fb.evaluateObjectExpression('({})'.format(classNameOrExpression), False)

    if not targetObject:
      # If the expression didn't yield anything then it's likely a class. Assume it is.
      # We will check again that the class does actually exist anyway.
      targetIsClass = True
      targetObject = fb.evaluateObjectExpression('[{} class]'.format(classNameOrExpression), False)

    targetClass = fb.evaluateObjectExpression('[{} class]'.format(targetObject), False)

    if not targetClass or int(targetClass, 0) == 0:
      print 'Couldn\'t find a class from the expression "{}". Did you typo?'.format(classNameOrExpression)
      return

    if methodIsClassMethod:
      targetClass = objc.object_getClass(targetClass)

    found = False
    nextClass = targetClass

    while not found and int(nextClass, 0) > 0:
      if classItselfImplementsSelector(nextClass, selector):
        found = True
      else:
        nextClass = objc.class_getSuperclass(nextClass)

    if not found:
      print 'There doesn\'t seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?'.format(selector)
      return

    breakpointClassName = objc.class_getName(nextClass)
    formattedCategory = category if category else ''
    breakpointFullName = '{}[{}{} {}]'.format(methodTypeCharacter, breakpointClassName, formattedCategory, selector)

    if targetIsClass:
      breakpointCondition = '(void*)object_getClass({}) == {}'.format(expressionForSelf, targetClass)
    else:
      breakpointCondition = '(void*){} == {}'.format(expressionForSelf, targetObject)

    print 'Setting a breakpoint at {} with condition {}'.format(breakpointFullName, breakpointCondition)

    if category:
      lldb.debugger.HandleCommand('breakpoint set --skip-prologue false --fullname "{}" --condition "{}"'.format(breakpointFullName, breakpointCondition))
    else:
      breakpointPattern = '{}\[{}(\(.+\))? {}\]'.format(methodTypeCharacter, breakpointClassName, selector)
      lldb.debugger.HandleCommand('breakpoint set --skip-prologue false --func-regex "{}" --condition "{}"'.format(breakpointPattern, breakpointCondition))

def classItselfImplementsSelector(klass, selector):
  thisMethod = objc.class_getInstanceMethod(klass, selector)
  if thisMethod == 0:
    return False

  superklass = objc.class_getSuperclass(klass)
  superMethod = objc.class_getInstanceMethod(superklass, selector)
  if thisMethod == superMethod:
    return False
  else:
    return True

class FBMemoryWarningCommand(fb.FBCommand):
  def name(self):
    return 'mwarning'

  def description(self):
    return 'simulate a memory warning'

  def run(self, arguments, options):
    fb.evaluateEffect('[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)]')

def switchBreakpointState(expression,on):

  expression_pattern = re.compile(r'{}'.format(expression),re.I)

  target = lldb.debugger.GetSelectedTarget()
  for breakpoint in target.breakpoint_iter():
    if breakpoint.IsEnabled() != on and (expression_pattern.search(str(breakpoint))):
      print str(breakpoint)
      breakpoint.SetEnabled(on)
    for location in breakpoint:
      if location.IsEnabled() != on and (expression_pattern.search(str(location)) or expression == hex(location.GetAddress()) ):
        print str(location)
        location.SetEnabled(on)

class FBMethodBreakpointEnableCommand(fb.FBCommand):
  def name(self):
    return 'benable'

  def description(self):
    return """
    Enable a set of breakpoints for a regular expression

    Examples:

          * benable ***address***
          benable 0x0000000104514dfc
          benable 0x183e23564

          #use `benable *filename*` to switch all breakpoints in this file to `enable`
          benable SUNNetService.m

          #use `benable ***module(AppName)***` to switch all breakpoints in this module to `enable`
          benable UIKit
          benable Foundation

    """

  def args(self):
    return [
      fb.FBCommandArgument(arg='expression', type='string', help='Expression to enable breakpoint'),
    ]

  def run(self, arguments, options):
    expression = arguments[0]
    switchBreakpointState(expression,True)

class FBMethodBreakpointDisableCommand(fb.FBCommand):
  def name(self):
    return 'bdisable'

  def description(self):
    return """
    Disable a set of breakpoints for a regular expression

    Examples:

          * bdisable ***address***
          bdisable 0x0000000104514dfc
          bdisable 0x183e23564

          #use `bdisable *filename*` to switch all breakpoints in this file to `disable`
          bdisable SUNNetService.m

          #use `bdisable ***module(AppName)***` to switch all breakpoints in this module to `disable`
          bdisable UIKit
          bdisable Foundation

    """
  def args(self):
    return [
      fb.FBCommandArgument(arg='expression', type='string', help='Expression to disable breakpoint'),
    ]

  def run(self, arguments, options):
    expression = arguments[0]
    switchBreakpointState(expression,False)

class FBFindInstancesCommand(fb.FBCommand):
  def name(self):
    return 'findinstances'

  def args(self):
    return [
      fb.FBCommandArgument(arg='type', help='Class or protocol name'),
      fb.FBCommandArgument(arg='query', default=' ', # space is a hack to mark optional
                           help='Query expression, uses NSPredicate syntax')
    ]

  def description(self):
    return """
    Find instances of specified ObjC classes.

    This command scans memory and uses heuristics to identify instances of
    Objective-C classes. This includes Swift classes that descend from NSObject.

    Basic examples:

        findinstances UIScrollView
        findinstances *UIScrollView
        findinstances UIScrollViewDelegate

    These basic searches find instances of the given class or protocol. By
    default, subclasses of the class or protocol are included in the results. To
    find exact class instances, add a `*` prefix, for example: *UIScrollView.

    Advanced examples:

        # Find views that are either: hidden, invisible, or not in a window
        findinstances UIView hidden == true || alpha == 0 || window == nil
        # Find views that have either a zero width or zero height
        findinstances UIView layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0
        # Find leaf views that have no subviews
        findinstances UIView subviews.@count == 0
        # Find dictionaries that have keys that might be passwords or passphrases
        findinstances NSDictionary any @allKeys beginswith 'pass'

    These examples make use of a filter. The filter is implemented with
    NSPredicate, see its documentaiton for more details. Basic NSPredicate
    expressions have relatively predicatable syntax. There are some exceptions
    as seen above, see https://github.com/facebook/chisel/wiki/findinstances.
    """

  def lex(self, commandLine):
    # Can't use default shlex splitting because it strips quotes, which results
    # in invalid NSPredicate syntax. Split the input into type and rest (query).
    return commandLine.split(' ', 1)

  def run(self, arguments, options):
    if not self.loadChiselIfNecessary():
      return

    if len(arguments) == 0 or not arguments[0].strip():
      print 'Usage: findinstances <classOrProtocol> [<predicate>]; Run `help findinstances`'
      return

    query = arguments[0]
    predicate = arguments[1].strip()
    # Escape double quotes and backslashes.
    predicate = re.sub('([\\"])', r'\\\1', predicate)
    call = '(void)PrintInstances("{}", "{}")'.format(query, predicate)
    fb.evaluateExpressionValue(call)

  def loadChiselIfNecessary(self):
    target = lldb.debugger.GetSelectedTarget()
    if target.module['Chisel']:
      return True

    path = self.chiselLibraryPath()
    if not os.path.exists(path):
      print 'Chisel library missing: ' + path
      return False

    module = fb.evaluateExpressionValue('(void*)dlopen("{}", 2)'.format(path))
    if module.unsigned != 0 or target.module['Chisel']:
      return True

    # `errno` is a macro that expands to a call to __error(). In development,
    # lldb was not getting a correct value for `errno`, so `__error()` is used.
    errno = fb.evaluateExpressionValue('*(int*)__error()').value
    error = fb.evaluateExpressionValue('(char*)dlerror()')
    if errno == 50:
      # KERN_CODESIGN_ERROR from <mach/kern_return.h>
      print 'Error loading Chisel: Code signing failure; Must re-run codesign'
    elif error.unsigned != 0:
      print 'Error loading Chisel: ' + error.summary
    elif errno != 0:
      error = fb.evaluateExpressionValue('(char*)strerror({})'.format(errno))
      if error.unsigned != 0:
        print 'Error loading Chisel: ' + error.summary
      else:
        print 'Error loading Chisel (errno {})'.format(errno)
    else:
      print 'Unknown error loading Chisel'

    return False

  def chiselLibraryPath(self):
    # script os.environ['CHISEL_LIBRARY_PATH'] = '/path/to/custom/Chisel'
    path = os.getenv('CHISEL_LIBRARY_PATH')
    if path and os.path.exists(path):
      return path

    source_path = sys.modules[__name__].__file__
    source_dir = os.path.dirname(source_path)
    # ugh: ../.. is to back out of commands/, then back out of libexec/
    return os.path.join(source_dir, '..', '..', 'lib', 'Chisel.framework', 'Chisel')

class FBHeapFromCommand(fb.FBCommand):
  def name(self):
    return 'heapfrom'

  def description(self):
    return 'Show all nested heap pointers contained within a given variable.'

  def run(self, arguments, options):
    # This command is like `expression --synthetic-type false`, except only showing nested heap references.
    var = self.context.frame.var(arguments[0])
    if not var or not var.IsValid():
      self.result.SetError('No variable named "{}"'.format(arguments[0]))
      return

    # Use the actual underlying structure of the variable, not the human friendly (synthetic) one.
    root = var.GetNonSyntheticValue()

    # Traversal of SBValue tree to get leaf nodes, which is where heap pointers will be.
    leafs = []
    queue = [root]
    while queue:
        node = queue.pop(0)
        if node.num_children == 0:
            leafs.append(node)
        else:
            queue += [node.GetChildAtIndex(i) for i in range(node.num_children)]

    pointers = {}
    for node in leafs:
        # Assumption: an addr that has no value means a pointer.
        if node.addr and not node.value:
            pointers[node.load_addr] = node.path

    options = lldb.SBExpressionOptions()
    options.SetLanguage(lldb.eLanguageTypeC)
    def isHeap(addr):
        lookup = '(int)malloc_size({})'.format(addr)
        return self.context.frame.EvaluateExpression(lookup, options).unsigned != 0

    allocations = (addr for addr in pointers if isHeap(addr))
    for addr in allocations:
        print >>self.result, '0x{addr:x} {path}'.format(addr=addr, path=pointers[addr])
    if not allocations:
        print >>self.result, "No heap addresses found"

class FBSequenceCommand(fb.FBCommand):
  def name(self):
    return 'sequence'

  def description(self):
    return 'Run commands in sequence, stopping on any error.'

  def lex(self, commandLine):
    return commandLine.split(';')

  def run(self, arguments, options):
    interpreter = lldb.debugger.GetCommandInterpreter()
    # The full unsplit command is in position 0.
    sequence = arguments[1:]
    for command in sequence:
      command = command.strip()
      if not command:
        continue
      object = lldb.SBCommandReturnObject()
      interpreter.HandleCommand(command, self.context, object)
      if object.GetOutput():
        print >>self.result, object.GetOutput().strip()

      if not object.Succeeded():
        if object.GetError():
          self.result.SetError(object.GetError())
        self.result.SetStatus(object.GetStatus())
        return
<|endoftext|>


<commit_before>"""
Utility functions to for atmospheric data wrangling / preparation.
"""

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits import basemap
import xray

import atmos.xrhelper as xr
from atmos.utils import print_if, strictly_decreasing

# ----------------------------------------------------------------------
def set_lon(data, lon, lonmax=360):
    """Set data longitudes to 0-360E or 180W-180E convention.

    Parameters
    ----------
    data : ndarray
        Input data array with longitude as the last dimension
    lon : 1-D ndarray or list
        Longitudes of input data
    lonmax : int, optional
        Maximum longitude for output data.  Set to 360 for 0-360E,
        or set to 180 for 180W-180E.

    Returns
    -------
    data_out, lon_out : ndarray
        The data and longitude arrays shifted to the selected convention.
    """
    lonmin = lonmax - 360
    if lonmin >= lon.min() and lonmin <= lon.max():
        lon0 = lonmin
        start = True
    else:
        lon0 = lonmax
        start = False

    data_out, lon_out = basemap.shiftgrid(lon0, data, lon, start=start)
    return data_out, lon_out

# ----------------------------------------------------------------------
def lon_convention(lon):
    """Return 360 if longitudes are 0-360E, 180 if 180W-180E.

    The output of this function can be used in the set_lon() function
    to make two data arrays use a consistent longitude convention.
    """
    if lon.min() < 0:
        return 180
    else:
        return 360

# ----------------------------------------------------------------------
def interp_latlon(data, lat_in, lon_in, lat_out, lon_out, checkbounds=False,
                  masked=False, order=1):
    """Interpolate data array onto a new lat-lon grid.

    Parameters
    ----------
    data : 2-D array
        Data to interpolate, with latitude as first dimension,
        longitude second
    lat_in, lon_in : 1-D float array
        Latitude and longitudes of input data
    lat_out, lon_out : 1-D float array
        Latitude and longitudes to interpolate onto
    checkbounds : bool, optional
        If True, values of lat_out and lon_out are checked to see
        that they lie within the range specified by lat_in, lon_in.
        If False, and lat_out, lon_out are outside lat_in, lon_in,
        interpolated values will be clipped to values on boundary
        of input grid lat_in, lon_in
    masked : bool or float, optional
        If True, points outside the range of lat_in, lon_in are masked
        (in a masked array).
        If masked is set to a number, then points outside the range of
        lat_in, lon_in will be set to that number.
    order : int, optional
        0 for nearest-neighbor interpolation,
        1 for bilinear interpolation
        3 for cublic spline (requires scipy.ndimage).

    Returns
    -------
    data_out : 2-D array
        Data interpolated onto lat_out, lon_out grid
    """

    # Check for the common case that lat_in and/or lat_out are decreasing
    # and flip if necessary to work with basemap.interp()
    flip = False
    if strictly_decreasing(lat_in):
        lat_in = lat_in[::-1]
        data = data[::-1, :]
    if strictly_decreasing(lat_out):
        flip = True
        lat_out = lat_out[::-1]

    x_out, y_out = np.meshgrid(lon_out, lat_out)

    data_out = basemap.interp(data, lon_in, lat_in, x_out, y_out,
                              checkbounds=checkbounds, masked=masked,
                              order=order)
    if flip:
        data_out = data_out[::-1, :]

    return data_out

# ----------------------------------------------------------------------
def get_topo(lat, lon, datafile='data/topo/ncep2_ps.nc'):
    """Return surface pressure climatology on selected latlon grid."""

    ds = xr.ncload(datafile)
    lon_ps = ds['lon'].values
    lat_ps = ds['lat'].values
    ps = ds['ps'].values

    # Check what longitude convention is used in the surface pressure
    # climatology and switch if necessary
    if lon_convention(lon_ps) != lon_convention(lon):
        ps, lon_ps = set_lon(ps, lon_ps, lonmax=lon_convention(lon))

    # Interpolate ps onto lat-lon grid
    ps = interp_latlon(ps, lat_ps, lon_ps, lat, lon)

    # Pack data and metadata into a DataArray
    topo = xray.DataArray(ps, coords={'lat': lat, 'lon': lon})
    topo.attrs = ds['ps'].attrs
    topo.attrs['title'] = ds.attrs['title']

    return topo
<commit_msg>Added placeholders for new functions.<commit_after>"""
Utility functions to for atmospheric data wrangling / preparation.
"""

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits import basemap
import xray

import atmos.xrhelper as xr
from atmos.utils import print_if, strictly_decreasing

# ----------------------------------------------------------------------
def set_lon(data, lon, lonmax=360):
    """Set data longitudes to 0-360E or 180W-180E convention.

    Parameters
    ----------
    data : ndarray
        Input data array with longitude as the last dimension
    lon : 1-D ndarray or list
        Longitudes of input data
    lonmax : int, optional
        Maximum longitude for output data.  Set to 360 for 0-360E,
        or set to 180 for 180W-180E.

    Returns
    -------
    data_out, lon_out : ndarray
        The data and longitude arrays shifted to the selected convention.
    """
    lonmin = lonmax - 360
    if lonmin >= lon.min() and lonmin <= lon.max():
        lon0 = lonmin
        start = True
    else:
        lon0 = lonmax
        start = False

    data_out, lon_out = basemap.shiftgrid(lon0, data, lon, start=start)
    return data_out, lon_out

# ----------------------------------------------------------------------
def lon_convention(lon):
    """Return 360 if longitudes are 0-360E, 180 if 180W-180E.

    The output of this function can be used in the set_lon() function
    to make two data arrays use a consistent longitude convention.
    """
    if lon.min() < 0:
        return 180
    else:
        return 360

# ----------------------------------------------------------------------
def interp_latlon(data, lat_in, lon_in, lat_out, lon_out, checkbounds=False,
                  masked=False, order=1):
    """Interpolate data array onto a new lat-lon grid.

    Parameters
    ----------
    data : 2-D array
        Data to interpolate, with latitude as first dimension,
        longitude second
    lat_in, lon_in : 1-D float array
        Latitude and longitudes of input data
    lat_out, lon_out : 1-D float array
        Latitude and longitudes to interpolate onto
    checkbounds : bool, optional
        If True, values of lat_out and lon_out are checked to see
        that they lie within the range specified by lat_in, lon_in.
        If False, and lat_out, lon_out are outside lat_in, lon_in,
        interpolated values will be clipped to values on boundary
        of input grid lat_in, lon_in
    masked : bool or float, optional
        If True, points outside the range of lat_in, lon_in are masked
        (in a masked array).
        If masked is set to a number, then points outside the range of
        lat_in, lon_in will be set to that number.
    order : int, optional
        0 for nearest-neighbor interpolation,
        1 for bilinear interpolation
        3 for cublic spline (requires scipy.ndimage).

    Returns
    -------
    data_out : 2-D array
        Data interpolated onto lat_out, lon_out grid
    """

    # Check for the common case that lat_in and/or lat_out are decreasing
    # and flip if necessary to work with basemap.interp()
    flip = False
    if strictly_decreasing(lat_in):
        lat_in = lat_in[::-1]
        data = data[::-1, :]
    if strictly_decreasing(lat_out):
        flip = True
        lat_out = lat_out[::-1]

    x_out, y_out = np.meshgrid(lon_out, lat_out)

    data_out = basemap.interp(data, lon_in, lat_in, x_out, y_out,
                              checkbounds=checkbounds, masked=masked,
                              order=order)
    if flip:
        data_out = data_out[::-1, :]

    return data_out

# ----------------------------------------------------------------------
def get_topo(lat, lon, datafile='data/topo/ncep2_ps.nc'):
    """Return surface pressure climatology on selected latlon grid."""

    ds = xr.ncload(datafile)
    lon_ps = ds['lon'].values
    lat_ps = ds['lat'].values
    ps = ds['ps'].values

    # Check what longitude convention is used in the surface pressure
    # climatology and switch if necessary
    if lon_convention(lon_ps) != lon_convention(lon):
        ps, lon_ps = set_lon(ps, lon_ps, lonmax=lon_convention(lon))

    # Interpolate ps onto lat-lon grid
    ps = interp_latlon(ps, lat_ps, lon_ps, lat, lon)

    # Pack data and metadata into a DataArray
    topo = xray.DataArray(ps, coords={'lat': lat, 'lon': lon})
    topo.attrs = ds['ps'].attrs
    topo.attrs['title'] = ds.attrs['title']

    return topo

# ----------------------------------------------------------------------
def mask_below_topography():
    """Mask pressure level data below topography."""

# ----------------------------------------------------------------------
# Wrapper function to add topo field to a dataset
<|endoftext|>


<commit_before>from spack import *
import shutil

class Cereal(Package):
    """cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone."""
    homepage = "http://uscilab.github.io/cereal/"
    url      = "https://github.com/USCiLab/cereal/archive/v1.1.2.tar.gz"

    version('1.1.2', '34d4ad174acbff005c36d4d10e48cbb9')
    version('1.1.1', '0ceff308c38f37d5b5f6df3927451c27')
    version('1.1.0', '9f2d5f72e935c54f4c6d23e954ce699f')
    version('1.0.0', 'd1bacca70a95cec0ddbff68b0871296b')
    version('0.9.1', '8872d4444ff274ce6cd1ed364d0fc0ad')

    patch("Werror.patch")

    depends_on("cmake @2.6.2:")

    def install(self, spec, prefix):
        # Don't use -Werror
        filter_file(r'-Werror', '', 'CMakeLists.txt')

        # configure
        # Boost is only used for self-tests, which we are not running (yet?)
        cmake('.', '-DCMAKE_DISABLE_FIND_PACKAGE_Boost=TRUE', *std_cmake_args)

        # Build
        make()

        # Install
        shutil.rmtree(join_path(prefix, 'doc'), ignore_errors=True)
        shutil.rmtree(join_path(prefix, 'include'), ignore_errors=True)
        shutil.copytree('doc', join_path(prefix, 'doc'), symlinks=True)
        shutil.copytree('include', join_path(prefix, 'include'), symlinks=True)
<commit_msg>Create lib directory<commit_after>from spack import *
import os
import shutil

class Cereal(Package):
    """cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone."""
    homepage = "http://uscilab.github.io/cereal/"
    url      = "https://github.com/USCiLab/cereal/archive/v1.1.2.tar.gz"

    version('1.1.2', '34d4ad174acbff005c36d4d10e48cbb9')
    version('1.1.1', '0ceff308c38f37d5b5f6df3927451c27')
    version('1.1.0', '9f2d5f72e935c54f4c6d23e954ce699f')
    version('1.0.0', 'd1bacca70a95cec0ddbff68b0871296b')
    version('0.9.1', '8872d4444ff274ce6cd1ed364d0fc0ad')

    patch("Werror.patch")

    depends_on("cmake @2.6.2:")

    def install(self, spec, prefix):
        # Don't use -Werror
        filter_file(r'-Werror', '', 'CMakeLists.txt')

        # configure
        # Boost is only used for self-tests, which we are not running (yet?)
        cmake('.', '-DCMAKE_DISABLE_FIND_PACKAGE_Boost=TRUE', *std_cmake_args)

        # Build
        make()

        # Install
        shutil.rmtree(join_path(prefix, 'doc'), ignore_errors=True)
        shutil.rmtree(join_path(prefix, 'include'), ignore_errors=True)
        shutil.rmtree(join_path(prefix, 'lib'), ignore_errors=True)
        shutil.copytree('doc', join_path(prefix, 'doc'), symlinks=True)
        shutil.copytree('include', join_path(prefix, 'include'), symlinks=True)
        # Create empty directory to avoid linker warnings later
        os.mkdir(join_path(prefix, 'lib'))
<|endoftext|>