def test_tag_follow_label(self):
        src = '{% load activity_tags %}'\
            '{% follow_label other_user yup nope %}'

        # Anonymous.
        output = Template(src).render(Context({'other_user': self.user1}))
        self.assertEqual(output, 'nope')

        output = Template(src).render(
            Context({
                'user': AnonymousUser(),
                'other_user': self.user1
            }))
        self.assertEqual(output, 'nope')

        # Non follower (user2 does not follow user1).
        output = Template(src).render(
            Context({
                'user': self.user2,
                'other_user': self.user1
            }))
        self.assertEqual(output, 'nope')

        # Follower (user1 follows user2).
        output = Template(src).render(
            Context({
                'user': self.user1,
                'other_user': self.user2
            }))
        self.assertEqual(output, 'yup')
示例#2
0
 def test_is_following_filter(self):
     src = '{% load activity_tags %}{% if user|is_following:group %}yup{% endif %}'
     self.assertEqual(Template(src).render(Context({
         'user': self.user2, 'group': self.group
     })), u'yup')
     self.assertEqual(Template(src).render(Context({
         'user': self.user1, 'group': self.group
     })), u'')
 def _get_text(a_node, is_templated, translate=True):
     if is_templated and a_node.text and "{%" in a_node.text:
         tpl = get_template_from_string(u"{%% load i18n %%}%s" %
                                        a_node.text)
         if translate:
             return lazy(lambda: tpl.render(Context()), text_type)()
         with translation.override("en"):
             return tpl.render(Context())
     return a_node.text
示例#4
0
文件: models.py 项目: tow/feincms
    def render(self, **kwargs):
        context = kwargs.pop('context', None)
        name = 'content/template/%s' % self.filename

        for loader in self.template_loaders:
            try:
                template, display_name = loader.load_template(name)
            except TemplateDoesNotExist:
                continue

            if not hasattr(template, 'render'):
                template = Template(template, name=name)

            if context:
                ctx = context
                ctx.update(dict(content=self, **kwargs))
            else:
                ctx = Context(dict(content=self, **kwargs))

            result = template.render(ctx)

            if context:
                context.pop()

            return result

        return u''  # Fail?
示例#5
0
def unused_as_printable(obj,as_pdf=True,model=None):
    #~ if model is None:
        #~ tn = obj._meta.db_table + "_print.html"
    #~ else:
        #~ tn = model._meta.db_table + "_print.html"
    tplnames = [ obj._meta.db_table, "lino/page" ]
    tpls = [ x + "_printable.html" for x in tplnames ]
    template = select_template(tpls)
    
    context = dict(
      #report=self,
      instance=obj,
      title = unicode(obj),
      #title=u"%s - %s" % (self.get_title(),obj),
      #layout = layout
    )
    html = template.render(Context(context))
    if not as_pdf:
        return html
    html = html.encode("ISO-8859-1")
    #file('tmp.html','w').write(html)
    result = cStringIO.StringIO()
    pdf = pisa.pisaDocument(cStringIO.StringIO(html), result)
    if pdf.err:
        raise Exception("pisa.pisaDocument.err is %r" % pdf.err)
    return result.getvalue()
示例#6
0
    def render_change_entry_html(self, info):
        try:
            autoland_id = int(info['new'][0])
        except (ValueError, TypeError):
            # Something unexpected was recorded as the autoland id in the
            # changedescription. This either means we have a serious bug or
            # someone was attempting to change the field themselves (possibly
            # maliciously).
            logger.error('A malformed autoland_id was detected: %s' %
                         info['new'][0])
            return self._retrieve_error_txt

        try:
            ar = AutolandRequest.objects.get(pk=autoland_id)
        except:
            logger.error('An unknown autoland_id was detected: %s' %
                info['new'][0])
            return self._retrieve_error_txt

        if ar.last_known_status == AutolandEventLogEntry.REQUESTED:
            return self._waiting_txt
        elif ar.last_known_status == AutolandEventLogEntry.PROBLEM:
            return linebreaksbr(self._autoland_problem % ar.last_error_msg)
        elif ar.last_known_status == AutolandEventLogEntry.SERVED:
            url = self._job_url % ar.repository_revision
            template = get_template('mozreview/try_result.html')
            return template.render(Context({'url': url}))
        else:
            return linebreaksbr(self._retrieve_error_txt)
