<commit_before># -*- encoding: utf-8 -*-
from django.contrib import messages
from django.core.paginator import (
    EmptyPage,
    PageNotAnInteger,
    Paginator,
)
from django.db import transaction
from django.db.models import get_model
from django.http import HttpResponseRedirect
from django.views.generic import (
    CreateView,
    DeleteView,
    UpdateView,
    TemplateView,
)

from braces.views import (
    LoginRequiredMixin,
    StaffuserRequiredMixin,
)
from formtools.wizard.views import SessionWizardView

from base.view_utils import BaseMixin
from .forms import (
    LinkDocumentForm,
    LinkDocumentForm,
    URLExternalLinkForm,
    URLExistingForm,
    URLInternalPageForm,
    URLTypeForm,
)
from .models import (
    BlockError,
    Page,
    PageSection,
    Section,
    ViewUrl,
)

def _get_block_model(page_section):
    block_model = get_model(
        page_section.section.block_app,
        page_section.section.block_model,
    )
    if not block_model:
        raise BlockError("Block model '{}.{}' does not exist.".format(
            page_section.section.block_app,
            page_section.section.block_model,
        ))
    return block_model

def _paginate_section(qs, page_no, section):
    """Paginate the 'block_list' queryset, using page section properties."""
    if section.paginated:
        # this is the block that requires pagination
        if section.paginated.order_by_field:
            qs = qs.order_by(section.paginated.order_by_field)
        if section.paginated.items_per_page:
            paginator = Paginator(qs, section.paginated.items_per_page)
        try:
            qs = paginator.page(page_no)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            qs = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            qs = paginator.page(paginator.num_pages)
    return qs

class ContentPageMixin(BaseMixin):
    """Page information."""

    def get_context_data(self, **kwargs):
        context = super(ContentPageMixin, self).get_context_data(**kwargs)
        context.update(dict(
            page=self.get_page(),
            menu_list=Page.objects.menu(),
        ))
        return context

    def get_page(self):
        menu = self.kwargs.get('menu', None)
        page = self.kwargs.get('page', None)
        if not page:
            raise BlockError("no 'page' parameter in url")
        try:
            if menu:
                return Page.objects.get(slug=page, slug_menu=menu)
            else:
                return Page.objects.get(slug=page, slug_menu='')
        except Page.DoesNotExist:
            raise BlockError(
                "Page '{}', menu '{}' does not exist".format(page, menu)
            )

    def get_page_section(self):
        page = self.get_page()
        section = self.get_section()
        try:
            return PageSection.objects.get(page=page, section=section)
        except PageSection.DoesNotExist:
            raise BlockError(
                "Page section '{}/{}' does not exist".format(
                    page.slug,
                    section.slug,
                )
            )

    def get_section(self):
        section = self.kwargs.get('section', None)
        if not section:
            raise BlockError("no 'section' parameter in url")
        try:
            return Section.objects.get(slug=section)
        except Section.DoesNotExist:
            raise BlockError("Section '{}' does not exist".format(section))

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ContentCreateView(ContentPageMixin, BaseMixin, CreateView):

    def form_valid(self, form):
        self.object = form.save(commit=False)
        try:
            block = self.block_class(page_section=self.get_page_section())
        except AttributeError:
            raise BlockError(
                "You need to add the 'block_class' attribute "
                "to your '{}' class.".format(self.__class__.__name__)
            )
        block.save()
        self.object.block = block
        self.object.order = self.model.objects.next_order()
        return super(ContentCreateView, self).form_valid(form)

class ContentPublishView(BaseMixin, UpdateView):

    def form_valid(self, form):
        """Publish 'pending' content."""
        self.object = form.save(commit=False)
        self.object.block.publish(self.request.user)
        messages.info(
            self.request,
            "Published block, id {}".format(
                self.object.block.pk,
            )
        )
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ContentRemoveView(BaseMixin, UpdateView):

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.block.remove(self.request.user)
        messages.info(
            self.request,
            "Removed block {}".format(
                self.object.block.pk,
            )
        )
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ContentUpdateView(BaseMixin, UpdateView):

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.set_pending_edit()
        return super(ContentUpdateView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(ContentUpdateView, self).get_context_data(**kwargs)
        context.update(dict(
            is_update=True,
        ))
        return context

    def get_section(self):
        return self.object.block.section

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ElementCreateView(BaseMixin, CreateView):
    """Update the parent (content) object so it knows it has been changed."""

    def form_valid(self, form):
        self.object = form.save(commit=False)
        content = self.object.get_parent()
        content.set_pending_edit()
        content.save()
        return super(ElementCreateView, self).form_valid(form)

class ElementDeleteView(BaseMixin, DeleteView):
    """Update the parent (content) object so it knows it has been changed."""

    def delete(self, request, *args, **kwargs):
        with transaction.atomic():
            result = super(ElementDeleteView, self).delete(
                request, *args, **kwargs
            )
            content = self.object.get_parent()
            content.set_pending_edit()
            content.save()
        return result

class ElementUpdateView(BaseMixin, UpdateView):
    """Update the parent (content) object so it knows it has been changed."""

    def form_valid(self, form):
        self.object = form.save(commit=False)
        content = self.object.get_parent()
        content.set_pending_edit()
        content.save()
        return super(ElementUpdateView, self).form_valid(form)

class PageTemplateMixin(object):

    def get_template_names(self) :
        page = self.get_page()
        if page.template_name:
            template_name = page.template_name
        else:
            raise BlockError(
                "Page '{}' has no 'template_name'".format(page.slug)
            )
        return [template_name,]

class PageDesignMixin(object):

    def get_context_data(self, **kwargs):
        context = super(PageDesignMixin, self).get_context_data(**kwargs)
        page = self.get_page()
        view_url = ViewUrl.objects.view_url(
            self.request.user, page, self.request.GET.get('view')
        )
        context.update(dict(
            design=True,
            is_block_page=True,
            view_url=view_url,
        ))
        for e in PageSection.objects.filter(page=page) :
            block_model = _get_block_model(e)
            qs = _paginate_section(
                block_model.objects.pending(e),
                self.request.GET.get('page'),
                e.section
            )
            context.update({
                '{}_list'.format(e.section.slug): qs,
            })
            create_url = e.section.create_url(page)
            if create_url:
                context.update({
                    '{}_create_url'.format(e.section.slug): create_url,
                })
        return context

class PageDesignView(
        LoginRequiredMixin, StaffuserRequiredMixin,
        PageDesignMixin, PageTemplateMixin, ContentPageMixin, TemplateView):
    pass

class PageMixin(object):

    def _check_url(self, page):
        """Check the page is being accessed using the correct URL."""
        if self.request.path == page.get_absolute_url():
            if page.is_custom:
                raise BlockError(
                    "This is a custom page, so the request path "
                    "should NOT match the absolute url: '{}'".format(
                        self.request.path
                    )
                )
        else:
            if page.is_custom:
                pass
            else:
                raise BlockError(
                    "'request.path' ('{}') does not match the absolute url: "
                    "('{}')".format(self.request.path, page.get_absolute_url())
                )

    def get_context_data(self, **kwargs):
        context = super(PageMixin, self).get_context_data(**kwargs)
        page = self.get_page()
        self._check_url(page)
        context.update(dict(
            design=False,
            is_block_page=True,
        ))
        for e in PageSection.objects.filter(page=page):
            block_model = _get_block_model(e)
            qs = _paginate_section(
                block_model.objects.published(e),
                self.request.GET.get('page'),
                e.section
            )
            context.update({
                '{}_list'.format(e.section.slug): qs,
            })
        return context

class PageFormMixin(PageMixin, PageTemplateMixin, ContentPageMixin):
    pass

class PageView(PageMixin, PageTemplateMixin, ContentPageMixin, TemplateView):
    pass

# -----------------------------------------------------------------------------
# support methods for the 'LinkWizard'
import os

from django.conf import settings
from django.core.files.storage import FileSystemStorage

def select_link_form(wizard, link_type) :
    """Return true if user has selected 'link_type'."""
    data =  wizard.get_cleaned_data_for_step(LinkWizard.FORM_LINK_TYPE)
    selected_link_type = data['link_type'] if data else None
    return selected_link_type == link_type

def url_existing(wizard):
    """Return true if user opts for existing document link"""
    return select_link_form(wizard, 'e')

def url_external_link(wizard):
    """Return true if user opts for external link """
    return select_link_form(wizard, 'l')

def url_internal_page(wizard):
    """Return true if user opts for an internal page """
    return select_link_form(wizard, 'p')

def url_upload(wizard):
    """Return true if user opts for upload a document """
    return select_link_form(wizard, LinkWizard.FORM_DOCUMENT)
# end of - support methods for the 'LinkWizard'

class LinkWizard(LoginRequiredMixin, StaffuserRequiredMixin, SessionWizardView):
    """Link Wizard.

    Documentation for the SessionWizardView in
    http://django-formtools.readthedocs.org/en/latest/

    """

    FORM_DOCUMENT = 'u'
    FORM_EXISTING = 'e'
    FORM_EXTERNAL_URL = 'l'
    FORM_LINK_TYPE = 'link_type'
    FORM_PAGE = 'p'

    condition_dict = {
        FORM_EXTERNAL_URL: url_external_link,
        FORM_PAGE: url_internal_page,
        FORM_DOCUMENT: url_upload,
        FORM_EXISTING: url_existing,
    }

    temp_dir = 'temp'
    #doc_dir = 'document'
    file_storage = FileSystemStorage(
        location=os.path.join(settings.MEDIA_ROOT, 'temp/wizard')
    )
    form_list = [
        (FORM_DOCUMENT, LinkDocumentForm),
        (FORM_EXISTING, URLExistingForm),
        (FORM_EXTERNAL_URL, URLExternalLinkForm),
        (FORM_LINK_TYPE, URLTypeForm),
        (FORM_PAGE, URLInternalPageForm),
    ]

    template_name = 'block/wizard.html'

    def get_form_initial(self, step):
        init_dict = {}
        #get current block to populate forms
        content_obj = self.get_current_content_instance()
        # PJK in the original 'compose' models, this returns the 'url' field.
        url = content_obj.get_url_link
        if (url != None and
            (url.startswith("http://") or url.startswith("https://"))):
            url_type = 'l'
        elif (url != None and url.startswith("/" + 'self.doc_dir' + "/")):
            url_type = 'e'
        else:
            url_type = 'p'
        # PJK in the original 'compose' models, this returns 'url_description'
        title = content_obj.get_url_text
        #set flag for whether title field is displayed
        if (title == None):
            use_title = False
        else:
            use_title = True
        perm_type = 'x'
        init_dict = {
            'url_type': url_type,
            'title': title,
            'url': url,
            'perm_type': perm_type,
            'use_title': use_title
        }
        return init_dict

    def done(self, form_list, form_dict, **kwargs):
        content_obj = self.get_current_content_instance()
        form_link_type = form_dict[self.FORM_LINK_TYPE]
        link_type = form_link_type.cleaned_data['link_type']
        update = False
        if link_type == URLTypeForm.UPLOAD:
            form = form_dict[self.FORM_DOCUMENT]
            content_obj.link_document = form.save()
            update = True
        content_obj.set_pending_edit()
        content_obj.save()
        url = content_obj.block.page_section.page.get_design_url()
        return HttpResponseRedirect(url)

        #data = {}
        #for form in form_list:
        #    for k, v in form.cleaned_data.items():
        #        data[k] = v

        url_info = {'type': '', 'url': '', 'content_type': '', 'title': ''}
        doc_path = os.path.join(settings.MEDIA_URL, self.doc_dir)
        perform_document_save = False

        for form in form_list:
            data = form.cleaned_data

            if ('url_type' in data):
                url_info['type'] = data['url_type']

            if ('title' in data):
                url_info['title'] = data['title']

            if ('level' in data) :
                url_info['level'] = data['level']

            if 'course' in data:
                url_info['course'] = data['course']

            if ('url' in data and data['url'] != None) :
                url_raw = data['url']

                # make sure a file has been chosen
                if (type(url_raw).__name__ == 'UploadedFile'
                    and 'type' in url_info and url_info['type'] == LINK_UPLOAD):

                    url_info['content_type'] = url_raw.content_type
                    # save the uploaded file name as the short file name
                    url_info['short_file_name'] = str(url_raw)

                    perform_document_save = True
                else :
                    url_info['url'] = url_raw

        if perform_document_save:
            url_info = save_document (self, url_raw, url_info)

        # update the block
        return_url = "/"

        content_obj = self.get_current_content_instance()

        import ipdb
        ipdb.set_trace()

        content_obj.set_url(url_info['url'], url_info['title'])
        content_obj.set_pending_edit()
        content_obj.save()
        return_url = content_obj.block.page_section.page.get_design_url()

        return HttpResponseRedirect(return_url)

    def get_current_content_instance(self):
        from django.contrib.contenttypes.models import ContentType
        content_pk = self.kwargs.get('content', None)
        pk = self.kwargs.get('pk', None)
        content_type = ContentType.objects.get(pk=content_pk)
        content_model = content_type.model_class()
        #block = self.kwargs.get('block', None)
        #app = self.kwargs.get('app', 'compose')
        #block_model = get_model(app, block)
        return content_model.objects.get(pk=pk)

# -----------------------------------------------------------------------------
<commit_msg>wip - discussion with MD #961<commit_after># -*- encoding: utf-8 -*-
from django.contrib import messages
from django.core.paginator import (
    EmptyPage,
    PageNotAnInteger,
    Paginator,
)
from django.db import transaction
from django.db.models import get_model
from django.http import HttpResponseRedirect
from django.views.generic import (
    CreateView,
    DeleteView,
    UpdateView,
    TemplateView,
)

from braces.views import (
    LoginRequiredMixin,
    StaffuserRequiredMixin,
)
from formtools.wizard.views import SessionWizardView

from base.view_utils import BaseMixin
from .forms import (
    LinkDocumentForm,
    LinkDocumentForm,
    URLExternalLinkForm,
    URLExistingForm,
    URLInternalPageForm,
    URLTypeForm,
)
from .models import (
    BlockError,
    Page,
    PageSection,
    Section,
    ViewUrl,
)

def _get_block_model(page_section):
    block_model = get_model(
        page_section.section.block_app,
        page_section.section.block_model,
    )
    if not block_model:
        raise BlockError("Block model '{}.{}' does not exist.".format(
            page_section.section.block_app,
            page_section.section.block_model,
        ))
    return block_model

def _paginate_section(qs, page_no, section):
    """Paginate the 'block_list' queryset, using page section properties."""
    if section.paginated:
        # this is the block that requires pagination
        if section.paginated.order_by_field:
            qs = qs.order_by(section.paginated.order_by_field)
        if section.paginated.items_per_page:
            paginator = Paginator(qs, section.paginated.items_per_page)
        try:
            qs = paginator.page(page_no)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            qs = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            qs = paginator.page(paginator.num_pages)
    return qs

class ContentPageMixin(BaseMixin):
    """Page information."""

    def get_context_data(self, **kwargs):
        context = super(ContentPageMixin, self).get_context_data(**kwargs)
        context.update(dict(
            page=self.get_page(),
            menu_list=Page.objects.menu(),
        ))
        return context

    def get_page(self):
        menu = self.kwargs.get('menu', None)
        page = self.kwargs.get('page', None)
        if not page:
            raise BlockError("no 'page' parameter in url")
        try:
            if menu:
                return Page.objects.get(slug=page, slug_menu=menu)
            else:
                return Page.objects.get(slug=page, slug_menu='')
        except Page.DoesNotExist:
            raise BlockError(
                "Page '{}', menu '{}' does not exist".format(page, menu)
            )

    def get_page_section(self):
        page = self.get_page()
        section = self.get_section()
        try:
            return PageSection.objects.get(page=page, section=section)
        except PageSection.DoesNotExist:
            raise BlockError(
                "Page section '{}/{}' does not exist".format(
                    page.slug,
                    section.slug,
                )
            )

    def get_section(self):
        section = self.kwargs.get('section', None)
        if not section:
            raise BlockError("no 'section' parameter in url")
        try:
            return Section.objects.get(slug=section)
        except Section.DoesNotExist:
            raise BlockError("Section '{}' does not exist".format(section))

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ContentCreateView(ContentPageMixin, BaseMixin, CreateView):

    def form_valid(self, form):
        self.object = form.save(commit=False)
        try:
            block = self.block_class(page_section=self.get_page_section())
        except AttributeError:
            raise BlockError(
                "You need to add the 'block_class' attribute "
                "to your '{}' class.".format(self.__class__.__name__)
            )
        block.save()
        self.object.block = block
        self.object.order = self.model.objects.next_order()
        return super(ContentCreateView, self).form_valid(form)

class ContentPublishView(BaseMixin, UpdateView):

    def form_valid(self, form):
        """Publish 'pending' content."""
        self.object = form.save(commit=False)
        self.object.block.publish(self.request.user)
        messages.info(
            self.request,
            "Published block, id {}".format(
                self.object.block.pk,
            )
        )
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ContentRemoveView(BaseMixin, UpdateView):

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.block.remove(self.request.user)
        messages.info(
            self.request,
            "Removed block {}".format(
                self.object.block.pk,
            )
        )
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ContentUpdateView(BaseMixin, UpdateView):

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.set_pending_edit()
        return super(ContentUpdateView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(ContentUpdateView, self).get_context_data(**kwargs)
        context.update(dict(
            is_update=True,
        ))
        return context

    def get_section(self):
        return self.object.block.section

    def get_success_url(self):
        return self.object.block.page_section.page.get_design_url()

class ElementCreateView(BaseMixin, CreateView):
    """Update the parent (content) object so it knows it has been changed."""

    def form_valid(self, form):
        self.object = form.save(commit=False)
        content = self.object.get_parent()
        content.set_pending_edit()
        content.save()
        return super(ElementCreateView, self).form_valid(form)

class ElementDeleteView(BaseMixin, DeleteView):
    """Update the parent (content) object so it knows it has been changed."""

    def delete(self, request, *args, **kwargs):
        with transaction.atomic():
            result = super(ElementDeleteView, self).delete(
                request, *args, **kwargs
            )
            content = self.object.get_parent()
            content.set_pending_edit()
            content.save()
        return result

class ElementUpdateView(BaseMixin, UpdateView):
    """Update the parent (content) object so it knows it has been changed."""

    def form_valid(self, form):
        self.object = form.save(commit=False)
        content = self.object.get_parent()
        content.set_pending_edit()
        content.save()
        return super(ElementUpdateView, self).form_valid(form)

class PageTemplateMixin(object):

    def get_template_names(self) :
        page = self.get_page()
        if page.template_name:
            template_name = page.template_name
        else:
            raise BlockError(
                "Page '{}' has no 'template_name'".format(page.slug)
            )
        return [template_name,]

class PageDesignMixin(object):

    def get_context_data(self, **kwargs):
        context = super(PageDesignMixin, self).get_context_data(**kwargs)
        page = self.get_page()
        view_url = ViewUrl.objects.view_url(
            self.request.user, page, self.request.GET.get('view')
        )
        context.update(dict(
            design=True,
            is_block_page=True,
            view_url=view_url,
        ))
        for e in PageSection.objects.filter(page=page) :
            block_model = _get_block_model(e)
            qs = _paginate_section(
                block_model.objects.pending(e),
                self.request.GET.get('page'),
                e.section
            )
            context.update({
                '{}_list'.format(e.section.slug): qs,
            })
            create_url = e.section.create_url(page)
            if create_url:
                context.update({
                    '{}_create_url'.format(e.section.slug): create_url,
                })
        return context

class PageDesignView(
        LoginRequiredMixin, StaffuserRequiredMixin,
        PageDesignMixin, PageTemplateMixin, ContentPageMixin, TemplateView):
    pass

class PageMixin(object):

    def _check_url(self, page):
        """Check the page is being accessed using the correct URL."""
        if self.request.path == page.get_absolute_url():
            if page.is_custom:
                raise BlockError(
                    "This is a custom page, so the request path "
                    "should NOT match the absolute url: '{}'".format(
                        self.request.path
                    )
                )
        else:
            if page.is_custom:
                pass
            else:
                raise BlockError(
                    "'request.path' ('{}') does not match the absolute url: "
                    "('{}')".format(self.request.path, page.get_absolute_url())
                )

    def get_context_data(self, **kwargs):
        context = super(PageMixin, self).get_context_data(**kwargs)
        page = self.get_page()
        self._check_url(page)
        context.update(dict(
            design=False,
            is_block_page=True,
        ))
        for e in PageSection.objects.filter(page=page):
            block_model = _get_block_model(e)
            qs = _paginate_section(
                block_model.objects.published(e),
                self.request.GET.get('page'),
                e.section
            )
            context.update({
                '{}_list'.format(e.section.slug): qs,
            })
        return context

class PageFormMixin(PageMixin, PageTemplateMixin, ContentPageMixin):
    pass

class PageView(PageMixin, PageTemplateMixin, ContentPageMixin, TemplateView):
    pass

# -----------------------------------------------------------------------------
# 'LinkWizard'
import os

from django.conf import settings
from django.core.files.storage import FileSystemStorage

def select_link_form(wizard, link_type) :
    """Return true if user has selected 'link_type'."""
    data =  wizard.get_cleaned_data_for_step(LinkWizard.FORM_LINK_TYPE)
    selected_link_type = data['link_type'] if data else None
    return selected_link_type == link_type

def url_existing(wizard):
    """Return true if user opts for existing document link"""
    return select_link_form(wizard, LinkWizard.FORM_EXISTING)

def url_external_link(wizard):
    """Return true if user opts for external link """
    return select_link_form(wizard, LinkWizard.FORM_EXTERNAL_URL)

def url_internal_page(wizard):
    """Return true if user opts for an internal page """
    return select_link_form(wizard, LinkWizard.FORM_PAGE)

def url_upload(wizard):
    """Return true if user opts for upload a document """
    return select_link_form(wizard, LinkWizard.FORM_DOCUMENT)

class LinkWizard(LoginRequiredMixin, StaffuserRequiredMixin, SessionWizardView):
    """Link Wizard.

    Documentation for the SessionWizardView in
    http://django-formtools.readthedocs.org/en/latest/

    """

    FORM_DOCUMENT = 'u'
    FORM_EXISTING = 'e'
    FORM_EXTERNAL_URL = 'l'
    FORM_LINK_TYPE = 'link_type'
    FORM_PAGE = 'p'

    condition_dict = {
        FORM_EXTERNAL_URL: url_external_link,
        FORM_PAGE: url_internal_page,
        FORM_DOCUMENT: url_upload,
        FORM_EXISTING: url_existing,
    }

    temp_dir = 'temp'
    #doc_dir = 'document'
    file_storage = FileSystemStorage(
        location=os.path.join(settings.MEDIA_ROOT, 'temp/wizard')
    )
    # this list of forms must stay in this order!
    form_list = [
        (FORM_LINK_TYPE, URLTypeForm),
        (FORM_EXTERNAL_URL, URLExternalLinkForm),
        (FORM_PAGE, URLInternalPageForm),
        (FORM_DOCUMENT, LinkDocumentForm),
        (FORM_EXISTING, URLExistingForm),
    ]

    template_name = 'block/wizard.html'

    def get_form_initial(self, step):
        init_dict = {}
        #get current block to populate forms
        content_obj = self.get_current_content_instance()
        # PJK in the original 'compose' models, this returns the 'url' field.
        url = content_obj.get_url_link
        if (url != None and
            (url.startswith("http://") or url.startswith("https://"))):
            url_type = 'l'
        elif (url != None and url.startswith("/" + 'self.doc_dir' + "/")):
            url_type = 'e'
        else:
            url_type = 'p'
        # PJK in the original 'compose' models, this returns 'url_description'
        title = content_obj.get_url_text
        #set flag for whether title field is displayed
        if (title == None):
            use_title = False
        else:
            use_title = True
        perm_type = 'x'
        init_dict = {
            'url_type': url_type,
            'title': title,
            'url': url,
            'perm_type': perm_type,
            'use_title': use_title
        }
        return init_dict

    def done(self, form_list, form_dict, **kwargs):
        content_obj = self.get_current_content_instance()
        form_link_type = form_dict[self.FORM_LINK_TYPE]
        link_type = form_link_type.cleaned_data['link_type']
        update = False
        if link_type == URLTypeForm.UPLOAD:
            form = form_dict[self.FORM_DOCUMENT]
            content_obj.link = form.save()
            update = True
        content_obj.set_pending_edit()
        content_obj.save()
        url = content_obj.block.page_section.page.get_design_url()
        return HttpResponseRedirect(url)

        #data = {}
        #for form in form_list:
        #    for k, v in form.cleaned_data.items():
        #        data[k] = v

        url_info = {'type': '', 'url': '', 'content_type': '', 'title': ''}
        doc_path = os.path.join(settings.MEDIA_URL, self.doc_dir)
        perform_document_save = False

        for form in form_list:
            data = form.cleaned_data

            if ('url_type' in data):
                url_info['type'] = data['url_type']

            if ('title' in data):
                url_info['title'] = data['title']

            if ('level' in data) :
                url_info['level'] = data['level']

            if 'course' in data:
                url_info['course'] = data['course']

            if ('url' in data and data['url'] != None) :
                url_raw = data['url']

                # make sure a file has been chosen
                if (type(url_raw).__name__ == 'UploadedFile'
                    and 'type' in url_info and url_info['type'] == LINK_UPLOAD):

                    url_info['content_type'] = url_raw.content_type
                    # save the uploaded file name as the short file name
                    url_info['short_file_name'] = str(url_raw)

                    perform_document_save = True
                else :
                    url_info['url'] = url_raw

        if perform_document_save:
            url_info = save_document (self, url_raw, url_info)

        # update the block
        return_url = "/"

        content_obj = self.get_current_content_instance()

        import ipdb
        ipdb.set_trace()

        content_obj.set_url(url_info['url'], url_info['title'])
        content_obj.set_pending_edit()
        content_obj.save()
        return_url = content_obj.block.page_section.page.get_design_url()

        return HttpResponseRedirect(return_url)

    def get_current_content_instance(self):
        from django.contrib.contenttypes.models import ContentType
        content_pk = self.kwargs.get('content', None)
        pk = self.kwargs.get('pk', None)
        content_type = ContentType.objects.get(pk=content_pk)
        content_model = content_type.model_class()
        #block = self.kwargs.get('block', None)
        #app = self.kwargs.get('app', 'compose')
        #block_model = get_model(app, block)
        return content_model.objects.get(pk=pk)

# -----------------------------------------------------------------------------
<|endoftext|>


<commit_before># Copyright (c) 2016 Steven A. Bjornson
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies
# or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## Info
# The goal of this software is to fascilitate the creation
# of complex light patterns using a large array of
# Philips Hue bulbs.
#
# An image is imported with PIL and the pixels are mapped
# to the bulbs.
# The x-axis being time and y-axis being bulb index

import argparse
import glob #list all images
from time import sleep

from PIL import Image
import numpy as np
from phue import Bridge #https://github.com/studioimaginaire/phue

# turns out Hue [0, 65535] and Saturation [0, 254] are available
# as properties of the lights
from hueColour import Converter

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default='Philips-hue.local',
                        help='hue hub ip address')
    parser.add_argument("--input", "--i", type=str, default='/home/pi/imgs',
                        help='Input image directory')
    parser.add_argument("--rate", "--r", type=float, default=1/25.,
                        help='Rate in ms to step between pixel values')
    parser.add_argument("--transition", "--t", type=float, default=0,
                        help='Transition time in seconds')

    args = parser.parse_args()

    b = Bridge(args.ip)
    b.connect()

    lights = b.lights

    for x in lights:
        x.transitiontime = args.transition

    conv = Converter()

    #make subset of lights which are active (a map)

    #make ordered list of images in directory
    imgs = glob.glob("{}/*.png".format(args.input))

    try:
        for i, names in enumerate(imgs):
            img = Image.open(names)
            img = np.asarray(img)

            for x in np.arange(img.shape[1]):
                lights[1].xy = conv.rgbToCIE(img[0, x, 0], img[0, x, 1], img[0, x, 2])
                lights[1].brightness = np.average(img[0,x,:])
                lights[2].xy = conv.rgbToCIE(img[1, x, 0], img[1, x, 1], img[1, x, 2])
                lights[2].brightness = np.average(img[1,x,:])
                sleep(args.rate)

    except KeyboardInterrupt:
        #some sort of cleanup
        0

    # try:
    #     while 1:
    #         #load image

    #         #step through image
    #         """
    #         set_light(self, light_id, parameter, value=None, transitiontime=None):
    #         Adjust properties of one or more lights.
    #         light_id can be a single lamp or an ARRAY of lamps!
    #         parameters: 'on' : True|False , 'bri' : 0-254, 'sat' : 0-254, 'ct': 154-500
    #         """

    #         #back to load image

    # except KeyboardInterrupt:
    #     #some sort of cleanup
    #     0
<commit_msg>added start message to python file to run as script<commit_after>#!/usr/bin/env python

# Copyright (c) 2016 Steven A. Bjornson
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies
# or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

## Info
# The goal of this software is to fascilitate the creation
# of complex light patterns using a large array of
# Philips Hue bulbs.
#
# An image is imported with PIL and the pixels are mapped
# to the bulbs.
# The x-axis being time and y-axis being bulb index

import argparse
import glob #list all images
from time import sleep

from PIL import Image
import numpy as np
from phue import Bridge #https://github.com/studioimaginaire/phue

# turns out Hue [0, 65535] and Saturation [0, 254] are available
# as properties of the lights
from hueColour import Converter

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", type=str, default='Philips-hue.local',
                        help='hue hub ip address')
    parser.add_argument("--input", "--i", type=str, default='/home/pi/imgs',
                        help='Input image directory')
    parser.add_argument("--rate", "--r", type=float, default=1/25.,
                        help='Rate in ms to step between pixel values')
    parser.add_argument("--transition", "--t", type=float, default=0,
                        help='Transition time in seconds')

    args = parser.parse_args()

    b = Bridge(args.ip)
    b.connect()

    lights = b.lights

    for x in lights:
        x.transitiontime = args.transition

    conv = Converter()

    #make subset of lights which are active (a map)

    #make ordered list of images in directory
    imgs = glob.glob("{}/*.png".format(args.input))

    try:
        for i, names in enumerate(imgs):
            img = Image.open(names)
            img = np.asarray(img)

            for x in np.arange(img.shape[1]):
                bri = int(np.average(img[0,x,:]))
                if bri > 0:
                    command =  {'xy': conv.rgbToCIE(img[0, x, 0], img[0, x, 1], img[0, x, 2]), 'bri' : bri}
                else:
                    command = {'On': False}
                b.set_light(2, command)

                bri = int(np.average(img[0,x,:]))
                if bri > 0:
                    command =  {'On':True, 'xy': conv.rgbToCIE(img[1, x, 0], img[1, x, 1], img[1, x, 2]), 'bri' : bri}
                else:
                    command = {'On': False}
                b.set_light(3, command)
                #lights[2].xy = conv.rgbToCIE(img[1, x, 0], img[1, x, 1], img[1, x, 2])
                #lights[2].brightness = int(np.average(img[1,x,:]))
                sleep(args.rate)

    except KeyboardInterrupt:
        #some sort of cleanup
        0

    # try:
    #     while 1:
    #         #load image

    #         #step through image
    #         """
    #         set_light(self, light_id, parameter, value=None, transitiontime=None):
    #         Adjust properties of one or more lights.
    #         light_id can be a single lamp or an ARRAY of lamps!
    #         parameters: 'on' : True|False , 'bri' : 0-254, 'sat' : 0-254, 'ct': 154-500
    #         """

    #         #back to load image

    # except KeyboardInterrupt:
    #     #some sort of cleanup
    #     0