示例#7
0
    def render_change_entry_html(self, values):
        # Fetch the template ourselves only once and render it for each item,
        # instead of calling render_to_string() in the loop, so we don't
        # have to locate and parse/fetch from cache for every item.

        template = get_template(self.thumbnail_template)
        review_request = self.review_request_details.get_review_request()

        if review_request.local_site:
            local_site_name = review_request.local_site.name
        else:
            local_site_name = None

        items = []
        for caption, filename, pk in values:
            if pk in self.file_attachment_id_map:
                attachment = self.file_attachment_id_map[pk]
            else:
                try:
                    attachment = FileAttachment.objects.get(pk=pk)
                except FileAttachment.DoesNotExist:
                    continue

            items.append(
                template.render(
                    Context({
                        'file': attachment,
                        'review_request': review_request,
                        'local_site_name': local_site_name,
                        'uuid': uuid.uuid4(),
                    })))

        return ''.join(items)
示例#8
0
    def as_html(self):
        commit_id = self.commit_data.extra_data.get(COMMIT_ID_KEY)

        if is_parent(self.review_request_details, self.commit_data):
            user = self.request.user
            parent = get_parent_rr(
                self.review_request_details.get_review_request(),
                self.commit_data)
            parent_details = parent.get_draft() or parent
            children = [
                child for child in gen_child_rrs(parent_details, user=user)
                if child.is_accessible_by(user)]

            commit_data = fetch_commit_data(children[-1])
            commit_id = commit_data.extra_data.get(COMMIT_ID_KEY)

        review_request = self.review_request_details.get_review_request()
        repo_path = review_request.repository.path

        if not commit_id:
            logger.error('No commit_id for review request: %d' % (
                review_request.id))
            return ''

        return get_template('mozreview/hg-pull.html').render(Context({
                'commit_id': commit_id,
                'repo_path': repo_path,
        }))
示例#9
0
    def as_html(self):
        user = self.request.user
        file_diff_reviewer_list = []
        reviewer_ids = self.review_request_details.target_people.values_list(
            'id', flat=True
        )

        if (user.is_authenticated() and
                isinstance(self.review_request_details, ReviewRequest)):
            diffsets = self.review_request_details.get_diffsets()
            # Merge all the FileDiffs together
            files = sum([list(diff.files.all()) for diff in diffsets], [])

            for item in files:
                file_diff_reviewer, _ = FileDiffReviewer.objects.get_or_create(
                    reviewer_id=user.id,
                    file_diff_id=item.id
                )
                file_diff_reviewer_list.append({
                    'id': file_diff_reviewer.id,
                    'reviewer_id': file_diff_reviewer.reviewer_id,
                    'file_diff_id': file_diff_reviewer.file_diff_id,
                    'last_modified': file_diff_reviewer.last_modified,
                    'reviewed': file_diff_reviewer.reviewed
                })

        return get_template('mozreview/file_diff_reviewer_data.html').render(
            Context({'file_diff_reviewer_list': file_diff_reviewer_list})
        )
示例#10
0
def render_archivedpage(request, url):
    """
    Render a requested ArchivedPage URL
    """
    try:
        apage = get_object_or_404(ArchivedPage, url__exact="/%s" % url)
    except Http404:
        if not url.endswith('/') and settings.APPEND_SLASH:
            apage = get_object_or_404(ArchivedPage, url__exact="/%s/" % url)
            return HttpResponsePermanentRedirect('%s/' % request.path)
        else:
            raise
    if apage.template_name:
        templates = [apage.template_name, DEFAULT_TEMPLATE]
    else:
        templates = get_templates_from_path(url)
        templates.append(DEFAULT_TEMPLATE)

    # To avoid having to always use the "|safe" filter in flatpage templates,
    # mark the title and content as already safe (since they are raw HTML
    # content in the first place).
    apage.title = mark_safe(apage.title)
    apage.content = mark_safe(Template(apage.content).render(Context({})))

    return render_to_response(templates, {'object': apage},
                              RequestContext(request))
示例#11
0
文件: base.py 项目: MVReddy/TMS
 def save(self, commit=True):
     """ put docstring here """
     # was:
     #output = render_to_string(self.template_name, {'object': self})
     context = Context()
     context.update(
         {
             'object':self,
             'date': self.date,
          }
     )
     output = render_to_string(self.template_name, context_instance = context)
     if commit == True:
         tasks_response = POSTResponseBase(object=self, xml=self.process_response(payload=output)).register()
         self.uid = tasks_response.uid
         self.lastUpdatedUid = tasks_response.lastUpdatedUid
     return self
示例#12
0
 def save(self, commit=True):
     """ put docstring here """
     # was:
     #output = render_to_string(self.template_name, {'object': self})
     context = Context()
     context.update({
         'object': self,
         'date': self.date,
     })
     output = render_to_string(self.template_name, context_instance=context)
     if commit == True:
         tasks_response = POSTResponseBase(
             object=self,
             xml=self.process_response(payload=output)).register()
         self.uid = tasks_response.uid
         self.lastUpdatedUid = tasks_response.lastUpdatedUid
     return self
示例#13
0
 def make_pisa_html(self, MEDIA_URL=settings.MEDIA_URL):
     context = dict(
         instance=self,
         title=unicode(self),
         MEDIA_URL=MEDIA_URL,
     )
     template = select_template(self.html_templates())
     return template.render(Context(context))
示例#14
0
 def render(self, name, value, attrs=None):
     attrs["class"] = 'currencyfield'
     input = super(CurrencyWidget, self).render(name, value, attrs)
     template = get_template("core/widgets/currency.html")
     context = Context({
         "input": input,
     })
     output = template.render(context)
     return mark_safe(output)
示例#15
0
 def get_file_contents(self, path):
     contents = super(DjangoDirectiveProcessor,
                      self).get_file_contents(path)
     if path.endswith(self.DJANGO_TEMPLATE_SUFFIX):
         template = get_template_from_string(contents)
         context = getattr(settings, 'STATICFILESPLUS_JS_CONTEXT', {})
         context.setdefault('settings', settings)
         contents = template.render(Context(context))
     return contents
示例#16
0
    def render_change_entry_html(self, info):
        """Render the change of base commit as a rebase."""
        old_value = info['old'][0]
        new_value = info['new'][0]
        repo_path = self._get_repo_path()

        return get_template('mozreview/changedesc-rebase.html').render(Context({
            'old_base': old_value,
            'new_base': new_value,
            'repo_path': repo_path,
        }))
示例#17
0
 def send_verification_mail(self):
     mail_template = get_template('mails/verification.txt')
     mail = EmailMessage(
         _('Please verify your email address on shortdiary, {0}'.format(
             self.username)),
         mail_template.render(
             Context({
                 'mailuser': self,
                 'hash': self.get_verification_hash()
             })), 'shortdiary <*****@*****.**>',
         ['{0} <{1}>'.format(self.username, self.email)])
     mail.send()
示例#18
0
def invite(request):
    context = {
        'title': 'Invite someone',
        'invites_left': request.user.invites_left,
    }

    if not request.method == 'POST':
        return render_to_response('invite.html',
                                  context_instance=RequestContext(
                                      request, context))

    # Request method is POST
    form = InviteForm(request.POST, request.FILES)

    if not form.is_valid():
        context['form'] = form
        return render_to_response('invite.html',
                                  context_instance=RequestContext(
                                      request, context))

    # Since you shouldn't be able to do this unless you do nasty stuff anyways,
    # no need for a pretty error page
    if request.user.invites_left < 1:
        return HttpResponse('Sorry, you don\'t have any invites left.')

    mail_template = get_template('mails/invite_friend.txt')

    # Generate the invite
    invite = Invite(generated_by=request.user)
    invite.save()

    # Remove from invites_left field
    request.user.invites_left -= 1
    context['invites_left'] = request.user.invites_left
    request.user.save()

    mail_context = Context({
        'user': request.user,
        'invite': invite,
        'message': form.cleaned_data['message']
    })

    mail = EmailMessage(
        _('You\'ve been invited to join shortdiary by {}').format(
            request.user.username),
        mail_template.render(mail_context),
        'shortdiary <*****@*****.**>',
        ['{}'.format(form.cleaned_data['email'])],
    )
    mail.send()
    return render_to_response('invite.html',
                              context_instance=RequestContext(
                                  request, context))