<|endoftext|>


<commit_before>from neuronvisio.controls import Controls
controls = Controls()
from neuron import h
import neuronControl
nrnSim = neuronControl.NeuronSim(mod_path="mod", hoc_path="hoc",
                              spines_dist='all',
                              biochemical_filename="biochemical_circuits/biomd183_noCalcium.eml")

<commit_msg>Commenting the multithread exp.<commit_after>from neuronvisio.controls import Controls
controls = Controls()
from neuron import h
import neuronControl
import time

nrnSim = neuronControl.NeuronSim(mod_path="mod", hoc_path="hoc",
                              spines_dist='all',
                              biochemical_filename="biochemical_circuits/biomd183_noCalcium.eml")

#start= time.time()
#
#controls.manager.add_all_vecRef('v') # Adding vector for the variable v
#
#print "Starting time: %s" % start
#h.load_file('parcom.hoc')
#p = h.ParallelComputeTool()
#p.nthread(4)
#p.multisplit(True)
#
#h.finitialize()
#while h.t < h.tstop:
#    h.fadvance()
#
#end= time.time()
#
#run_time = end-start
#
#print "Ending time: %s. Total time with no parallel: %s" %(end, run_time)
#print "Tstop: %s" %(h.tstop)
#
## file where to save the results
#filename = 'storage.h5'
## Saving the vectors
#controls.manager.save_to_hdf(filename)<|endoftext|>