示例#19
0
def feedback(request):
    form = FeedbackForm(request.POST)
    from_email = ""
    mail = request.POST.get("email")
    user_email = [mail]
    admin_email = settings.FEEDBACK_ADMIN_EMAIL
    to_admin = [admin_email]
    if request.method == 'POST':
        form = FeedbackForm(request.POST)
        subject = get_template('feedback/feedback_email.txt').render(Context({
            'name': request.POST.get("name")
            }))
        admin = get_template('feedback/admin_email.txt').render(Context({
            'name': request.POST.get("name"),
            'email': request.POST.get("email"),
            'feedback': request.POST.get("feedback")
            }))
        if form.is_valid():
            form.save()
            form = FeedbackForm()
            try:
                send_mail("Feedback Confirmation",
                          subject,
                          from_email,
                          user_email
                          )
                send_mail("Feedback By User",
                          admin,
                          from_email,
                          to_admin
                          )
                form = FeedbackForm()
                messages.success(request, "Thanks for giving your Feedback")
                return HttpResponseRedirect('/')
            except BadHeaderError:
                return HttpResponse("invalid header error")
    else:
        form = FeedbackForm()
    return render(request, "feedback/button.html", {'form': form})
示例#20
0
    def as_html(self):
        user = self.request.user

        commit_data = fetch_commit_data(self.review_request_details)
        commit_id = commit_data.get_for(self.review_request_details,
                                        COMMIT_ID_KEY)

        review_request = self.review_request_details.get_review_request()
        parent = get_parent_rr(review_request)
        parent_details = parent.get_draft(user) or parent

        author = commit_data.extra_data.get(AUTHOR_KEY, None)

        # If a user can view the parent draft they should also have
        # permission to view every child. We check if the child is
        # accessible anyways in case it has been restricted for other
        # reasons.
        children_details = [
            child for child in gen_child_rrs(parent_details, user=user)
            if child.is_accessible_by(user)
        ]

        # Generate the import and pull input field contents
        import_text = pull_text = ""
        repo_path = review_request.repository.path

        if commit_id:
            import_text = "hg import %s/rev/%s" % (repo_path, commit_id)

        last_child_commit_id = commit_id
        if is_parent(self.review_request_details, commit_data=commit_data):
            last_child_commit_data = fetch_commit_data(children_details[-1])
            last_child_commit_id = (
                last_child_commit_data.extra_data.get(COMMIT_ID_KEY))

        pull_text = "hg pull -r %s %s" % (last_child_commit_id, repo_path)

        # Get just the extended commit message details for display
        commit_message_detail = "\n".join(
            self.review_request_details.description.splitlines()[1:]).strip()

        return get_template('mozreview/commit-main.html').render(
            Context({
                'review_request_details': self.review_request_details,
                'parent_details': parent_details,
                'user': user,
                'author': author,
                'pull_text': pull_text,
                'import_text': import_text,
                'commit_message_detail': commit_message_detail,
            }))
    def render_change_entry_html(self, values):
        # Fetch the template ourselves only once and render it for each item,
        # instead of calling render_to_string() in the loop, so we don't
        # have to locate and parse/fetch from cache for every item.
        template = get_template(self.thumbnail_template)
        review_request = self.review_request_details.get_review_request()

        return ''.join([
            template.render(Context({
                'file': self.file_attachment_id_map[pk],
                'review_request': review_request,
            }))
            for caption, filename, pk in values
        ])
示例#22
0
 def render(self,as_pdf=True):
     template = get_template("lino/grid_print.html")
     context=dict(
       report=self,
       title=self.get_title(),
     )
     html  = template.render(Context(context))
     if not (pisa and as_pdf):
         return HttpResponse(html)
     result = cStringIO.StringIO()
     pdf = pisa.pisaDocument(cStringIO.StringIO(html.encode("ISO-8859-1")), result)
     if pdf.err:
         raise Exception(cgi.escape(html))
     return HttpResponse(result.getvalue(),mimetype='application/pdf')
示例#23
0
    def as_html(self):
        commit_id = self.commit_data.extra_data.get(COMMIT_ID_KEY)
        review_request = self.review_request_details.get_review_request()
        repo_path = review_request.repository.path

        if not commit_id:
            logger.error('No commit_id for review request: %d' % (
                review_request.id))
            return ''

        return get_template('mozreview/hg-import.html').render(Context({
                'commit_id': commit_id,
                'repo_path': repo_path,
        }))