<commit_before># encoding: utf-8

from __future__ import absolute_import, unicode_literals

import dataproperty
import six
import typepy
from six.moves import zip

from ...error import EmptyHeaderError
from ...style import TextStyler
from .._table_writer import AbstractTableWriter, LineBreakHandling
from ._interface import IndentationInterface, TextWriterInterface

class TextTableWriter(AbstractTableWriter, TextWriterInterface):
    """
    A base class for table writer with text formats.

    .. py:attribute:: column_delimiter

        A column delimiter of a table.

    .. py:attribute:: char_left_side_row

        A character of a left side of a row.

    .. py:attribute:: char_right_side_row

        A character of a right side of a row.

    .. py:attribute:: char_cross_point

        A character of the crossing point of column delimiter and row
        delimiter.

    .. py:attribute:: char_opening_row

        A character of the first line of a table.

    .. py:attribute:: char_header_row_separator

        A character of a separator line of the header and
        the body of the table.

    .. py:attribute:: char_value_row_separator

        A character of a row separator line of the table.

    .. py:attribute:: char_closing_row

        A character of the last line of a table.

    .. py:attribute:: is_write_header_separator_row

        Write a header separator line of the table if the value is |True|.

    .. py:attribute:: is_write_value_separator_row

        Write row separator line(s) of the table if the value is |True|.

    .. py:attribute:: is_write_opening_row

        Write an opening line of the table if the value is |True|.

    .. py:attribute:: is_write_closing_row

        Write a closing line of the table if the value is |True|.

    .. py:attribute:: is_write_null_line_after_table

        Write a blank line of after writing a table if the value is |True|.

    .. figure:: ss/table_char.png
       :scale: 60%
       :alt: table_char

       Character attributes that compose a table
    """

    @property
    def margin(self):
        return self.__margin

    @margin.setter
    def margin(self, value):
        self.__margin = value

        self.__value_cell_margin_format = self.__make_margin_format(" ")
        self.__opening_row_cell_format = self.__make_margin_format(self.char_opening_row)
        self._header_row_separator_cell_format = self.__make_margin_format(
            self.char_header_row_separator
        )
        self.__value_row_separator_cell_format = self.__make_margin_format(
            self.char_value_row_separator
        )
        self.__closing_row_cell_format = self.__make_margin_format(self.char_closing_row)

    def __init__(self):
        super(TextTableWriter, self).__init__()

        self.column_delimiter = "|"
        self.char_left_side_row = ""
        self.char_right_side_row = ""
        self.char_cross_point = ""

        self.char_opening_row = "-"
        self.char_header_row_separator = "-"
        self.char_value_row_separator = "-"
        self.char_closing_row = "-"

        self.margin = 0

        self.line_break_handling = LineBreakHandling.REPLACE
        self.is_write_null_line_after_table = False

    def write_null_line(self):
        """
        Write a null line to the |stream|.
        """

        self._write_line()

    def write_table(self):
        """
        |write_table|.

        .. note::
            - |None| values are written as an empty string.
        """

        super(TextTableWriter, self).write_table()
        if self.is_write_null_line_after_table:
            self.write_null_line()

    def dumps(self):
        """Get rendered tabular text from the table data.

        Only available for text format table writers.

        Returns:
            str: Rendered tabular text.
        """

        old_stream = self.stream
        self.stream = six.StringIO()
        self.write_table()
        tabular_text = self.stream.getvalue()
        self.stream = old_stream

        return tabular_text

    def _create_styler(self, style, writer):
        return TextStyler(style, writer)

    def _write_table_iter(self):
        super(TextTableWriter, self)._write_table_iter()
        if self.is_write_null_line_after_table:
            self.write_null_line()

    def _write_table(self):
        self._preprocess()
        self._write_opening_row()

        try:
            self._write_header()
            self.__write_header_row_separator()
        except EmptyHeaderError:
            pass

        is_first_value_row = True
        for value_list, value_dp_list in zip(self._table_value_matrix, self._table_value_dp_matrix):
            try:
                if is_first_value_row:
                    is_first_value_row = False
                else:
                    if self.is_write_value_separator_row:
                        self._write_value_row_separator()

                self._write_value_row(value_list, value_dp_list)
            except TypeError:
                continue

        self._write_closing_row()

    def _get_opening_row_item_list(self):
        return self.__get_row_separator_item_list(
            self.__opening_row_cell_format, self.char_opening_row
        )

    def _get_header_row_separator_item_list(self):
        return self.__get_row_separator_item_list(
            self._header_row_separator_cell_format, self.char_header_row_separator
        )

    def _get_value_row_separator_item_list(self):
        return self.__get_row_separator_item_list(
            self.__value_row_separator_cell_format, self.char_value_row_separator
        )

    def _get_closing_row_item_list(self):
        return self.__get_row_separator_item_list(
            self.__closing_row_cell_format, self.char_closing_row
        )

    def __get_row_separator_item_list(self, margin_format, separator_char):
        return [
            margin_format.format(separator_char * self._get_padding_len(col_dp))
            for col_dp in self._column_dp_list
        ]

    def _get_header_format_string(self, col_dp, value_dp):
        return "{{:{:s}{:s}}}".format(
            self._get_align_char(dataproperty.Align.CENTER),
            str(self._get_padding_len(col_dp, value_dp)),
        )

    def _to_header_item(self, col_dp, value_dp):
        return self.__value_cell_margin_format.format(
            super(TextTableWriter, self)._to_header_item(col_dp, value_dp)
        )

    def _to_row_item(self, col_dp, value_dp):
        return self.__value_cell_margin_format.format(
            super(TextTableWriter, self)._to_row_item(col_dp, value_dp)
        )

    def _write_raw_string(self, unicode_text):
        self.stream.write(unicode_text)

    def _write_raw_line(self, unicode_text=""):
        self._write_raw_string(unicode_text + "\n")

    def _write(self, text):
        self._write_raw_string(text)

    def _write_line(self, text=""):
        self._write_raw_line(text)

    def _write_row(self, value_list):
        if typepy.is_empty_sequence(value_list):
            return

        self._write_line(
            self.char_left_side_row
            + self.column_delimiter.join(value_list)
            + self.char_right_side_row
        )

    def _write_header(self):
        if not self.is_write_header:
            return

        if typepy.is_empty_sequence(self._table_header_list):
            raise EmptyHeaderError("header is empty")

        self._write_row(self._table_header_list)

    def _write_value_row(self, value_list, value_dp_list):
        self._write_row(value_list)

    def __write_separator_row(self, value_list):
        if typepy.is_empty_sequence(value_list):
            return

        left_cross_point = self.char_cross_point
        right_cross_point = self.char_cross_point
        if typepy.is_null_string(self.char_left_side_row):
            left_cross_point = ""
        if typepy.is_null_string(self.char_right_side_row):
            right_cross_point = ""

        self._write_line(
            left_cross_point + self.char_cross_point.join(value_list) + right_cross_point
        )

    def _write_opening_row(self):
        if not self.is_write_opening_row:
            return

        self.__write_separator_row(self._get_opening_row_item_list())

    def __write_header_row_separator(self):
        if any([not self.is_write_header, not self.is_write_header_separator_row]):
            return

        self.__write_separator_row(self._get_header_row_separator_item_list())

    def _write_value_row_separator(self):
        """
        Write row separator of the table which matched to the table type
        regardless of the value of the
        :py:attr:`.is_write_value_separator_row`.
        """

        self.__write_separator_row(self._get_value_row_separator_item_list())

    def _write_closing_row(self):
        if not self.is_write_closing_row:
            return

        self.__write_separator_row(self._get_closing_row_item_list())

    def __make_margin_format(self, margin_char):
        margin_str = margin_char * self.__margin

        return margin_str + "{:s}" + margin_str

class IndentationTextTableWriter(TextTableWriter, IndentationInterface):
    """
    A base class for table writer with indentation text formats.

    .. py:attribute:: indent_string

        Indentation string for each level.
    """

    def __init__(self):
        super(IndentationTextTableWriter, self).__init__()

        self.set_indent_level(0)
        self.indent_string = ""

    def set_indent_level(self, indent_level):
        """
        Set the current indent level.

        :param int indent_level: New indent level.
        """

        self._indent_level = indent_level

    def inc_indent_level(self):
        """
        Increment the current indent level.
        """

        self._indent_level += 1

    def dec_indent_level(self):
        """
        Decrement the current indent level.
        """

        self._indent_level -= 1

    def _get_indent_string(self):
        return self.indent_string * self._indent_level

    def _write(self, text):
        self._write_raw_string(self._get_indent_string() + text)

    def _write_line(self, text=""):
        if typepy.is_not_null_string(text):
            self._write_raw_line(self._get_indent_string() + text)
        else:
            self._write_raw_line("")
<commit_msg>Add try-finally to restore the stream<commit_after># encoding: utf-8

from __future__ import absolute_import, unicode_literals

import dataproperty
import six
import typepy
from six.moves import zip

from ...error import EmptyHeaderError
from ...style import TextStyler
from .._table_writer import AbstractTableWriter, LineBreakHandling
from ._interface import IndentationInterface, TextWriterInterface

class TextTableWriter(AbstractTableWriter, TextWriterInterface):
    """
    A base class for table writer with text formats.

    .. py:attribute:: column_delimiter

        A column delimiter of a table.

    .. py:attribute:: char_left_side_row

        A character of a left side of a row.

    .. py:attribute:: char_right_side_row

        A character of a right side of a row.

    .. py:attribute:: char_cross_point

        A character of the crossing point of column delimiter and row
        delimiter.

    .. py:attribute:: char_opening_row

        A character of the first line of a table.

    .. py:attribute:: char_header_row_separator

        A character of a separator line of the header and
        the body of the table.

    .. py:attribute:: char_value_row_separator

        A character of a row separator line of the table.

    .. py:attribute:: char_closing_row

        A character of the last line of a table.

    .. py:attribute:: is_write_header_separator_row

        Write a header separator line of the table if the value is |True|.

    .. py:attribute:: is_write_value_separator_row

        Write row separator line(s) of the table if the value is |True|.

    .. py:attribute:: is_write_opening_row

        Write an opening line of the table if the value is |True|.

    .. py:attribute:: is_write_closing_row

        Write a closing line of the table if the value is |True|.

    .. py:attribute:: is_write_null_line_after_table

        Write a blank line of after writing a table if the value is |True|.

    .. figure:: ss/table_char.png
       :scale: 60%
       :alt: table_char

       Character attributes that compose a table
    """

    @property
    def margin(self):
        return self.__margin

    @margin.setter
    def margin(self, value):
        self.__margin = value

        self.__value_cell_margin_format = self.__make_margin_format(" ")
        self.__opening_row_cell_format = self.__make_margin_format(self.char_opening_row)
        self._header_row_separator_cell_format = self.__make_margin_format(
            self.char_header_row_separator
        )
        self.__value_row_separator_cell_format = self.__make_margin_format(
            self.char_value_row_separator
        )
        self.__closing_row_cell_format = self.__make_margin_format(self.char_closing_row)

    def __init__(self):
        super(TextTableWriter, self).__init__()

        self.column_delimiter = "|"
        self.char_left_side_row = ""
        self.char_right_side_row = ""
        self.char_cross_point = ""

        self.char_opening_row = "-"
        self.char_header_row_separator = "-"
        self.char_value_row_separator = "-"
        self.char_closing_row = "-"

        self.margin = 0

        self.line_break_handling = LineBreakHandling.REPLACE
        self.is_write_null_line_after_table = False

    def write_null_line(self):
        """
        Write a null line to the |stream|.
        """

        self._write_line()

    def write_table(self):
        """
        |write_table|.

        .. note::
            - |None| values are written as an empty string.
        """

        super(TextTableWriter, self).write_table()
        if self.is_write_null_line_after_table:
            self.write_null_line()

    def dumps(self):
        """Get rendered tabular text from the table data.

        Only available for text format table writers.

        Returns:
            str: Rendered tabular text.
        """

        old_stream = self.stream

        try:
            self.stream = six.StringIO()
            self.write_table()
            tabular_text = self.stream.getvalue()
        finally:
            self.stream = old_stream

        return tabular_text

    def _create_styler(self, style, writer):
        return TextStyler(style, writer)

    def _write_table_iter(self):
        super(TextTableWriter, self)._write_table_iter()
        if self.is_write_null_line_after_table:
            self.write_null_line()

    def _write_table(self):
        self._preprocess()
        self._write_opening_row()

        try:
            self._write_header()
            self.__write_header_row_separator()
        except EmptyHeaderError:
            pass

        is_first_value_row = True
        for value_list, value_dp_list in zip(self._table_value_matrix, self._table_value_dp_matrix):
            try:
                if is_first_value_row:
                    is_first_value_row = False
                else:
                    if self.is_write_value_separator_row:
                        self._write_value_row_separator()

                self._write_value_row(value_list, value_dp_list)
            except TypeError:
                continue

        self._write_closing_row()

    def _get_opening_row_item_list(self):
        return self.__get_row_separator_item_list(
            self.__opening_row_cell_format, self.char_opening_row
        )

    def _get_header_row_separator_item_list(self):
        return self.__get_row_separator_item_list(
            self._header_row_separator_cell_format, self.char_header_row_separator
        )

    def _get_value_row_separator_item_list(self):
        return self.__get_row_separator_item_list(
            self.__value_row_separator_cell_format, self.char_value_row_separator
        )

    def _get_closing_row_item_list(self):
        return self.__get_row_separator_item_list(
            self.__closing_row_cell_format, self.char_closing_row
        )

    def __get_row_separator_item_list(self, margin_format, separator_char):
        return [
            margin_format.format(separator_char * self._get_padding_len(col_dp))
            for col_dp in self._column_dp_list
        ]

    def _get_header_format_string(self, col_dp, value_dp):
        return "{{:{:s}{:s}}}".format(
            self._get_align_char(dataproperty.Align.CENTER),
            str(self._get_padding_len(col_dp, value_dp)),
        )

    def _to_header_item(self, col_dp, value_dp):
        return self.__value_cell_margin_format.format(
            super(TextTableWriter, self)._to_header_item(col_dp, value_dp)
        )

    def _to_row_item(self, col_dp, value_dp):
        return self.__value_cell_margin_format.format(
            super(TextTableWriter, self)._to_row_item(col_dp, value_dp)
        )

    def _write_raw_string(self, unicode_text):
        self.stream.write(unicode_text)

    def _write_raw_line(self, unicode_text=""):
        self._write_raw_string(unicode_text + "\n")

    def _write(self, text):
        self._write_raw_string(text)

    def _write_line(self, text=""):
        self._write_raw_line(text)

    def _write_row(self, value_list):
        if typepy.is_empty_sequence(value_list):
            return

        self._write_line(
            self.char_left_side_row
            + self.column_delimiter.join(value_list)
            + self.char_right_side_row
        )

    def _write_header(self):
        if not self.is_write_header:
            return

        if typepy.is_empty_sequence(self._table_header_list):
            raise EmptyHeaderError("header is empty")

        self._write_row(self._table_header_list)

    def _write_value_row(self, value_list, value_dp_list):
        self._write_row(value_list)

    def __write_separator_row(self, value_list):
        if typepy.is_empty_sequence(value_list):
            return

        left_cross_point = self.char_cross_point
        right_cross_point = self.char_cross_point
        if typepy.is_null_string(self.char_left_side_row):
            left_cross_point = ""
        if typepy.is_null_string(self.char_right_side_row):
            right_cross_point = ""

        self._write_line(
            left_cross_point + self.char_cross_point.join(value_list) + right_cross_point
        )

    def _write_opening_row(self):
        if not self.is_write_opening_row:
            return

        self.__write_separator_row(self._get_opening_row_item_list())

    def __write_header_row_separator(self):
        if any([not self.is_write_header, not self.is_write_header_separator_row]):
            return

        self.__write_separator_row(self._get_header_row_separator_item_list())

    def _write_value_row_separator(self):
        """
        Write row separator of the table which matched to the table type
        regardless of the value of the
        :py:attr:`.is_write_value_separator_row`.
        """

        self.__write_separator_row(self._get_value_row_separator_item_list())

    def _write_closing_row(self):
        if not self.is_write_closing_row:
            return

        self.__write_separator_row(self._get_closing_row_item_list())

    def __make_margin_format(self, margin_char):
        margin_str = margin_char * self.__margin

        return margin_str + "{:s}" + margin_str

class IndentationTextTableWriter(TextTableWriter, IndentationInterface):
    """
    A base class for table writer with indentation text formats.

    .. py:attribute:: indent_string

        Indentation string for each level.
    """

    def __init__(self):
        super(IndentationTextTableWriter, self).__init__()

        self.set_indent_level(0)
        self.indent_string = ""

    def set_indent_level(self, indent_level):
        """
        Set the current indent level.

        :param int indent_level: New indent level.
        """

        self._indent_level = indent_level

    def inc_indent_level(self):
        """
        Increment the current indent level.
        """

        self._indent_level += 1

    def dec_indent_level(self):
        """
        Decrement the current indent level.
        """

        self._indent_level -= 1

    def _get_indent_string(self):
        return self.indent_string * self._indent_level

    def _write(self, text):
        self._write_raw_string(self._get_indent_string() + text)

    def _write_line(self, text=""):
        if typepy.is_not_null_string(text):
            self._write_raw_line(self._get_indent_string() + text)
        else:
            self._write_raw_line("")
<|endoftext|>


<commit_before># Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import logging
import socket
import sys

from telemetry.core import util
from telemetry.core import exceptions
from telemetry.core.backends import png_bitmap
from telemetry.core.backends.chrome import inspector_console
from telemetry.core.backends.chrome import inspector_memory
from telemetry.core.backends.chrome import inspector_network
from telemetry.core.backends.chrome import inspector_page
from telemetry.core.backends.chrome import inspector_runtime
from telemetry.core.backends.chrome import inspector_timeline
from telemetry.core.backends.chrome import websocket
from telemetry.core.heap import model

class InspectorException(Exception):
  pass