示例#24
0
 def create(self, **kw):
     """ put docstring here """
     object = classobj('Model', (BaseModel, ), {})
     for key in kw.keys():
         setattr(object, key, kw[key])
     (filepath, filename) = os.path.split(self.model.template_name)
     (shortname, extension) = os.path.splitext(filename)
     template_name = os.path.join(filepath,
                                  '%s_initial%s' % (shortname, extension))
     context = Context(object)
     xml_response = render_to_string(template_name,
                                     dictionary=kw,
                                     context_instance=context)
     return self.model(xml=xml_response)
示例#25
0
def send_emails(sender, instance, created, **kwargs):
    if created:
        author = getattr(instance, 'author')
        city = getattr(instance, 'city')
        email_list = []
        users = User.objects.filter(city=city,
                                    email_notification=1).exclude(id=author.id)
        for user in users:
            if user.is_active == True:
                #	if user.online.online() == False:
                email_list.append(user.email)
            #	else:
            #		pass
            else:
                pass

        context = Context()
        context['post'] = instance
        context['author'] = author
        context['city'] = city

        subject = getattr(instance, 'text')

        if '\n' in subject[:70]:
            subject = subject.split("\n")[0]
        else:
            subject = subject[:70]

        if subject == '':
            subject = render_to_string('post_created.txt', context)
            body_html = get_template('post_created_body_empty.html')
            body_txt = render_to_string('post_created_body_empty.txt')
        else:
            body_html = get_template('post_created_body.html')
            body_txt = render_to_string('post_created_body.txt')

        body = body_html.render(context)

        for email in email_list:
            email = EmailMultiAlternatives(
                subject, body_txt,
                'Gulf Fishing Club <*****@*****.**>', [email])
            email.attach_alternative(body, "text/html")
            email.send()

        return

    else:
        pass
示例#26
0
def assert_rendered_equally(settings,
                            template_name,
                            ctx_dict,
                            expected=None,
                            must_succeed=False):
    native_raises, native_result = render_native(settings, template_name,
                                                 Context(ctx_dict))

    compiled_raises, compiled_result = render_compiled(settings, template_name,
                                                       Context(ctx_dict))

    if bool(native_raises) != bool(compiled_raises):
        if native_raises:
            raise native_raises
        if compiled_raises:
            raise compiled_raises

    assert native_result == compiled_result

    if must_succeed:
        assert not native_raises

    if expected is not None:
        assert native_result == expected