class InspectorBackend(object):
  def __init__(self, browser, browser_backend, debugger_url):
    assert debugger_url
    self._browser = browser
    self._browser_backend = browser_backend
    self._debugger_url = debugger_url
    self._socket = None
    self._domain_handlers = {}
    self._cur_socket_timeout = 0
    self._next_request_id = 0

    self._console = inspector_console.InspectorConsole(self)
    self._memory = inspector_memory.InspectorMemory(self)
    self._page = inspector_page.InspectorPage(self)
    self._runtime = inspector_runtime.InspectorRuntime(self)
    self._timeline = inspector_timeline.InspectorTimeline(self)
    self._network = inspector_network.InspectorNetwork(self)

  def __del__(self):
    self.Disconnect()

  def _Connect(self):
    if self._socket:
      return
    try:
      self._socket = websocket.create_connection(self._debugger_url)
    except (websocket.WebSocketException):
      if self._browser_backend.IsBrowserRunning():
        raise exceptions.TabCrashException(sys.exc_info()[1])
      else:
        raise exceptions.BrowserGoneException()

    self._cur_socket_timeout = 0
    self._next_request_id = 0

  def Disconnect(self):
    for _, handlers in self._domain_handlers.items():
      _, will_close_handler = handlers
      will_close_handler()
    self._domain_handlers = {}

    if self._socket:
      self._socket.close()
      self._socket = None

  # General public methods.

  @property
  def browser(self):
    return self._browser

  @property
  def url(self):
    self.Disconnect()
    return self._browser_backend.tab_list_backend.GetTabUrl(self._debugger_url)

  def Activate(self):
    self._Connect()
    self._browser_backend.tab_list_backend.ActivateTab(self._debugger_url)

  def Close(self):
    self.Disconnect()
    self._browser_backend.tab_list_backend.CloseTab(self._debugger_url)

  # Public methods implemented in JavaScript.

  def WaitForDocumentReadyStateToBeComplete(self, timeout):
    util.WaitFor(
        lambda: self._runtime.Evaluate('document.readyState') == 'complete',
        timeout)

  def WaitForDocumentReadyStateToBeInteractiveOrBetter(
      self, timeout):
    def IsReadyStateInteractiveOrBetter():
      rs = self._runtime.Evaluate('document.readyState')
      return rs == 'complete' or rs == 'interactive'
    util.WaitFor(IsReadyStateInteractiveOrBetter, timeout)

  @property
  def screenshot_supported(self):
    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking === undefined'):
      return False

    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking.beginWindowSnapshotPNG === undefined'):
      return False

    return self._browser_backend.chrome_branch_number >= 1391

  def Screenshot(self, timeout):
    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking === undefined'):
      raise Exception("Browser was not started with --enable-gpu-benchmarking")

    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking.beginWindowSnapshotPNG === undefined'):
      raise Exception("Browser does not support window snapshot API.")

    self._runtime.Evaluate("""
        if(!window.__telemetry) {
          window.__telemetry = {}
        }
        window.__telemetry.snapshotComplete = false;
        window.__telemetry.snapshotData = null;
        window.chrome.gpuBenchmarking.beginWindowSnapshotPNG(
          function(snapshot) {
            window.__telemetry.snapshotData = snapshot;
            window.__telemetry.snapshotComplete = true;
          }
        );
    """)

    def IsSnapshotComplete():
      return self._runtime.Evaluate('window.__telemetry.snapshotComplete')

    util.WaitFor(IsSnapshotComplete, timeout)

    snap = self._runtime.Evaluate("""
      (function() {
        var data = window.__telemetry.snapshotData;
        delete window.__telemetry.snapshotComplete;
        delete window.__telemetry.snapshotData;
        return data;
      })()
    """)
    if snap:
      return png_bitmap.PngBitmap.FromBase64(snap['data'])
    return None

  # Console public methods.

  @property
  def message_output_stream(self):  # pylint: disable=E0202
    return self._console.message_output_stream

  @message_output_stream.setter
  def message_output_stream(self, stream):  # pylint: disable=E0202
    self._console.message_output_stream = stream

  # Memory public methods.

  def GetDOMStats(self, timeout):
    dom_counters = self._memory.GetDOMCounters(timeout)
    return {
      'document_count': dom_counters['documents'],
      'node_count': dom_counters['nodes'],
      'event_listener_count': dom_counters['jsEventListeners']
    }

  # Page public methods.

  def PerformActionAndWaitForNavigate(self, action_function, timeout):
    self._page.PerformActionAndWaitForNavigate(action_function, timeout)

  def Navigate(self, url, script_to_evaluate_on_commit, timeout):
    self._page.Navigate(url, script_to_evaluate_on_commit, timeout)

  def GetCookieByName(self, name, timeout):
    return self._page.GetCookieByName(name, timeout)

  # Runtime public methods.

  def ExecuteJavaScript(self, expr, timeout):
    self._runtime.Execute(expr, timeout)

  def EvaluateJavaScript(self, expr, timeout):
    return self._runtime.Evaluate(expr, timeout)

  # Timeline public methods.

  @property
  def timeline_model(self):
    return self._timeline.timeline_model

  def StartTimelineRecording(self):
    self._timeline.Start()

  def StopTimelineRecording(self):
    self._timeline.Stop()

  # Network public methods.

  def ClearCache(self):
    self._network.ClearCache()

  # Methods used internally by other backends.

  def DispatchNotifications(self, timeout=10):
    self._Connect()
    self._SetTimeout(timeout)

    try:
      data = self._socket.recv()
    except (socket.error, websocket.WebSocketException):
      if self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
          self._debugger_url):
        return
      raise exceptions.TabCrashException(sys.exc_info()[1])

    res = json.loads(data)
    logging.debug('got [%s]', data)
    if 'method' in res:
      self._HandleNotification(res)

  def _HandleNotification(self, res):
    if (res['method'] == 'Inspector.detached' and
        res.get('params', {}).get('reason','') == 'replaced_with_devtools'):
      self._WaitForInspectorToGoAwayAndReconnect()
      return
    if res['method'] == 'Inspector.targetCrashed':
      raise exceptions.TabCrashException()

    mname = res['method']
    dot_pos = mname.find('.')
    domain_name = mname[:dot_pos]
    if domain_name in self._domain_handlers:
      try:
        self._domain_handlers[domain_name][0](res)
      except Exception:
        import traceback
        traceback.print_exc()
    else:
      logging.debug('Unhandled inspector message: %s', res)

  def SendAndIgnoreResponse(self, req):
    self._Connect()
    req['id'] = self._next_request_id
    self._next_request_id += 1
    data = json.dumps(req)
    self._socket.send(data)
    logging.debug('sent [%s]', data)

  def _SetTimeout(self, timeout):
    if self._cur_socket_timeout != timeout:
      self._socket.settimeout(timeout)
      self._cur_socket_timeout = timeout

  def _WaitForInspectorToGoAwayAndReconnect(self):
    sys.stderr.write('The connection to Chrome was lost to the Inspector UI.\n')
    sys.stderr.write('Telemetry is waiting for the inspector to be closed...\n')
    self._socket.close()
    self._socket = None
    def IsBack():
      return self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
        self._debugger_url)
    util.WaitFor(IsBack, 512, 0.5)
    sys.stderr.write('\n')
    sys.stderr.write('Inspector\'s UI closed. Telemetry will now resume.\n')
    self._Connect()

  def SyncRequest(self, req, timeout=10):
    self._Connect()
    # TODO(nduca): Listen to the timeout argument
    # pylint: disable=W0613
    self._SetTimeout(timeout)
    self.SendAndIgnoreResponse(req)

    while True:
      try:
        data = self._socket.recv()
      except (socket.error, websocket.WebSocketException):
        if self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
            self._debugger_url):
          raise util.TimeoutException(
            'Timed out waiting for reply. This is unusual.')
        raise exceptions.TabCrashException(sys.exc_info()[1])

      res = json.loads(data)
      logging.debug('got [%s]', data)
      if 'method' in res:
        self._HandleNotification(res)
        continue

      if 'id' not in res or res['id'] != req['id']:
        logging.debug('Dropped reply: %s', json.dumps(res))
        continue
      return res

  def RegisterDomain(self,
      domain_name, notification_handler, will_close_handler):
    """Registers a given domain for handling notification methods.

    For example, given inspector_backend:
       def OnConsoleNotification(msg):
          if msg['method'] == 'Console.messageAdded':
             print msg['params']['message']
          return
       def OnConsoleClose(self):
          pass
       inspector_backend.RegisterDomain('Console',
                                        OnConsoleNotification, OnConsoleClose)
       """
    assert domain_name not in self._domain_handlers
    self._domain_handlers[domain_name] = (notification_handler,
                                          will_close_handler)

  def UnregisterDomain(self, domain_name):
    """Unregisters a previously registered domain."""
    assert domain_name in self._domain_handlers
    self._domain_handlers.pop(domain_name)

  def CollectGarbage(self):
    self._page.CollectGarbage()

  def TakeJSHeapSnapshot(self, timeout=120):
    # This is a hack to make the nested function be able to modify the
    # variables.
    snapshot_uid = [0]
    snapshot = []

    def OnNotification(res):
      if res['method'] == 'HeapProfiler.addProfileHeader':
        snapshot_uid[0] = res['params']['header']['uid']
      elif res['method'] == 'HeapProfiler.addHeapSnapshotChunk':
        snapshot.append(res['params']['chunk'])

    def OnClose():
      pass

    self.RegisterDomain('HeapProfiler', OnNotification, OnClose)

    self.SyncRequest({'method': 'Page.getResourceTree'}, timeout)
    self.SyncRequest({'method': 'Debugger.enable'}, timeout)
    self.SyncRequest({'method': 'HeapProfiler.clearProfiles'}, timeout)
    self.SyncRequest({'method': 'HeapProfiler.takeHeapSnapshot'}, timeout)
    self.SyncRequest({'method': 'HeapProfiler.getHeapSnapshot',
                      'params': {'uid': snapshot_uid[0]}}, timeout)
    snapshot = ''.join(snapshot)

    self.UnregisterDomain('HeapProfiler')
    return model.Model(snapshot)
<commit_msg>android: Implement screenshots for Content Shell and Chromium Test Shell<commit_after># Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import logging
import socket
import sys

from telemetry.core import util
from telemetry.core import exceptions
from telemetry.core.backends import png_bitmap
from telemetry.core.backends.chrome import inspector_console
from telemetry.core.backends.chrome import inspector_memory
from telemetry.core.backends.chrome import inspector_network
from telemetry.core.backends.chrome import inspector_page
from telemetry.core.backends.chrome import inspector_runtime
from telemetry.core.backends.chrome import inspector_timeline
from telemetry.core.backends.chrome import websocket
from telemetry.core.heap import model

class InspectorException(Exception):
  pass

class InspectorBackend(object):
  def __init__(self, browser, browser_backend, debugger_url):
    assert debugger_url
    self._browser = browser
    self._browser_backend = browser_backend
    self._debugger_url = debugger_url
    self._socket = None
    self._domain_handlers = {}
    self._cur_socket_timeout = 0
    self._next_request_id = 0

    self._console = inspector_console.InspectorConsole(self)
    self._memory = inspector_memory.InspectorMemory(self)
    self._page = inspector_page.InspectorPage(self)
    self._runtime = inspector_runtime.InspectorRuntime(self)
    self._timeline = inspector_timeline.InspectorTimeline(self)
    self._network = inspector_network.InspectorNetwork(self)

  def __del__(self):
    self.Disconnect()

  def _Connect(self):
    if self._socket:
      return
    try:
      self._socket = websocket.create_connection(self._debugger_url)
    except (websocket.WebSocketException):
      if self._browser_backend.IsBrowserRunning():
        raise exceptions.TabCrashException(sys.exc_info()[1])
      else:
        raise exceptions.BrowserGoneException()

    self._cur_socket_timeout = 0
    self._next_request_id = 0

  def Disconnect(self):
    for _, handlers in self._domain_handlers.items():
      _, will_close_handler = handlers
      will_close_handler()
    self._domain_handlers = {}

    if self._socket:
      self._socket.close()
      self._socket = None

  # General public methods.

  @property
  def browser(self):
    return self._browser

  @property
  def url(self):
    self.Disconnect()
    return self._browser_backend.tab_list_backend.GetTabUrl(self._debugger_url)

  def Activate(self):
    self._Connect()
    self._browser_backend.tab_list_backend.ActivateTab(self._debugger_url)

  def Close(self):
    self.Disconnect()
    self._browser_backend.tab_list_backend.CloseTab(self._debugger_url)

  # Public methods implemented in JavaScript.

  def WaitForDocumentReadyStateToBeComplete(self, timeout):
    util.WaitFor(
        lambda: self._runtime.Evaluate('document.readyState') == 'complete',
        timeout)

  def WaitForDocumentReadyStateToBeInteractiveOrBetter(
      self, timeout):
    def IsReadyStateInteractiveOrBetter():
      rs = self._runtime.Evaluate('document.readyState')
      return rs == 'complete' or rs == 'interactive'
    util.WaitFor(IsReadyStateInteractiveOrBetter, timeout)

  @property
  def screenshot_supported(self):
    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking === undefined'):
      return False

    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking.beginWindowSnapshotPNG === undefined'):
      return False

    return (self._browser_backend.chrome_branch_number >= 1391 or
            self._browser_backend.is_content_shell)

  def Screenshot(self, timeout):
    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking === undefined'):
      raise Exception("Browser was not started with --enable-gpu-benchmarking")

    if self._runtime.Evaluate(
        'window.chrome.gpuBenchmarking.beginWindowSnapshotPNG === undefined'):
      raise Exception("Browser does not support window snapshot API.")

    self._runtime.Evaluate("""
        if(!window.__telemetry) {
          window.__telemetry = {}
        }
        window.__telemetry.snapshotComplete = false;
        window.__telemetry.snapshotData = null;
        window.chrome.gpuBenchmarking.beginWindowSnapshotPNG(
          function(snapshot) {
            window.__telemetry.snapshotData = snapshot;
            window.__telemetry.snapshotComplete = true;
          }
        );
    """)

    def IsSnapshotComplete():
      return self._runtime.Evaluate('window.__telemetry.snapshotComplete')

    util.WaitFor(IsSnapshotComplete, timeout)

    snap = self._runtime.Evaluate("""
      (function() {
        var data = window.__telemetry.snapshotData;
        delete window.__telemetry.snapshotComplete;
        delete window.__telemetry.snapshotData;
        return data;
      })()
    """)
    if snap:
      return png_bitmap.PngBitmap.FromBase64(snap['data'])
    return None

  # Console public methods.

  @property
  def message_output_stream(self):  # pylint: disable=E0202
    return self._console.message_output_stream

  @message_output_stream.setter
  def message_output_stream(self, stream):  # pylint: disable=E0202
    self._console.message_output_stream = stream

  # Memory public methods.

  def GetDOMStats(self, timeout):
    dom_counters = self._memory.GetDOMCounters(timeout)
    return {
      'document_count': dom_counters['documents'],
      'node_count': dom_counters['nodes'],
      'event_listener_count': dom_counters['jsEventListeners']
    }

  # Page public methods.

  def PerformActionAndWaitForNavigate(self, action_function, timeout):
    self._page.PerformActionAndWaitForNavigate(action_function, timeout)

  def Navigate(self, url, script_to_evaluate_on_commit, timeout):
    self._page.Navigate(url, script_to_evaluate_on_commit, timeout)

  def GetCookieByName(self, name, timeout):
    return self._page.GetCookieByName(name, timeout)

  # Runtime public methods.

  def ExecuteJavaScript(self, expr, timeout):
    self._runtime.Execute(expr, timeout)

  def EvaluateJavaScript(self, expr, timeout):
    return self._runtime.Evaluate(expr, timeout)

  # Timeline public methods.

  @property
  def timeline_model(self):
    return self._timeline.timeline_model

  def StartTimelineRecording(self):
    self._timeline.Start()

  def StopTimelineRecording(self):
    self._timeline.Stop()

  # Network public methods.

  def ClearCache(self):
    self._network.ClearCache()

  # Methods used internally by other backends.

  def DispatchNotifications(self, timeout=10):
    self._Connect()
    self._SetTimeout(timeout)

    try:
      data = self._socket.recv()
    except (socket.error, websocket.WebSocketException):
      if self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
          self._debugger_url):
        return
      raise exceptions.TabCrashException(sys.exc_info()[1])

    res = json.loads(data)
    logging.debug('got [%s]', data)
    if 'method' in res:
      self._HandleNotification(res)

  def _HandleNotification(self, res):
    if (res['method'] == 'Inspector.detached' and
        res.get('params', {}).get('reason','') == 'replaced_with_devtools'):
      self._WaitForInspectorToGoAwayAndReconnect()
      return
    if res['method'] == 'Inspector.targetCrashed':
      raise exceptions.TabCrashException()

    mname = res['method']
    dot_pos = mname.find('.')
    domain_name = mname[:dot_pos]
    if domain_name in self._domain_handlers:
      try:
        self._domain_handlers[domain_name][0](res)
      except Exception:
        import traceback
        traceback.print_exc()
    else:
      logging.debug('Unhandled inspector message: %s', res)

  def SendAndIgnoreResponse(self, req):
    self._Connect()
    req['id'] = self._next_request_id
    self._next_request_id += 1
    data = json.dumps(req)
    self._socket.send(data)
    logging.debug('sent [%s]', data)

  def _SetTimeout(self, timeout):
    if self._cur_socket_timeout != timeout:
      self._socket.settimeout(timeout)
      self._cur_socket_timeout = timeout

  def _WaitForInspectorToGoAwayAndReconnect(self):
    sys.stderr.write('The connection to Chrome was lost to the Inspector UI.\n')
    sys.stderr.write('Telemetry is waiting for the inspector to be closed...\n')
    self._socket.close()
    self._socket = None
    def IsBack():
      return self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
        self._debugger_url)
    util.WaitFor(IsBack, 512, 0.5)
    sys.stderr.write('\n')
    sys.stderr.write('Inspector\'s UI closed. Telemetry will now resume.\n')
    self._Connect()

  def SyncRequest(self, req, timeout=10):
    self._Connect()
    # TODO(nduca): Listen to the timeout argument
    # pylint: disable=W0613
    self._SetTimeout(timeout)
    self.SendAndIgnoreResponse(req)

    while True:
      try:
        data = self._socket.recv()
      except (socket.error, websocket.WebSocketException):
        if self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
            self._debugger_url):
          raise util.TimeoutException(
            'Timed out waiting for reply. This is unusual.')
        raise exceptions.TabCrashException(sys.exc_info()[1])

      res = json.loads(data)
      logging.debug('got [%s]', data)
      if 'method' in res:
        self._HandleNotification(res)
        continue

      if 'id' not in res or res['id'] != req['id']:
        logging.debug('Dropped reply: %s', json.dumps(res))
        continue
      return res

  def RegisterDomain(self,
      domain_name, notification_handler, will_close_handler):
    """Registers a given domain for handling notification methods.

    For example, given inspector_backend:
       def OnConsoleNotification(msg):
          if msg['method'] == 'Console.messageAdded':
             print msg['params']['message']
          return
       def OnConsoleClose(self):
          pass
       inspector_backend.RegisterDomain('Console',
                                        OnConsoleNotification, OnConsoleClose)
       """
    assert domain_name not in self._domain_handlers
    self._domain_handlers[domain_name] = (notification_handler,
                                          will_close_handler)

  def UnregisterDomain(self, domain_name):
    """Unregisters a previously registered domain."""
    assert domain_name in self._domain_handlers
    self._domain_handlers.pop(domain_name)

  def CollectGarbage(self):
    self._page.CollectGarbage()

  def TakeJSHeapSnapshot(self, timeout=120):
    # This is a hack to make the nested function be able to modify the
    # variables.
    snapshot_uid = [0]
    snapshot = []

    def OnNotification(res):
      if res['method'] == 'HeapProfiler.addProfileHeader':
        snapshot_uid[0] = res['params']['header']['uid']
      elif res['method'] == 'HeapProfiler.addHeapSnapshotChunk':
        snapshot.append(res['params']['chunk'])

    def OnClose():
      pass

    self.RegisterDomain('HeapProfiler', OnNotification, OnClose)

    self.SyncRequest({'method': 'Page.getResourceTree'}, timeout)
    self.SyncRequest({'method': 'Debugger.enable'}, timeout)
    self.SyncRequest({'method': 'HeapProfiler.clearProfiles'}, timeout)
    self.SyncRequest({'method': 'HeapProfiler.takeHeapSnapshot'}, timeout)
    self.SyncRequest({'method': 'HeapProfiler.getHeapSnapshot',
                      'params': {'uid': snapshot_uid[0]}}, timeout)
    snapshot = ''.join(snapshot)

    self.UnregisterDomain('HeapProfiler')
    return model.Model(snapshot)