示例#27
0
文件: views.py 项目: oerb/immotask
def get_task_pdf(request, task_id):
    """
    Get the Task as PDF
    to get this shit work
    following package Installation is needed in Ubuntu 12.04:
    sudo apt-get install libxml2-dev libxslt1-dev
    pip install lxlm
    pip install tinycss cssselect cairocffi
    go to package xhtml2pdf and fix the lines by this:
    https://stackoverflow.com/questions/22075485/xhtml2pdf-importerror-django
    """
    data = {}
    if type(task_id) == Task:
        task = task_id
    else:
        task = get_object_or_404(Task, pk=task_id)
    data['task'] = task  # get_object_or_404(Task, pk=task_id)
    template = 'tasks/typedprint/' + str(data['task'].ta_tasktype.tt_template)
    # Example: tasks/typedprint/anschreiben.html
    todata = ContactData.objects.filter(
        cd_address_id=data['task'].ta_adrid_to.id)
    printfields = TaskTemplateFields.objects.filter(id=1)
    for element in todata:  # TODO: contacttype by task type layout more Elements
        if element.cd_contacttype_id == printfields[0].ttf_company:
            data['company'] = element.cd_textfield
        elif element.cd_contacttype_id == printfields[0].ttf_name:
            data['name'] = element.cd_textfield
        elif element.cd_contacttype_id == printfields[0].ttf_zipcode:
            data['postalcode'] = element.cd_textfield
        elif element.cd_contacttype_id == printfields[0].ttf_city:
            data['city'] = element.cd_textfield
        else:
            pass
    #resp = render(request, template, data)
    t = get_template(template)
    c = Context(data)
    resp = t.render(c)
    # print resp.content
    # creating the PDF - needs canvas and HttpResponse
    # pip install reportlab
    # https://docs.djangoproject.com/en/dev/howto/outputting-pdf/
    response = HttpResponse(content=resp, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="immotask.pdf"'
    #p = pisa.pisaDocument(src=BytesIO(resp.content.encode('utf-8')), dest=BytesIO(), encoding="utf-8", path=response)
    p = pisa.CreatePDF(resp, response)
    return response
示例#28
0
    def _write_style(self, book):
        """Creates style file.

        Style file will include default styling, theme styling and custom styling
        provided by the user.

        Created style file will be used by booktype2mpdf.php script
        to create final PDF file.

        :Args:
          - book: EPUB Book object
        """

        if 'settings' not in self.config:
            return

        css_style = create_default_style(self.config, self.name,
                                         self.get_extra_style(book))
        theme_style = u''

        if self.theme_name != '':
            theme_style = read_theme_style(self.theme_name, self.name)

            try:
                if self.theme_name == 'custom':
                    custom = self.config['theme'].pop('custom', '{}')
                    custom = json.loads(custom.encode('utf-8'))
                    self.config.update(custom)

                tmpl = Template(theme_style)
                ctx = Context(self.config)
                _style = tmpl.render(ctx)
                theme_style = _style
            except:
                logger.exception("Writing styles failed for `%s` theme." %
                                 self.theme_name)

        custom_style = self.config.get('settings', {}).get('styling', u'')

        f = codecs.open('{}/style.css'.format(self.sandbox_path), 'wt', 'utf8')
        f.write(css_style)
        f.write(theme_style)
        f.write(custom_style)
        f.close()
示例#29
0
    def render(self, name, value, attrs=None):
        attrs["class"] = 'hidden-datefield'

        # Convert date to castom format which was setup in settings.py
        if value:
            try:
                d = dateutil.parser.parse(str(value))
                value = d.strftime(settings.DATE_FORMAT)
            except:
                pass

        field = super(DateHiddentWidget, self).render(name, value, attrs)
        template = get_template("core/widgets/hidden_datepicker.html")
        context = Context({
            "name": name,
            'value': value,
            'field': field,
        })
        output = template.render(context)
        return mark_safe(output)
示例#30
0
    def render_change_entry_html(self, info):
        old_value = json.loads(info.get('old', ['[]'])[0])
        old_commits = [c for c, r in old_value]

        new_value = json.loads(info.get('new', ['[]'])[0])
        new_commits = [c for c, r in new_value]

        # Pad the commit lists so they're equal in length.
        max_len = max(len(old_commits), len(new_commits))
        old_commits += [''] * (max_len - len(old_commits))
        new_commits += [''] * (max_len - len(new_commits))

        commit_changes = zip(old_commits, new_commits)

        review_request = self.review_request_details.get_review_request()

        return get_template('mozreview/commits_changedescription.html').render(
            Context({
                'commit_changes': commit_changes,
                'review_request': review_request,
                'repository_path': review_request.repository.path
            }))
示例#31
0
def process_mails():
    print('Sending mails…')

    mail_template = get_template('mails/post.txt')

    searched_date = datetime.date.today() - datetime.timedelta(years=1)
    print('Searching mails from {}'.format(searched_date))

    posts = Post.objects.filter(date=searched_date, sent=False)
    print('Found {} mail(s) to send'.format(len(posts)))

    for post in posts:
        print('Sending mail for post #{} ({})'.format(post.id, post))

        if not post.author.get_profile().mail_verified:
            print('User hasn\'t verified mail address, skipping')
            continue

        mail = EmailMessage(
            _('Your shortdiary post from {0}').format(post.date),
            mail_template.render(
                Context({
                    'post': post,
                    'MEDIA_URL': settings.MEDIA_URL
                })),
            'shortdiary <*****@*****.**>',
            ['{0} <{1}>'.format(post.author.username, post.author.email)],
            headers={'X-Shortdiary-Post-Date': searched_date})

        if post.image and mimetypes.guess_type(post.image.name)[0]:
            mail.attach(
                os.path.split(post.image.name)[1], post.image.read(),
                mimetypes.guess_type(post.image.name)[0])

        mail.send()

        post.sent = True
        post.save()
示例#32
0
    def _exec_children(self, top, context=None):
        print "--> Executing children of %s..." % (top)
        
        # store the node we're on as the last-expanded node
        # we'll use this to allow repeating the last taken action on a poke
        self.last_expansion = self.tree.getpath(top)
        self.last_expansion_context = context
        
        # first off, clear all pre-existing conditions
        self.conditions = []
        self.instance.timeout_date = None
        self.instance.save()
        
        # construct a default context for this evaluation
        # and add any parent context info to the dict
        if context: self.context.update(context)
        default_context = Context({
            'patient': self.instance.patient,
            'participant': self.instance.patient.asapparticipant,
            'params': self.params
            })
        default_context.update(self.context)

        # also copy the prefix attribute (if it exists) into our machine's registered prefix
        if 'prefix' in top.attrib:
            self.prefix = self.dispatch.request_prefix(self.instance.patient, top.attrib['prefix'])

        # pre-step: determine if there are any elements that require a response
        # that may be siblings to a <message> element. we need to know this
        # so we know whether to tell them to "type prefix before their response"
        siblings = [node.tag for node in top]
        accepts_response = ("response" in siblings or "link" in siblings)

        # execute all top-level elements
        for node in top:
            # depending on the type of the thing, perform some action
            if node.tag == "message":
                # if there's a condition supplied, evaluate it using the template language
                # only proceed if the string evaluates to a non-empty string.
                # if there's no condition, just send it!
                if (not "condition" in node.attrib) or (self.templatize(node.attrib['condition'], default_context).strip()):
                    # strip node text and collapse whitespace
                    text = " ".join(node.text.strip().split())
                    # apply django's template engine to the text and send the resulting message
                    self.send(self.templatize(text, default_context), accepts_response=accepts_response)
            elif node.tag == "response":
                # we first check to see if this can apply to us at all by evaluating the condition attribute
                # it works just like it does for message; if it evaluates to false, this node is skipped entirely
                if (not "condition" in node.attrib) or (self.templatize(node.attrib['condition'], default_context).strip()):
                    if node.get('type',None) == "date_time":
                        # it's a parsedatetime condition rather than a regex one
                        self.conditions.append(ParseDateTimeCondition(self.tree.getpath(node)))
                    else:
                        # it's a regex condition (FIXME: should be a 'regex' type)
                        # add the condition of the response to the action queue
                        print "--> Adding a regex condition in %s" % (top)
                        # angle brackets are mapped to {@ and @} to get around xml's restrictions
                        pattern = node.attrib["pattern"].replace("{@","<").replace("@}",">")
                        self.conditions.append(RegexCondition(self.tree.getpath(node), pattern))
            elif node.tag == "timeout":
                # gather the duration and offset, if specified
                try:
                    duration = node.attrib['delay']
                    offset = node.get('offset', None) # optional; None if not present
                    triggerdate = utilities.parsedt(duration, offset)
                except KeyError as ex:
                    raise XMLFormatException("%s node expects attribute '%s'" % (node.tag, ex.args[0]))

                # FIXME: allows temporary override of the timeout duration for testing
                try:
                    if settings.FORCE_TIMEOUT_DELAY:
                        triggerdate = utilities.parsedt(settings.FORCE_TIMEOUT_DELAY)
                except:
                    # we don't need to do anything; we just assume the setting wasn't set
                    pass
        
                # add the condition of the response to the action queue
                print "--> Adding a timeout condition in %s" % (top)
                self.conditions.append(TimeoutCondition(self.tree.getpath(node), triggerdate))

                # and register us as requiring a timeout
                # only replace the timeout if the new one is more recent than the existing one
                # this is just a nicety to the task writer, since only one timeout
                # will ever trigger...thus, the first one will erase all subsequent ones anyway
                self.instance.timeout_date = triggerdate
                self.instance.save()
            elif node.tag == "schedule":
                # gather the duration and offset, if specified
                try:
                    tasktemplatename = node.attrib['task']
                    date = self.templatize(node.attrib['date'], default_context)
                    offset = node.get('offset', None) # optional; None if not present
                    if offset is not None:
                        offset = self.templatize(offset, default_context)
                        schedule_date = utilities.parsedt(offset, utilities.parsedt(date))
                    else:
                        schedule_date = utilities.parsedt(date)
                except KeyError as ex:
                    raise XMLFormatException("%s node expects attribute '%s'" % (node.tag, ex.args[0]))

                # FIXME: allows temporary override of the timeout duration for testing
                try:
                    if settings.FORCE_SCHEDULE_DELAY:
                        schedule_date = utilities.parsedt(settings.FORCE_SCHEDULE_DELAY)
                except:
                    # we don't need to do anything; we just assume the setting wasn't set
                    pass

                # look up the task template that they specified...
                template = TaskTemplate.objects.get(name=tasktemplatename)
                # grab its default arguments to start out
                new_args = json.loads(template.arguments)
                # and collect any additional arguments (e.g. params) defined in children of this node in <param key="a">value</param> format
                for param in [n for n in node if n.tag == "param"]:
                    # process the values and insert them into the new_args, too
                    new_args[param.attrib['key']] = self.templatize(param.text, default_context)

                # this time we spawn another task rather than continuing execution here
                self.instance.spawn_task(
                    template.task,
                    schedule_date,
                    name=template.name,
                    update_params=new_args
                    )
            elif node.tag == "store":
                # gather the key and value
                try:
                    key = node.attrib['key']
                    value = node.attrib['value']
                except KeyError as ex:
                    raise XMLFormatException("%s node expects attribute '%s'" % (node.tag, ex.args[0]))

                value = self.templatize(value, default_context)

                print "--> Storing '%s' to key '%s'" % (value, key)

                # store these to the persistent params collection and save it
                p = json.loads(self.instance.params)
                p[key] = value
                
                # and don't forget to update the context, too!
                default_context['params'] = p

                # finally, save it all back to the db
                self.instance.params = json.dumps(p)
                self.instance.save()
            elif node.tag == "unstore":
                # gather the key and value
                try:
                    key = node.attrib['key']
                except KeyError as ex:
                    raise XMLFormatException("%s node expects attribute '%s'" % (node.tag, ex.args[0]))

                print "--> Unstoring key '%s'" % (key)

                # store these to the persistent params collection and save it
                try:
                    p = json.loads(self.instance.params)
                    del p[key]
                    # and don't forget to update the context, too!
                    default_context['params'] = p

                    # finally, save it all back to the db
                    self.instance.params = json.dumps(p)
                    self.instance.save()
                except:
                    # not sure what to do here
                    self.dispatch.info("Unable to unstore key '%s' from parameters collection" % (key))
            elif node.tag == "alert":
                # gather the key and value
                try:
                    name = node.attrib['name']
                except KeyError as ex:
                    raise XMLFormatException("%s node expects attribute '%s'" % (node.tag, ex.args[0]))

                # collect any params defined in children of this node in <param key="a">value</param> format
                alert_args = {}
                for param in [n for n in node if n.tag == "param"]:
                    # process the values and insert them into alert_args
                    alert_args[param.attrib['key']] = self.templatize(param.text, default_context)
                
                alert_args['url'] = '/taskmanager/patients/%d/history/#session_%d' % (self.instance.patient.id, self.instance.id)
                # alert_args.update(default_context)
                Alert.objects.add_alert(name, arguments=alert_args, patient=self.instance.patient)
            elif node.tag == "abort":
                # gather the key and value
                try:
                    scope = node.attrib['scope']
                except KeyError as ex:
                    raise XMLFormatException("%s node expects attribute '%s'" % (node.tag, ex.args[0]))

                if scope == "process":
                    # remove all pending tasks belonging to the same process
                    TaskInstance.objects.filter(process=self.instance.process, status="pending").delete()
                    # and immediately conclude execution
                    raise TaskCompleteException()
                elif scope == "others":
                    # end all other tasks that belong to the same process
                    TaskInstance.objects.filter(process=self.instance.process,status="running").exclude(pk=self.instance.id).update(status="completed")
            elif node.tag == "scope":
                # immediately expands when reached
                # if the condition is present and false,the node is ignored.
                if ("condition" not in node.attrib) or (self.templatize(node.attrib['condition'], default_context).strip()):
                    self._exec_children(node, context)
                    return # we have to break here as well so we don't die immediately
            elif node.tag == "link":
                # immediately expand the link with the id specified by target
                # but first we have to find it
                target = self.tree.xpath("//*[@id='" + node.attrib["target"] + "']")

                if len(target) <= 0:
                    raise Exception("Target node for %s couldn't be found!" % ("//*[@id='" + node.attrib["target"] + "']"))

                # take the first element that matches the given id
                # (there should only be one, but we're not validating for that)
                target = target[0]

                # check for some obvious problem conditions
                if target == top or target == node:
                    raise Exception("Aborting, link would lead to infinite recursion")                    

                print "--> Following link from %s to %s" % (top, target)

                # if everything's good, jump immediately to that node
                # we maintain the context to allow us to pass things that we detected in our present node
                self._exec_children(target, context)
                return # we have to break here, too...

        # if there's nothing left on the condition queue then, once again, we're done
        if not self.conditions:
            print "--> Dying in %s on account of having no conditions left" % (top)
            raise TaskCompleteException()