<|endoftext|>


<commit_before>from collections import defaultdict

# get_args_dict()
#_________________________________________________________________________________________
def get_args_dict(args):
    metadata = defaultdict(list)
    for md in args:
        key, value = md.split(':')
        metadata[key].append(value)
    # Flatten single item lists.
    for key, value in metadata.items():
        if len(value) <= 1:
            metadata[key] = value[0]
    return metadata
<commit_msg>Allow for ":" in argument values (only split args on first occurence of ":".<commit_after>from collections import defaultdict

# get_args_dict()
#_________________________________________________________________________________________
def get_args_dict(args):
    metadata = defaultdict(list)
    for md in args:
        key, value = md.split(':', 1)
        metadata[key].append(value)
    # Flatten single item lists.
    for key, value in metadata.items():
        if len(value) <= 1:
            metadata[key] = value[0]
    return metadata
<|endoftext|>


<commit_before>import inspect
import os
import six
import subprocess
import time
from .utils import serverContext

def _webClientResource():
    from girder.api import access
    from girder.api.describe import describeRoute, Description
    from girder.api.rest import Resource
    from girder.constants import ROOT_DIR, registerAccessFlag
    from girder.exceptions import RestException
    from girder.models.folder import Folder
    from girder.models.upload import Upload
    from girder.plugin import getPlugin
    from girder.utility.progress import ProgressContext

    class _WebClientTestEndpoints(Resource):
        def __init__(self):
            super(_WebClientTestEndpoints, self).__init__()
            self.route('GET', ('progress',), self.testProgress)
            self.route('PUT', ('progress', 'stop'), self.testProgressStop)
            self.route('POST', ('file',), self.uploadFile)
            self.route('POST', ('access_flag',), self.registerAccessFlags)
            self.stop = False

        @access.token
        @describeRoute(
            Description('Test progress contexts from the web')
            .param('test', 'Name of test to run.  These include "success" and "failure".',
                   required=False)
            .param('duration', 'Duration of the test in seconds', required=False, dataType='int')
            .param('resourceId', 'Resource ID associated with the progress notification.',
                   required=False)
            .param('resourceName', 'Type of resource associated with the progress notification.',
                   required=False)
        )
        def testProgress(self, params):
            test = params.get('test', 'success')
            duration = int(params.get('duration', 10))
            resourceId = params.get('resourceId', None)
            resourceName = params.get('resourceName', None)
            startTime = time.time()
            with ProgressContext(True, user=self.getCurrentUser(),
                                 title='Progress Test', message='Progress Message',
                                 total=duration, resource={'_id': resourceId},
                                 resourceName=resourceName) as ctx:
                for current in range(duration):
                    if self.stop:
                        break
                    ctx.update(current=current)
                    wait = startTime + current + 1 - time.time()
                    if wait > 0:
                        time.sleep(wait)
                if test == 'error':
                    raise RestException('Progress error test.')

        @access.token
        @describeRoute(
            Description('Halt all progress tests')
        )
        def testProgressStop(self, params):
            self.stop = True

        @access.user
        @describeRoute(None)
        def uploadFile(self, params):
            """
            Providing this works around a limitation in phantom that makes us
            unable to upload binary files, or at least ones that contain certain
            byte values. The path parameter should be provided relative to the
            root directory of the repository.
            """
            self.requireParams(('folderId', 'path'), params)

            if params['path'].startswith('${'):  # relative to plugin e.g. ${my_plugin}/path
                end = params['path'].find('}')
                plugin = params['path'][2:end]
                plugin = getPlugin(plugin)
                if plugin is None:
                    raise Exception('Invalid plugin %s.' % plugin)
                root = os.path.dirname(inspect.getfile(plugin.__class__))
                path = root + params['path'][end + 1:]
            else:  # assume relative to core package
                path = os.path.join(ROOT_DIR, params['path'])
            name = os.path.basename(path)
            folder = Folder().load(params['folderId'], force=True)

            upload = Upload().createUpload(
                user=self.getCurrentUser(), name=name, parentType='folder',
                parent=folder, size=os.path.getsize(path))

            with open(path, 'rb') as fd:
                file = Upload().handleChunk(upload, fd)

            return file

        @access.public
        @describeRoute(None)
        def registerAccessFlags(self, params):
            """
            Helper that can be used to register access flags in the system. This is
            used to test the access flags UI since the core does not expose any flags.
            """
            flags = self.getBodyJson()
            for key, info in six.viewitems(flags):
                registerAccessFlag(key, info['name'], info['description'], info['admin'])

    return _WebClientTestEndpoints()

def runWebClientTest(spec, plugins=()):
    from girder.constants import ROOT_DIR

    with serverContext(plugins=plugins, bindPort=True) as server:
        server.root.api.v1.webclienttest = _webClientResource()

        cmd = (
            'npx', 'phantomjs',
            os.path.join(ROOT_DIR, 'girder', 'web_client', 'test', 'specRunner.js'),
            'http://localhost:%s/static/built/testEnv.html' % server.boundPort,
            spec)

        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        jasmineFinished = False
        for line in iter(p.stdout.readline, b''):
            print(line.rstrip())
            if b'PHANTOM_TIMEOUT' in line or b'error loading source script' in line:
                p.kill()
                raise Exception('Phantomjs failure')
            if b'Testing Finished' in line:
                jasmineFinished = True
        assert p.wait() == 0
        assert jasmineFinished
<commit_msg>Make the runWebClientTest method take a boundServer parameter.<commit_after>import inspect
import os
import six
import subprocess
import time

def _webClientResource():
    from girder.api import access
    from girder.api.describe import describeRoute, Description
    from girder.api.rest import Resource
    from girder.constants import ROOT_DIR, registerAccessFlag
    from girder.exceptions import RestException
    from girder.models.folder import Folder
    from girder.models.upload import Upload
    from girder.plugin import getPlugin
    from girder.utility.progress import ProgressContext

    class _WebClientTestEndpoints(Resource):
        def __init__(self):
            super(_WebClientTestEndpoints, self).__init__()
            self.route('GET', ('progress',), self.testProgress)
            self.route('PUT', ('progress', 'stop'), self.testProgressStop)
            self.route('POST', ('file',), self.uploadFile)
            self.route('POST', ('access_flag',), self.registerAccessFlags)
            self.stop = False

        @access.token
        @describeRoute(
            Description('Test progress contexts from the web')
            .param('test', 'Name of test to run.  These include "success" and "failure".',
                   required=False)
            .param('duration', 'Duration of the test in seconds', required=False, dataType='int')
            .param('resourceId', 'Resource ID associated with the progress notification.',
                   required=False)
            .param('resourceName', 'Type of resource associated with the progress notification.',
                   required=False)
        )
        def testProgress(self, params):
            test = params.get('test', 'success')
            duration = int(params.get('duration', 10))
            resourceId = params.get('resourceId', None)
            resourceName = params.get('resourceName', None)
            startTime = time.time()
            with ProgressContext(True, user=self.getCurrentUser(),
                                 title='Progress Test', message='Progress Message',
                                 total=duration, resource={'_id': resourceId},
                                 resourceName=resourceName) as ctx:
                for current in range(duration):
                    if self.stop:
                        break
                    ctx.update(current=current)
                    wait = startTime + current + 1 - time.time()
                    if wait > 0:
                        time.sleep(wait)
                if test == 'error':
                    raise RestException('Progress error test.')

        @access.token
        @describeRoute(
            Description('Halt all progress tests')
        )
        def testProgressStop(self, params):
            self.stop = True

        @access.user
        @describeRoute(None)
        def uploadFile(self, params):
            """
            Providing this works around a limitation in phantom that makes us
            unable to upload binary files, or at least ones that contain certain
            byte values. The path parameter should be provided relative to the
            root directory of the repository.
            """
            self.requireParams(('folderId', 'path'), params)

            if params['path'].startswith('${'):  # relative to plugin e.g. ${my_plugin}/path
                end = params['path'].find('}')
                plugin = params['path'][2:end]
                plugin = getPlugin(plugin)
                if plugin is None:
                    raise Exception('Invalid plugin %s.' % plugin)
                root = os.path.dirname(inspect.getfile(plugin.__class__))
                path = root + params['path'][end + 1:]
            else:  # assume relative to core package
                path = os.path.join(ROOT_DIR, params['path'])
            name = os.path.basename(path)
            folder = Folder().load(params['folderId'], force=True)

            upload = Upload().createUpload(
                user=self.getCurrentUser(), name=name, parentType='folder',
                parent=folder, size=os.path.getsize(path))

            with open(path, 'rb') as fd:
                file = Upload().handleChunk(upload, fd)

            return file

        @access.public
        @describeRoute(None)
        def registerAccessFlags(self, params):
            """
            Helper that can be used to register access flags in the system. This is
            used to test the access flags UI since the core does not expose any flags.
            """
            flags = self.getBodyJson()
            for key, info in six.viewitems(flags):
                registerAccessFlag(key, info['name'], info['description'], info['admin'])

    return _WebClientTestEndpoints()

def runWebClientTest(boundServer, spec):
    """
    Run a web client spec using the phantomjs specRunner.

    :param boundServer: a boundServer fixture.
    :param spec: path to the javascript spec file.
    """
    from girder.constants import ROOT_DIR

    boundServer.root.api.v1.webclienttest = _webClientResource()

    cmd = (
        'npx', 'phantomjs',
        os.path.join(ROOT_DIR, 'girder', 'web_client', 'test', 'specRunner.js'),
        'http://localhost:%s/static/built/testEnv.html' % boundServer.boundPort,
        spec)

    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    jasmineFinished = False
    for line in iter(p.stdout.readline, b''):
        print(line.rstrip())
        if b'PHANTOM_TIMEOUT' in line or b'error loading source script' in line:
            p.kill()
            raise Exception('Phantomjs failure')
        if b'Testing Finished' in line:
            jasmineFinished = True
    assert p.wait() == 0
    assert jasmineFinished
<|endoftext|>