<commit_before>"""
FilterSpec encapsulates the logic for displaying filters in the Django admin.
Filters are specified in models with the "list_filter" option.

Each filter subclass knows how to display a filter for a field that passes a
certain test -- e.g. being a DateField or ForeignKey.
"""

from django.db import models
import datetime

class FilterSpec(object):
    filter_specs = []
    def __init__(self, f, request, params, model):
        self.field = f
        self.params = params

    def register(cls, test, factory):
        cls.filter_specs.append((test, factory))
    register = classmethod(register)

    def create(cls, f, request, params, model):
        for test, factory in cls.filter_specs:
            if test(f):
                return factory(f, request, params, model)
    create = classmethod(create)

    def has_output(self):
        return True

    def choices(self, cl):
        raise NotImplementedError()

    def title(self):
        return self.field.verbose_name

    def output(self, cl):
        t = []
        if self.has_output():
            t.append(_('
By %s:
\n
\n') % self.title())

            for choice in self.choices(cl):
                t.append('
%s
\n' % \
                    ((choice['selected'] and ' class="selected"' or ''),
                     choice['query_string'] ,
                     choice['display']))
            t.append('
\n\n')
        return "".join(t)

class RelatedFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(RelatedFilterSpec, self).__init__(f, request, params, model)
        if isinstance(f, models.ManyToManyField):
            self.lookup_title = f.rel.to._meta.verbose_name
        else:
            self.lookup_title = f.verbose_name
        self.lookup_kwarg = '%s__%s__exact' % (f.name, f.rel.to._meta.pk.name)
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
        self.lookup_choices = f.rel.to._default_manager.all()

    def has_output(self):
        return len(self.lookup_choices) > 1

    def title(self):
        return self.lookup_title

    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
               'display': _('All')}
        for val in self.lookup_choices:
            pk_val = getattr(val, self.field.rel.to._meta.pk.attname)
            yield {'selected': self.lookup_val == str(pk_val),
                   'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
                   'display': val}

FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)

class ChoicesFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(ChoicesFilterSpec, self).__init__(f, request, params, model)
        self.lookup_kwarg = '%s__exact' % f.name
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)

    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
               'display': _('All')}
        for k, v in self.field.choices:
            yield {'selected': str(k) == self.lookup_val,
                    'query_string': cl.get_query_string({self.lookup_kwarg: k}),
                    'display': v}

FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)

class DateFieldFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(DateFieldFilterSpec, self).__init__(f, request, params, model)

        self.field_generic = '%s__' % self.field.name

        self.date_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)])

        today = datetime.date.today()
        one_week_ago = today - datetime.timedelta(days=7)
        today_str = isinstance(self.field, models.DateTimeField) and today.strftime('%Y-%m-%d 23:59:59') or today.strftime('%Y-%m-%d')

        self.links = (
            (_('Any date'), {}),
            (_('Today'), {'%s__year' % self.field.name: str(today.year),
                       '%s__month' % self.field.name: str(today.month),
                       '%s__day' % self.field.name: str(today.day)}),
            (_('Past 7 days'), {'%s__gte' % self.field.name: one_week_ago.strftime('%Y-%m-%d'),
                             '%s__lte' % f.name: today_str}),
            (_('This month'), {'%s__year' % self.field.name: str(today.year),
                             '%s__month' % f.name: str(today.month)}),
            (_('This year'), {'%s__year' % self.field.name: str(today.year)})
        )

    def title(self):
        return self.field.verbose_name

    def choices(self, cl):
        for title, param_dict in self.links:
            yield {'selected': self.date_params == param_dict,
                   'query_string': cl.get_query_string(param_dict, self.field_generic),
                   'display': title}

FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)

class BooleanFieldFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(BooleanFieldFilterSpec, self).__init__(f, request, params, model)
        self.lookup_kwarg = '%s__exact' % f.name
        self.lookup_kwarg2 = '%s__isnull' % f.name
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
        self.lookup_val2 = request.GET.get(self.lookup_kwarg2, None)

    def title(self):
        return self.field.verbose_name

    def choices(self, cl):
        for k, v in ((_('All'), None), (_('Yes'), '1'), (_('No'), '0')):
            yield {'selected': self.lookup_val == v and not self.lookup_val2,
                   'query_string': cl.get_query_string({self.lookup_kwarg: v}, [self.lookup_kwarg2]),
                   'display': k}
        if isinstance(self.field, models.NullBooleanField):
            yield {'selected': self.lookup_val2 == 'True',
                   'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]),
                   'display': _('Unknown')}

FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)

# This should be registered last, because it's a last resort. For example,
# if a field is eligible to use the BooleanFieldFilterSpec, that'd be much
# more appropriate, and the AllValuesFilterSpec won't get used for it.
class AllValuesFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(AllValuesFilterSpec, self).__init__(f, request, params, model)
        self.lookup_val = request.GET.get(f.name, None)
        self.lookup_choices = model._meta.admin.manager.distinct().order_by(f.name).values(f.name)

    def title(self):
        return self.field.verbose_name

    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.field.name]),
               'display': _('All')}
        for val in self.lookup_choices:
            val = str(val[self.field.name])
            yield {'selected': self.lookup_val == val,
                   'query_string': cl.get_query_string({self.field.name: val}),
                   'display': val}
FilterSpec.register(lambda f: True, AllValuesFilterSpec)
<commit_msg>Fixed #2342 -- Made small fix to DateFieldFilterSpec. Thanks, Alex Dedul<commit_after>"""
FilterSpec encapsulates the logic for displaying filters in the Django admin.
Filters are specified in models with the "list_filter" option.

Each filter subclass knows how to display a filter for a field that passes a
certain test -- e.g. being a DateField or ForeignKey.
"""

from django.db import models
import datetime

class FilterSpec(object):
    filter_specs = []
    def __init__(self, f, request, params, model):
        self.field = f
        self.params = params

    def register(cls, test, factory):
        cls.filter_specs.append((test, factory))
    register = classmethod(register)

    def create(cls, f, request, params, model):
        for test, factory in cls.filter_specs:
            if test(f):
                return factory(f, request, params, model)
    create = classmethod(create)

    def has_output(self):
        return True

    def choices(self, cl):
        raise NotImplementedError()

    def title(self):
        return self.field.verbose_name

    def output(self, cl):
        t = []
        if self.has_output():
            t.append(_('
By %s:
\n
\n') % self.title())

            for choice in self.choices(cl):
                t.append('
%s
\n' % \
                    ((choice['selected'] and ' class="selected"' or ''),
                     choice['query_string'] ,
                     choice['display']))
            t.append('
\n\n')
        return "".join(t)

class RelatedFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(RelatedFilterSpec, self).__init__(f, request, params, model)
        if isinstance(f, models.ManyToManyField):
            self.lookup_title = f.rel.to._meta.verbose_name
        else:
            self.lookup_title = f.verbose_name
        self.lookup_kwarg = '%s__%s__exact' % (f.name, f.rel.to._meta.pk.name)
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
        self.lookup_choices = f.rel.to._default_manager.all()

    def has_output(self):
        return len(self.lookup_choices) > 1

    def title(self):
        return self.lookup_title

    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
               'display': _('All')}
        for val in self.lookup_choices:
            pk_val = getattr(val, self.field.rel.to._meta.pk.attname)
            yield {'selected': self.lookup_val == str(pk_val),
                   'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
                   'display': val}

FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)

class ChoicesFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(ChoicesFilterSpec, self).__init__(f, request, params, model)
        self.lookup_kwarg = '%s__exact' % f.name
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)

    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
               'display': _('All')}
        for k, v in self.field.choices:
            yield {'selected': str(k) == self.lookup_val,
                    'query_string': cl.get_query_string({self.lookup_kwarg: k}),
                    'display': v}

FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)

class DateFieldFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(DateFieldFilterSpec, self).__init__(f, request, params, model)

        self.field_generic = '%s__' % self.field.name

        self.date_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)])

        today = datetime.date.today()
        one_week_ago = today - datetime.timedelta(days=7)
        today_str = isinstance(self.field, models.DateTimeField) and today.strftime('%Y-%m-%d 23:59:59') or today.strftime('%Y-%m-%d')

        self.links = (
            (_('Any date'), {}),
            (_('Today'), {'%s__year' % self.field.name: str(today.year),
                       '%s__month' % self.field.name: str(today.month),
                       '%s__day' % self.field.name: str(today.day)}),
            (_('Past 7 days'), {'%s__gte' % self.field.name: one_week_ago.strftime('%Y-%m-%d'),
                             '%s__lte' % f.name: today_str}),
            (_('This month'), {'%s__year' % self.field.name: str(today.year),
                             '%s__month' % f.name: str(today.month)}),
            (_('This year'), {'%s__year' % self.field.name: str(today.year)})
        )

    def title(self):
        return self.field.verbose_name

    def choices(self, cl):
        for title, param_dict in self.links:
            yield {'selected': self.date_params == param_dict,
                   'query_string': cl.get_query_string(param_dict, [self.field_generic]),
                   'display': title}

FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)

class BooleanFieldFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(BooleanFieldFilterSpec, self).__init__(f, request, params, model)
        self.lookup_kwarg = '%s__exact' % f.name
        self.lookup_kwarg2 = '%s__isnull' % f.name
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
        self.lookup_val2 = request.GET.get(self.lookup_kwarg2, None)

    def title(self):
        return self.field.verbose_name

    def choices(self, cl):
        for k, v in ((_('All'), None), (_('Yes'), '1'), (_('No'), '0')):
            yield {'selected': self.lookup_val == v and not self.lookup_val2,
                   'query_string': cl.get_query_string({self.lookup_kwarg: v}, [self.lookup_kwarg2]),
                   'display': k}
        if isinstance(self.field, models.NullBooleanField):
            yield {'selected': self.lookup_val2 == 'True',
                   'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]),
                   'display': _('Unknown')}

FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)

# This should be registered last, because it's a last resort. For example,
# if a field is eligible to use the BooleanFieldFilterSpec, that'd be much
# more appropriate, and the AllValuesFilterSpec won't get used for it.
class AllValuesFilterSpec(FilterSpec):
    def __init__(self, f, request, params, model):
        super(AllValuesFilterSpec, self).__init__(f, request, params, model)
        self.lookup_val = request.GET.get(f.name, None)
        self.lookup_choices = model._meta.admin.manager.distinct().order_by(f.name).values(f.name)

    def title(self):
        return self.field.verbose_name

    def choices(self, cl):
        yield {'selected': self.lookup_val is None,
               'query_string': cl.get_query_string({}, [self.field.name]),
               'display': _('All')}
        for val in self.lookup_choices:
            val = str(val[self.field.name])
            yield {'selected': self.lookup_val == val,
                   'query_string': cl.get_query_string({self.field.name: val}),
                   'display': val}
FilterSpec.register(lambda f: True, AllValuesFilterSpec)
<|endoftext|>


<commit_before>"""
Formtools Preview application.

This is an abstraction of the following workflow:

    "Display an HTML form, force a preview, then do something with the submission."

Given a django.newforms.Form object that you define, this takes care of the
following:

    * Displays the form as HTML on a Web page.
    * Validates the form data once it's submitted via POST.
        * If it's valid, displays a preview page.
        * If it's not valid, redisplays the form with error messages.
    * At the preview page, if the preview confirmation button is pressed, calls
      a hook that you define -- a done() method.

The framework enforces the required preview by passing a shared-secret hash to
the preview page. If somebody tweaks the form parameters on the preview page,
the form submission will fail the hash comparison test.

Usage
=====

Subclass FormPreview and define a done() method:

    def done(self, request, clean_data):
        # ...

This method takes an HttpRequest object and a dictionary of the form data after
it has been validated and cleaned. It should return an HttpResponseRedirect.

Then, just instantiate your FormPreview subclass by passing it a Form class,
and pass that to your URLconf, like so:

    (r'^post/$', MyFormPreview(MyForm)),

The FormPreview class has a few other hooks. See the docstrings in the source
code below.

The framework also uses two templates: 'formtools/preview.html' and
'formtools/form.html'. You can override these by setting 'preview_template' and
'form_template' attributes on your FormPreview subclass. See
django/contrib/formtools/templates for the default templates.
"""

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.shortcuts import render_to_response
import cPickle as pickle
import md5

AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.

class FormPreview(object):
    preview_template = 'formtools/preview.html'
    form_template = 'formtools/form.html'

    # METHODS SUBCLASSES SHOULDN'T OVERRIDE ###################################

    def __init__(self, form):
        # form should be a Form class, not an instance.
        self.form, self.state = form, {}

    def __call__(self, request, *args, **kwargs):
        stage = {'1': 'preview', '2': 'post'}.get(request.POST.get(self.unused_name('stage')), 'preview')
        self.parse_params(*args, **kwargs)
        try:
            method = getattr(self, stage + '_' + request.method.lower())
        except AttributeError:
            raise Http404
        return method(request)

    def unused_name(self, name):
        """
        Given a first-choice name, adds an underscore to the name until it
        reaches a name that isn't claimed by any field in the form.

        This is calculated rather than being hard-coded so that no field names
        are off-limits for use in the form.
        """
        while 1:
            try:
                f = self.form.fields[name]
            except KeyError:
                break # This field name isn't being used by the form.
            name += '_'
        return name

    def preview_get(self, request):
        "Displays the form"
        f = self.form(auto_id=AUTO_ID)
        return render_to_response(self.form_template, {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state})

    def preview_post(self, request):
        "Validates the POST data. If valid, displays the preview page. Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state}
        if f.is_valid():
            context['hash_field'] = self.unused_name('hash')
            context['hash_value'] = self.security_hash(request, f)
            return render_to_response(self.preview_template, context)
        else:
            return render_to_response(self.form_template, context)

    def post_post(self, request):
        "Validates the POST data. If valid, calls done(). Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        if f.is_valid():
            if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
                return self.failed_hash(request) # Security hash failed.
            return self.done(request, f.clean_data)
        else:
            return render_to_response(self.form_template, {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state})

    # METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ########################

    def parse_params(self, *args, **kwargs):
        """
        Given captured args and kwargs from the URLconf, saves something in
        self.state and/or raises Http404 if necessary.

        For example, this URLconf captures a user_id variable:

            (r'^contact/(?P<user_id>\d{1,6})/$', MyFormPreview(MyForm)),

        In this case, the kwargs variable in parse_params would be
        {'user_id': 32} for a request to '/contact/32/'. You can use that
        user_id to make sure it's a valid user and/or save it for later, for
        use in done().
        """
        pass

    def security_hash(self, request, form):
        """
        Calculates the security hash for the given Form instance.

        This creates a list of the form field names/values in a deterministic
        order, pickles the result with the SECRET_KEY setting and takes an md5
        hash of that.

        Subclasses may want to take into account request-specific information
        such as the IP address.
        """
        data = [(bf.name, bf.data) for bf in form] + [settings.SECRET_KEY]
        # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
        # Python 2.3, but Django requires 2.3 anyway, so that's OK.
        pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
        return md5.new(pickled).hexdigest()

    def failed_hash(self, request):
        "Returns an HttpResponse in the case of an invalid security hash."
        return self.preview_post(request)

    # METHODS SUBCLASSES MUST OVERRIDE ########################################

    def done(self, request, clean_data):
        "Does something with the clean_data and returns an HttpResponseRedirect."
        raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)
<commit_msg>Fixed #3204 -- Changed FormPreview to use RequestContext<commit_after>"""
Formtools Preview application.

This is an abstraction of the following workflow:

    "Display an HTML form, force a preview, then do something with the submission."

Given a django.newforms.Form object that you define, this takes care of the
following:

    * Displays the form as HTML on a Web page.
    * Validates the form data once it's submitted via POST.
        * If it's valid, displays a preview page.
        * If it's not valid, redisplays the form with error messages.
    * At the preview page, if the preview confirmation button is pressed, calls
      a hook that you define -- a done() method.

The framework enforces the required preview by passing a shared-secret hash to
the preview page. If somebody tweaks the form parameters on the preview page,
the form submission will fail the hash comparison test.

Usage
=====

Subclass FormPreview and define a done() method:

    def done(self, request, clean_data):
        # ...

This method takes an HttpRequest object and a dictionary of the form data after
it has been validated and cleaned. It should return an HttpResponseRedirect.

Then, just instantiate your FormPreview subclass by passing it a Form class,
and pass that to your URLconf, like so:

    (r'^post/$', MyFormPreview(MyForm)),

The FormPreview class has a few other hooks. See the docstrings in the source
code below.

The framework also uses two templates: 'formtools/preview.html' and
'formtools/form.html'. You can override these by setting 'preview_template' and
'form_template' attributes on your FormPreview subclass. See
django/contrib/formtools/templates for the default templates.
"""

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.shortcuts import render_to_response
import cPickle as pickle
import md5

AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.

class FormPreview(object):
    preview_template = 'formtools/preview.html'
    form_template = 'formtools/form.html'

    # METHODS SUBCLASSES SHOULDN'T OVERRIDE ###################################

    def __init__(self, form):
        # form should be a Form class, not an instance.
        self.form, self.state = form, {}

    def __call__(self, request, *args, **kwargs):
        stage = {'1': 'preview', '2': 'post'}.get(request.POST.get(self.unused_name('stage')), 'preview')
        self.parse_params(*args, **kwargs)
        try:
            method = getattr(self, stage + '_' + request.method.lower())
        except AttributeError:
            raise Http404
        return method(request)

    def unused_name(self, name):
        """
        Given a first-choice name, adds an underscore to the name until it
        reaches a name that isn't claimed by any field in the form.

        This is calculated rather than being hard-coded so that no field names
        are off-limits for use in the form.
        """
        while 1:
            try:
                f = self.form.fields[name]
            except KeyError:
                break # This field name isn't being used by the form.
            name += '_'
        return name

    def preview_get(self, request):
        "Displays the form"
        f = self.form(auto_id=AUTO_ID)
        return render_to_response(self.form_template,
            {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
            context_instance=RequestContext(request))

    def preview_post(self, request):
        "Validates the POST data. If valid, displays the preview page. Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state}
        if f.is_valid():
            context['hash_field'] = self.unused_name('hash')
            context['hash_value'] = self.security_hash(request, f)
            return render_to_response(self.preview_template, context, context_instance=RequestContext(request))
        else:
            return render_to_response(self.form_template, context, context_instance=RequestContext(request))

    def post_post(self, request):
        "Validates the POST data. If valid, calls done(). Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        if f.is_valid():
            if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
                return self.failed_hash(request) # Security hash failed.
            return self.done(request, f.clean_data)
        else:
            return render_to_response(self.form_template,
                {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
                context_instance=RequestContext(request))

    # METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ########################

    def parse_params(self, *args, **kwargs):
        """
        Given captured args and kwargs from the URLconf, saves something in
        self.state and/or raises Http404 if necessary.

        For example, this URLconf captures a user_id variable:

            (r'^contact/(?P<user_id>\d{1,6})/$', MyFormPreview(MyForm)),

        In this case, the kwargs variable in parse_params would be
        {'user_id': 32} for a request to '/contact/32/'. You can use that
        user_id to make sure it's a valid user and/or save it for later, for
        use in done().
        """
        pass

    def security_hash(self, request, form):
        """
        Calculates the security hash for the given Form instance.

        This creates a list of the form field names/values in a deterministic
        order, pickles the result with the SECRET_KEY setting and takes an md5
        hash of that.

        Subclasses may want to take into account request-specific information
        such as the IP address.
        """
        data = [(bf.name, bf.data) for bf in form] + [settings.SECRET_KEY]
        # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
        # Python 2.3, but Django requires 2.3 anyway, so that's OK.
        pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
        return md5.new(pickled).hexdigest()

    def failed_hash(self, request):
        "Returns an HttpResponse in the case of an invalid security hash."
        return self.preview_post(request)

    # METHODS SUBCLASSES MUST OVERRIDE ########################################

    def done(self, request, clean_data):
        "Does something with the clean_data and returns an HttpResponseRedirect."
        raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)
<|endoftext|>


<commit_before>"""
Formtools Preview application.

This is an abstraction of the following workflow:

    "Display an HTML form, force a preview, then do something with the submission."

Given a django.newforms.Form object that you define, this takes care of the
following:

    * Displays the form as HTML on a Web page.
    * Validates the form data once it's submitted via POST.
        * If it's valid, displays a preview page.
        * If it's not valid, redisplays the form with error messages.
    * At the preview page, if the preview confirmation button is pressed, calls
      a hook that you define -- a done() method.

The framework enforces the required preview by passing a shared-secret hash to
the preview page. If somebody tweaks the form parameters on the preview page,
the form submission will fail the hash comparison test.

Usage
=====

Subclass FormPreview and define a done() method:

    def done(self, request, clean_data):
        # ...

This method takes an HttpRequest object and a dictionary of the form data after
it has been validated and cleaned. It should return an HttpResponseRedirect.

Then, just instantiate your FormPreview subclass by passing it a Form class,
and pass that to your URLconf, like so:

    (r'^post/$', MyFormPreview(MyForm)),

The FormPreview class has a few other hooks. See the docstrings in the source
code below.

The framework also uses two templates: 'formtools/preview.html' and
'formtools/form.html'. You can override these by setting 'preview_template' and
'form_template' attributes on your FormPreview subclass. See
django/contrib/formtools/templates for the default templates.
"""

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.shortcuts import render_to_response
import cPickle as pickle
import md5

AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.

class FormPreview(object):
    preview_template = 'formtools/preview.html'
    form_template = 'formtools/form.html'

    # METHODS SUBCLASSES SHOULDN'T OVERRIDE ###################################

    def __init__(self, form):
        # form should be a Form class, not an instance.
        self.form, self.state = form, {}

    def __call__(self, request, *args, **kwargs):
        stage = {'1': 'preview', '2': 'post'}.get(request.POST.get(self.unused_name('stage')), 'preview')
        self.parse_params(*args, **kwargs)
        try:
            method = getattr(self, stage + '_' + request.method.lower())
        except AttributeError:
            raise Http404
        return method(request)

    def unused_name(self, name):
        """
        Given a first-choice name, adds an underscore to the name until it
        reaches a name that isn't claimed by any field in the form.

        This is calculated rather than being hard-coded so that no field names
        are off-limits for use in the form.
        """
        while 1:
            try:
                f = self.form.fields[name]
            except KeyError:
                break # This field name isn't being used by the form.
            name += '_'
        return name

    def preview_get(self, request):
        "Displays the form"
        f = self.form(auto_id=AUTO_ID)
        return render_to_response(self.form_template,
            {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
            context_instance=RequestContext(request))

    def preview_post(self, request):
        "Validates the POST data. If valid, displays the preview page. Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state}
        if f.is_valid():
            context['hash_field'] = self.unused_name('hash')
            context['hash_value'] = self.security_hash(request, f)
            return render_to_response(self.preview_template, context, context_instance=RequestContext(request))
        else:
            return render_to_response(self.form_template, context, context_instance=RequestContext(request))

    def post_post(self, request):
        "Validates the POST data. If valid, calls done(). Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        if f.is_valid():
            if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
                return self.failed_hash(request) # Security hash failed.
            return self.done(request, f.clean_data)
        else:
            return render_to_response(self.form_template,
                {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
                context_instance=RequestContext(request))

    # METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ########################

    def parse_params(self, *args, **kwargs):
        """
        Given captured args and kwargs from the URLconf, saves something in
        self.state and/or raises Http404 if necessary.

        For example, this URLconf captures a user_id variable:

            (r'^contact/(?P<user_id>\d{1,6})/$', MyFormPreview(MyForm)),

        In this case, the kwargs variable in parse_params would be
        {'user_id': 32} for a request to '/contact/32/'. You can use that
        user_id to make sure it's a valid user and/or save it for later, for
        use in done().
        """
        pass

    def security_hash(self, request, form):
        """
        Calculates the security hash for the given Form instance.

        This creates a list of the form field names/values in a deterministic
        order, pickles the result with the SECRET_KEY setting and takes an md5
        hash of that.

        Subclasses may want to take into account request-specific information
        such as the IP address.
        """
        data = [(bf.name, bf.data) for bf in form] + [settings.SECRET_KEY]
        # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
        # Python 2.3, but Django requires 2.3 anyway, so that's OK.
        pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
        return md5.new(pickled).hexdigest()

    def failed_hash(self, request):
        "Returns an HttpResponse in the case of an invalid security hash."
        return self.preview_post(request)

    # METHODS SUBCLASSES MUST OVERRIDE ########################################

    def done(self, request, clean_data):
        "Does something with the clean_data and returns an HttpResponseRedirect."
        raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)
<commit_msg>Added missing import to django.contrib.formtools.preview from [4259]. Thanks, Vadim Macagon<commit_after>"""
Formtools Preview application.

This is an abstraction of the following workflow:

    "Display an HTML form, force a preview, then do something with the submission."

Given a django.newforms.Form object that you define, this takes care of the
following:

    * Displays the form as HTML on a Web page.
    * Validates the form data once it's submitted via POST.
        * If it's valid, displays a preview page.
        * If it's not valid, redisplays the form with error messages.
    * At the preview page, if the preview confirmation button is pressed, calls
      a hook that you define -- a done() method.

The framework enforces the required preview by passing a shared-secret hash to
the preview page. If somebody tweaks the form parameters on the preview page,
the form submission will fail the hash comparison test.

Usage
=====

Subclass FormPreview and define a done() method:

    def done(self, request, clean_data):
        # ...

This method takes an HttpRequest object and a dictionary of the form data after
it has been validated and cleaned. It should return an HttpResponseRedirect.

Then, just instantiate your FormPreview subclass by passing it a Form class,
and pass that to your URLconf, like so:

    (r'^post/$', MyFormPreview(MyForm)),

The FormPreview class has a few other hooks. See the docstrings in the source
code below.

The framework also uses two templates: 'formtools/preview.html' and
'formtools/form.html'. You can override these by setting 'preview_template' and
'form_template' attributes on your FormPreview subclass. See
django/contrib/formtools/templates for the default templates.
"""

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.http import Http404
from django.shortcuts import render_to_response
from django.template.context import RequestContext
import cPickle as pickle
import md5

AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.

class FormPreview(object):
    preview_template = 'formtools/preview.html'
    form_template = 'formtools/form.html'

    # METHODS SUBCLASSES SHOULDN'T OVERRIDE ###################################

    def __init__(self, form):
        # form should be a Form class, not an instance.
        self.form, self.state = form, {}

    def __call__(self, request, *args, **kwargs):
        stage = {'1': 'preview', '2': 'post'}.get(request.POST.get(self.unused_name('stage')), 'preview')
        self.parse_params(*args, **kwargs)
        try:
            method = getattr(self, stage + '_' + request.method.lower())
        except AttributeError:
            raise Http404
        return method(request)

    def unused_name(self, name):
        """
        Given a first-choice name, adds an underscore to the name until it
        reaches a name that isn't claimed by any field in the form.

        This is calculated rather than being hard-coded so that no field names
        are off-limits for use in the form.
        """
        while 1:
            try:
                f = self.form.fields[name]
            except KeyError:
                break # This field name isn't being used by the form.
            name += '_'
        return name

    def preview_get(self, request):
        "Displays the form"
        f = self.form(auto_id=AUTO_ID)
        return render_to_response(self.form_template,
            {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
            context_instance=RequestContext(request))

    def preview_post(self, request):
        "Validates the POST data. If valid, displays the preview page. Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        context = {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state}
        if f.is_valid():
            context['hash_field'] = self.unused_name('hash')
            context['hash_value'] = self.security_hash(request, f)
            return render_to_response(self.preview_template, context, context_instance=RequestContext(request))
        else:
            return render_to_response(self.form_template, context, context_instance=RequestContext(request))

    def post_post(self, request):
        "Validates the POST data. If valid, calls done(). Else, redisplays form."
        f = self.form(request.POST, auto_id=AUTO_ID)
        if f.is_valid():
            if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
                return self.failed_hash(request) # Security hash failed.
            return self.done(request, f.clean_data)
        else:
            return render_to_response(self.form_template,
                {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
                context_instance=RequestContext(request))

    # METHODS SUBCLASSES MIGHT OVERRIDE IF APPROPRIATE ########################

    def parse_params(self, *args, **kwargs):
        """
        Given captured args and kwargs from the URLconf, saves something in
        self.state and/or raises Http404 if necessary.

        For example, this URLconf captures a user_id variable:

            (r'^contact/(?P<user_id>\d{1,6})/$', MyFormPreview(MyForm)),

        In this case, the kwargs variable in parse_params would be
        {'user_id': 32} for a request to '/contact/32/'. You can use that
        user_id to make sure it's a valid user and/or save it for later, for
        use in done().
        """
        pass

    def security_hash(self, request, form):
        """
        Calculates the security hash for the given Form instance.

        This creates a list of the form field names/values in a deterministic
        order, pickles the result with the SECRET_KEY setting and takes an md5
        hash of that.

        Subclasses may want to take into account request-specific information
        such as the IP address.
        """
        data = [(bf.name, bf.data) for bf in form] + [settings.SECRET_KEY]
        # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
        # Python 2.3, but Django requires 2.3 anyway, so that's OK.
        pickled = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
        return md5.new(pickled).hexdigest()

    def failed_hash(self, request):
        "Returns an HttpResponse in the case of an invalid security hash."
        return self.preview_post(request)

    # METHODS SUBCLASSES MUST OVERRIDE ########################################

    def done(self, request, clean_data):
        "Does something with the clean_data and returns an HttpResponseRedirect."
        raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)
<|endoftext|>


<commit_before>from datetime import date, timedelta
import json

from mock import patch
from nose.tools import eq_

from lib.buyers.models import Buyer, BuyerPaypal
from solitude.base import APITest

class TestBuyer(APITest):

    def setUp(self):
        self.api_name = 'generic'
        self.uuid = 'sample:uid'
        self.list_url = self.get_list_url('buyer')

    def test_add(self):
        res = self.client.post(self.list_url, data={'uuid': self.uuid})
        eq_(res.status_code, 201)
        eq_(Buyer.objects.filter(uuid=self.uuid).count(), 1)

    def test_add_multiple(self):
        self.client.post(self.list_url, data={'uuid': self.uuid})
        res = self.client.post(self.list_url, data={'uuid': self.uuid})
        eq_(res.status_code, 400)
        eq_(self.get_errors(res.content, 'uuid'),
            # How do we stop uuid being capitalized?
            ['Buyer with this Uuid already exists.'])

    def test_add_empty(self):
        res = self.client.post(self.list_url, data={'uuid': ''})
        eq_(res.status_code, 400)
        eq_(self.get_errors(res.content, 'uuid'), ['This field is required.'])

    def test_add_missing(self):
        res = self.client.post(self.list_url, data={})
        eq_(res.status_code, 400)
        eq_(self.get_errors(res.content, 'uuid'), ['This field is required.'])

    def test_list_allowed(self):
        self.allowed_verbs(self.list_url, ['post'])

    def create(self):
        return Buyer.objects.create(uuid=self.uuid)

    def test_get(self):
        obj = self.create()
        res = self.client.get(self.get_detail_url('buyer', obj))
        eq_(res.status_code, 200)
        eq_(json.loads(res.content)['uuid'], self.uuid)

    def test_get_allowed(self):
        obj = self.create()
        self.allowed_verbs(self.get_detail_url('buyer', obj), ['get'])

class TestBuyerPaypal(APITest):

    def setUp(self):
        self.api_name = 'paypal'
        self.uuid = 'sample:uid'
        self.buyer = Buyer.objects.create(uuid=self.uuid)
        self.list_url = self.get_list_url('buyer')

    def test_post(self):
        res = self.client.post(self.list_url,
                               data={'buyer':
                                     '/paypal/buyer/%s/' % self.buyer.pk})
        eq_(res.status_code, 201)
        eq_(BuyerPaypal.objects.count(), 1)

    def test_get(self):
        obj = self.create()
        url = self.get_detail_url('buyer', obj)
        res = self.client.get(url)
        eq_(res.status_code, 200)
        eq_(json.loads(res.content)['key'], False)

    def test_get_generic(self):
        self.create()
        url = self.get_detail_url('buyer', self.buyer, api_name='generic')
        res = self.client.get(url)
        eq_(res.status_code, 200)
        eq_(json.loads(res.content)['paypal']['key'], False)

    def create(self):
        return BuyerPaypal.objects.create(buyer=self.buyer)

    def test_boolean_key(self):
        obj = self.create()
        url = self.get_detail_url('buyer', obj)

        res = self.client.get(url, data={'uuid': self.uuid})
        eq_(json.loads(res.content)['key'], False)

        obj.key = 'abc'
        obj.save()

        res = self.client.get(url, data={'uuid': self.uuid})
        eq_(json.loads(res.content)['key'], True)

@patch('lib.buyers.resource.Client.get_preapproval_key')
class TestPreapprovalPaypal(APITest):

    def setUp(self):
        self.api_name = 'paypal'
        self.uuid = 'sample:uid'
        self.list_url = self.get_list_url('preapproval')

    def get_data(self):
        return {'start': date.today().strftime('%Y-%m-%d'),
                'end': (date.today() +
                        timedelta(days=30)).strftime('%Y-%m-%d'),
                'return_url': 'http://foo.com/return.url',
                'cancel_url': 'http://foo.com/cancel.url'}

    def test_post(self, key):
        key.return_value = {'key': 'foo'}
        res = self.client.post(self.list_url, data=self.get_data())
        eq_(res.status_code, 201)
        eq_(json.loads(res.content)['key'], 'foo')

    def test_post_empty(self, key):
        res = self.client.post(self.list_url, data={})
        eq_(res.status_code, 400)
        data = json.loads(res.content)
        for k in ['start', 'end', 'return_url', 'cancel_url']:
            eq_(data[k], [u'This field is required.'])

    def test_post_not_date(self, key):
        data = self.get_data()
        data['start'] = '2012'
        res = self.client.post(self.list_url, data=data)
        eq_(res.status_code, 400)
        eq_(json.loads(res.content)['start'], [u'Enter a valid date.'])

    def test_post_not_url(self, key):
        data = self.get_data()
        data['return_url'] = 'blargh'
        res = self.client.post(self.list_url, data=data)
        eq_(res.status_code, 400)
        eq_(json.loads(res.content)['return_url'], [u'Enter a valid URL.'])

    def create(self):
        res = self.client.post(self.list_url, data=self.get_data())
        return json.loads(res.content)['pk']

    def test_get(self, key):
        key.return_value = {'key': 'foo'}
        uuid = self.create()
        url = self.get_detail_url('preapproval', uuid)
        res = self.client.get(url)
        assert 'foo' not in res  # Just check we didn't leak the key.

    def test_put(self, key):
        key.return_value = {'key': 'foo'}
        buyer = Buyer.objects.create(uuid=self.uuid)
        paypal = BuyerPaypal.objects.create(buyer=buyer)
        eq_(paypal.key, None)
        uuid = self.create()
        url = self.get_detail_url('preapproval', uuid)
        res = self.client.put(url, data={'uuid': buyer.uuid})
        eq_(res.status_code, 202)
        eq_(BuyerPaypal.objects.get(buyer=buyer).key, 'foo')

    def test_put_fails(self, key):
        url = self.get_detail_url('preapproval', 'asd')
        res = self.client.put(url)
        eq_(res.status_code, 404, res.content)

    def test_put_no_cache(self, key):
        key.return_value = {'key': 'foo'}
        buyer = Buyer.objects.create(uuid=self.uuid)
        paypal = BuyerPaypal.objects.create(buyer=buyer)
        eq_(paypal.key, None)

        url = self.get_detail_url('preapproval', '123')
        res = self.client.put(url, data={'uuid': buyer.uuid})
        eq_(res.status_code, 404)
<commit_msg>add note that we can disclose the key here<commit_after>from datetime import date, timedelta
import json

from mock import patch
from nose.tools import eq_

from lib.buyers.models import Buyer, BuyerPaypal
from solitude.base import APITest

class TestBuyer(APITest):

    def setUp(self):
        self.api_name = 'generic'
        self.uuid = 'sample:uid'
        self.list_url = self.get_list_url('buyer')

    def test_add(self):
        res = self.client.post(self.list_url, data={'uuid': self.uuid})
        eq_(res.status_code, 201)
        eq_(Buyer.objects.filter(uuid=self.uuid).count(), 1)

    def test_add_multiple(self):
        self.client.post(self.list_url, data={'uuid': self.uuid})
        res = self.client.post(self.list_url, data={'uuid': self.uuid})
        eq_(res.status_code, 400)
        eq_(self.get_errors(res.content, 'uuid'),
            # How do we stop uuid being capitalized?
            ['Buyer with this Uuid already exists.'])

    def test_add_empty(self):
        res = self.client.post(self.list_url, data={'uuid': ''})
        eq_(res.status_code, 400)
        eq_(self.get_errors(res.content, 'uuid'), ['This field is required.'])

    def test_add_missing(self):
        res = self.client.post(self.list_url, data={})
        eq_(res.status_code, 400)
        eq_(self.get_errors(res.content, 'uuid'), ['This field is required.'])

    def test_list_allowed(self):
        self.allowed_verbs(self.list_url, ['post'])

    def create(self):
        return Buyer.objects.create(uuid=self.uuid)

    def test_get(self):
        obj = self.create()
        res = self.client.get(self.get_detail_url('buyer', obj))
        eq_(res.status_code, 200)
        eq_(json.loads(res.content)['uuid'], self.uuid)

    def test_get_allowed(self):
        obj = self.create()
        self.allowed_verbs(self.get_detail_url('buyer', obj), ['get'])

class TestBuyerPaypal(APITest):

    def setUp(self):
        self.api_name = 'paypal'
        self.uuid = 'sample:uid'
        self.buyer = Buyer.objects.create(uuid=self.uuid)
        self.list_url = self.get_list_url('buyer')

    def test_post(self):
        res = self.client.post(self.list_url,
                               data={'buyer':
                                     '/paypal/buyer/%s/' % self.buyer.pk})
        eq_(res.status_code, 201)
        eq_(BuyerPaypal.objects.count(), 1)

    def test_get(self):
        obj = self.create()
        url = self.get_detail_url('buyer', obj)
        res = self.client.get(url)
        eq_(res.status_code, 200)
        eq_(json.loads(res.content)['key'], False)

    def test_get_generic(self):
        self.create()
        url = self.get_detail_url('buyer', self.buyer, api_name='generic')
        res = self.client.get(url)
        eq_(res.status_code, 200)
        eq_(json.loads(res.content)['paypal']['key'], False)

    def create(self):
        return BuyerPaypal.objects.create(buyer=self.buyer)

    def test_boolean_key(self):
        obj = self.create()
        url = self.get_detail_url('buyer', obj)

        res = self.client.get(url, data={'uuid': self.uuid})
        eq_(json.loads(res.content)['key'], False)

        obj.key = 'abc'
        obj.save()

        res = self.client.get(url, data={'uuid': self.uuid})
        eq_(json.loads(res.content)['key'], True)

@patch('lib.buyers.resource.Client.get_preapproval_key')
class TestPreapprovalPaypal(APITest):

    def setUp(self):
        self.api_name = 'paypal'
        self.uuid = 'sample:uid'
        self.list_url = self.get_list_url('preapproval')

    def get_data(self):
        return {'start': date.today().strftime('%Y-%m-%d'),
                'end': (date.today() +
                        timedelta(days=30)).strftime('%Y-%m-%d'),
                'return_url': 'http://foo.com/return.url',
                'cancel_url': 'http://foo.com/cancel.url'}

    def test_post(self, key):
        key.return_value = {'key': 'foo'}
        res = self.client.post(self.list_url, data=self.get_data())
        eq_(res.status_code, 201)
        # Note: the key needs to be disclosed here so it can be passed
        # on to client to ask PayPal. This is the only time it should
        # be disclosed however.
        eq_(json.loads(res.content)['key'], 'foo')

    def test_post_empty(self, key):
        res = self.client.post(self.list_url, data={})
        eq_(res.status_code, 400)
        data = json.loads(res.content)
        for k in ['start', 'end', 'return_url', 'cancel_url']:
            eq_(data[k], [u'This field is required.'])

    def test_post_not_date(self, key):
        data = self.get_data()
        data['start'] = '2012'
        res = self.client.post(self.list_url, data=data)
        eq_(res.status_code, 400)
        eq_(json.loads(res.content)['start'], [u'Enter a valid date.'])

    def test_post_not_url(self, key):
        data = self.get_data()
        data['return_url'] = 'blargh'
        res = self.client.post(self.list_url, data=data)
        eq_(res.status_code, 400)
        eq_(json.loads(res.content)['return_url'], [u'Enter a valid URL.'])

    def create(self):
        res = self.client.post(self.list_url, data=self.get_data())
        return json.loads(res.content)['pk']

    def test_get(self, key):
        key.return_value = {'key': 'foo'}
        uuid = self.create()
        url = self.get_detail_url('preapproval', uuid)
        res = self.client.get(url)
        assert 'foo' not in res  # Just check we didn't leak the key.

    def test_put(self, key):
        key.return_value = {'key': 'foo'}
        buyer = Buyer.objects.create(uuid=self.uuid)
        paypal = BuyerPaypal.objects.create(buyer=buyer)
        eq_(paypal.key, None)
        uuid = self.create()
        url = self.get_detail_url('preapproval', uuid)
        res = self.client.put(url, data={'uuid': buyer.uuid})
        eq_(res.status_code, 202)
        eq_(BuyerPaypal.objects.get(buyer=buyer).key, 'foo')

    def test_put_fails(self, key):
        url = self.get_detail_url('preapproval', 'asd')
        res = self.client.put(url)
        eq_(res.status_code, 404, res.content)

    def test_put_no_cache(self, key):
        key.return_value = {'key': 'foo'}
        buyer = Buyer.objects.create(uuid=self.uuid)
        paypal = BuyerPaypal.objects.create(buyer=buyer)
        eq_(paypal.key, None)

        url = self.get_detail_url('preapproval', '123')
        res = self.client.put(url, data={'uuid': buyer.uuid})
        eq_(res.status_code, 404)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# filter_qc 0.0.1
# Generated by dx-app-wizard.
#
# Basic execution pattern: Your app will run on a single machine from
# beginning to end.
#
# See https://wiki.dnanexus.com/Developer-Portal for documentation and
# tutorials on how to modify this file.
#
# DNAnexus Python Bindings (dxpy) documentation:
#   http://autodoc.dnanexus.com/bindings/python/current/

import os, subprocess, shlex
import dxpy

@dxpy.entry_point('main')
def main(input_bam, paired_end, samtools_params):

    # The following line(s) initialize your data object inputs on the platform
    # into dxpy.DXDataObject instances that you can start using immediately.

    raw_bam_file = dxpy.DXFile(input_bam)

    # The following line(s) download your file inputs to the local file system
    # using variable names for the filenames.

    raw_bam_filename = raw_bam_file.name
    raw_bam_basename = raw_bam_filename.rstrip('.bam')
    dxpy.download_dxfile(raw_bam_file.get_id(), raw_bam_filename)
    filt_bam_filename = raw_bam_basename + ".filt.srt.bam"
    tmp_filt_bam_filename = raw_bam_basename + ".dupmark.bam"
    dup_file_qc_filename = raw_bam_basename + ".dup.qc"

    print subprocess.check_output('ls -l', shell=True)

    with open(filt_bam_filename, 'w') as fh:
        subprocess.check_call(shlex.split("samtools view -F 1804 %s -b %s" \
            %(samtools_params, raw_bam_filename)), stdout=fh)

    subprocess.check_call(shlex.split(
        "java -Xmx4G -jar /picard/MarkDuplicates.jar INPUT=%s OUTPUT=%s METRICS_FILE=%s \
         VALIDATION_STRINGENCY=LENIENT ASSUME_SORTED=true REMOVE_DUPLICATES=false"
         %(filt_bam_filename, tmp_filt_bam_filename, dup_file_qc_filename)))

    open("filtered_bam_index",'a').close()
    open("filtered_mapstats",'a').close()
    open("pbc_file_qc",'a').close()

    # The following line(s) use the Python bindings to upload your file outputs
    # after you have created them on the local file system.  It assumes that you
    # have used the output field name for the filename for each output, but you
    # can change that behavior to suit your needs.

    filtered_bam = dxpy.upload_local_file(filt_bam_filename)
    filtered_bam_index = dxpy.upload_local_file("filtered_bam_index")
    filtered_mapstats = dxpy.upload_local_file("filtered_mapstats")
    dup_file_qc = dxpy.upload_local_file(dup_file_qc_filename)
    pbc_file_qc = dxpy.upload_local_file("pbc_file_qc")

    # The following line fills in some basic dummy output and assumes
    # that you have created variables to represent your output with
    # the same name as your output fields.

    output = {}
    output["filtered_bam"] = dxpy.dxlink(filtered_bam)
    output["filtered_bam_index"] = dxpy.dxlink(filtered_bam_index)
    output["filtered_mapstats"] = dxpy.dxlink(filtered_mapstats)
    output["dup_file_qc"] = dxpy.dxlink(dup_file_qc)
    output["pbc_file_qc"] = dxpy.dxlink(pbc_file_qc)

    return output

dxpy.run()
<commit_msg>Complete post-alignment filtering for single-end<commit_after>#!/usr/bin/env python
# filter_qc 0.0.1
# Generated by dx-app-wizard.
#
# Basic execution pattern: Your app will run on a single machine from
# beginning to end.
#
# See https://wiki.dnanexus.com/Developer-Portal for documentation and
# tutorials on how to modify this file.
#
# DNAnexus Python Bindings (dxpy) documentation:
#   http://autodoc.dnanexus.com/bindings/python/current/

import os, subprocess, shlex
import dxpy

def run_pipe(steps, outfile=None):
    #break this out into a recursive function
    #TODO:  as written does not handle single-step pipes
    from subprocess import Popen, PIPE
    p = None
    p_next = None
    first_step_n = 1
    last_step_n = len(steps)
    for n,step in enumerate(steps, start=first_step_n):
        print "step: %s" %(step)
        if n == first_step_n:
            p = Popen(shlex.split(step), stdout=PIPE)
        elif n == last_step_n and outfile: #only treat the last step specially if you're sending stdout to a file
            with open(outfile, 'w') as fh:
                p_last = Popen(shlex.split(step), stdin=p.stdout, stdout=fh)
                p.stdout.close()
                p = p_last
        else: #handles intermediate steps and, in the case of a pipe to stdout, the last step
            p_next = Popen(shlex.split(step), stdin=p.stdout, stdout=PIPE)
            p.stdout.close()
            p = p_next
    out,err = p.communicate()
    return out,err

@dxpy.entry_point('main')
def main(input_bam, paired_end, samtools_params):

    print "In main"

    # The following line(s) initialize your data object inputs on the platform
    # into dxpy.DXDataObject instances that you can start using immediately.

    raw_bam_file = dxpy.DXFile(input_bam)

    # The following line(s) download your file inputs to the local file system
    # using variable names for the filenames.

    raw_bam_filename = raw_bam_file.name
    raw_bam_basename = raw_bam_filename.rstrip('.bam')
    dxpy.download_dxfile(raw_bam_file.get_id(), raw_bam_filename)

    print subprocess.check_output('ls -l', shell=True)

    # =============================
    # Remove  unmapped, mate unmapped
    # not primary alignment, reads failing platform
    # Remove low MAPQ reads
    # Obtain name sorted BAM file
    # ==================
    filt_bam_filename = raw_bam_basename + ".filt.srt.bam"
    with open(filt_bam_filename, 'w') as fh:
        subprocess.check_call(shlex.split("samtools view -F 1804 %s -b %s"
            %(samtools_params, raw_bam_filename)), stdout=fh)

    # ========================
    # Mark duplicates
    # ======================
    tmp_filt_bam_filename = raw_bam_basename + ".dupmark.bam"
    dup_file_qc_filename = raw_bam_basename + ".dup.qc"
    subprocess.check_call(shlex.split(
        "java -Xmx4G -jar /picard/MarkDuplicates.jar INPUT=%s OUTPUT=%s METRICS_FILE=%s \
         VALIDATION_STRINGENCY=LENIENT ASSUME_SORTED=true REMOVE_DUPLICATES=false"
         %(filt_bam_filename, tmp_filt_bam_filename, dup_file_qc_filename)))
    os.rename(tmp_filt_bam_filename,filt_bam_filename)

    # ============================
    # Remove duplicates
    # Index final position sorted BAM
    # ============================
    final_bam_prefix = raw_bam_basename + ".filt.nodup.srt"
    final_bam_filename = final_bam_prefix + ".bam" # To be stored
    final_bam_index_filename = final_bam_prefix + ".bai" # To be stored
    final_bam_file_mapstats_filename = final_bam_prefix + ".flagstat.qc" # QC file
    with open(final_bam_filename, 'w') as fh:
        subprocess.check_call(shlex.split("samtools view -F 1804 -b %s"
            %(filt_bam_filename)), stdout=fh)
    subprocess.check_call(shlex.split("samtools index %s %s" %(final_bam_filename, final_bam_index_filename)))
    with open(final_bam_file_mapstats_filename, 'w') as fh:
        subprocess.check_call(shlex.split("samtools flagstat %s"
            %(final_bam_filename)), stdout=fh)

    # =============================
    # Compute library complexity
    # =============================
    # Sort by name
    # convert to bedPE and obtain fragment coordinates
    # sort by position and strand
    # Obtain unique count statistics
    pbc_file_qc_filename = final_bam_prefix + ".pbc.qc"
    # PBC File output
    # TotalReadPairs [tab] DistinctReadPairs [tab] OneReadPair [tab] TwoReadPairs [tab] NRF=Distinct/Total [tab] PBC1=OnePair/Distinct [tab] PBC2=OnePair/TwoPair
    steps = [
        "bamToBed -i %s" %(final_bam_filename), #for some reason bedtools bamtobed does not work
        r"""awk 'BEGIN{OFS="\t"}{print $1,$2,$3,$6}'""",
        "grep -v 'chrM'",
        "sort",
        "uniq -c",
        r"""awk 'BEGIN{mt=0;m0=0;m1=0;m2=0} ($1==1){m1=m1+1} ($1==2){m2=m2+1} {m0=m0+1} {mt=mt+$1} END{printf "%d\t%d\t%d\t%d\t%f\t%f\t%f\n",mt,m0,m1,m2,m0/mt,m1/m0,m1/m2}'"""
        ]
    out,err = run_pipe(steps,pbc_file_qc_filename)
    if err:
        print "PBC file error: %s" %(err)

    # Use the Python bindings to upload the file outputs to the project.
    filtered_bam = dxpy.upload_local_file(filt_bam_filename)
    filtered_bam_index = dxpy.upload_local_file(final_bam_index_filename)
    filtered_mapstats = dxpy.upload_local_file(final_bam_file_mapstats_filename)
    dup_file_qc = dxpy.upload_local_file(dup_file_qc_filename)
    pbc_file_qc = dxpy.upload_local_file(pbc_file_qc_filename)

    # Return links to the output files
    output = {}
    output["filtered_bam"] = dxpy.dxlink(filtered_bam)
    output["filtered_bam_index"] = dxpy.dxlink(filtered_bam_index)
    output["filtered_mapstats"] = dxpy.dxlink(filtered_mapstats)
    output["dup_file_qc"] = dxpy.dxlink(dup_file_qc)
    output["pbc_file_qc"] = dxpy.dxlink(pbc_file_qc)

    return output

dxpy.run()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2019 Compassion CH (http://www.compassion.ch)
#    @author: Nicolas Badoux <n.badoux@hotmail.com>
#
#    The licence is in the file __manifest__.py
#
##############################################################################

from odoo import api, fields, models
from odoo.addons.firebase_connector.controllers.firebase_controller\
    import RestController as Firebase

import logging

class GetPartnerMessage(models.Model):
    _inherit = "firebase.registration"

    receive_child_notification = fields.Boolean()
    receive_general_notification = fields.Boolean()

    ##########################################################################
    #                             PUBLIC METHODS                             #
    ##########################################################################
    @api.model
    def mobile_update_notification_preference(self, json_data, **params):
        """
        This is called when the user updates his notification preferences.
        :param params: {
            "firebaseId": the firebase id of the device where the request
                          originated
            "appchild": boolean (receive child notification)
            "appinfo": boolean (receive general notifications)
        }
        :return:
        """
        firebase_id = json_data.get('firebaseId')
        partner_id = json_data.get('SupporterId'),
        reg = self.env['firebase.registration'].search([
            ('registration_id', '=', firebase_id)])

        if len(reg) == 0:
            # id is not yet registered in Odoo
            logging.warning("Received a notification preference for a device "
                            "not yet registered in Odoo. It should not happen "
                            "in the normal registration flow.")
            self.mobile_register(json_data, {
                'operation': 'Insert',
                'supId': partner_id,
                'firebaseId': firebase_id,
            })
        else:
            reg.receive_child_notification = json_data.get('appchild') == '1'
            reg.receive_general_notification = json_data.get('appinfo') == '1'

        return {
            "UpdateRecordingContactResult":
            "App notification Child And App notification child Info updated "
            "of Supporter ID : {} ({} {}, {})".format(
                partner_id,
                firebase_id,
                reg.receive_child_notification,
                reg.receive_general_notification,)
        }

    @api.model
    def mobile_register(self, json_data, **params):
        """
        This function redirect mobile app request to register and deregister
        Firebase ids from Odoo. It redirects to the correct function in the
        firebase_connector module.
        :param json_data: since the request is urlformencoded this field is
                          usually empty and we look for data in params
        :param params: {
                    firebaseId: the firebase token from the device
                    operation: Insert or Delete, depending if un/ registering
                    supId: optional partner_id as stored in Odoo
               }
        :return: the return value of register firebase
        """

        firebase_id = params['firebaseId']
        operation = params['operation']
        partner_id = params.get('supId', None)
        if partner_id == "":
            partner_id = None
        logging.debug(
            operation + "ing a Firebase ID from partner id: " +
            str(partner_id) + " with value: " + firebase_id)

        if operation == 'Insert':
            reg_id = Firebase().firebase_register(
                registration_id=firebase_id,
                partner_id=partner_id,
            )
        elif operation == 'Delete':
            reg_id = Firebase().firebase_unregister(
                registration_id=firebase_id,
                partner_id=partner_id
            )
        else:
            raise NotImplemented('Operation %s is not supported by Odoo' %
                                 operation)

        return reg_id
<commit_msg>FIX firebase registration access issue<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2019 Compassion CH (http://www.compassion.ch)
#    @author: Nicolas Badoux <n.badoux@hotmail.com>
#
#    The licence is in the file __manifest__.py
#
##############################################################################

from odoo import api, fields, models
from odoo.addons.firebase_connector.controllers.firebase_controller\
    import RestController as Firebase

import logging

class GetPartnerMessage(models.Model):
    _inherit = "firebase.registration"

    receive_child_notification = fields.Boolean()
    receive_general_notification = fields.Boolean()

    ##########################################################################
    #                             PUBLIC METHODS                             #
    ##########################################################################
    @api.model
    def mobile_update_notification_preference(self, json_data, **params):
        """
        This is called when the user updates his notification preferences.
        :param params: {
            "firebaseId": the firebase id of the device where the request
                          originated
            "appchild": boolean (receive child notification)
            "appinfo": boolean (receive general notifications)
        }
        :return:
        """
        firebase_id = json_data.get('firebaseId')
        partner_id = json_data.get('SupporterId'),
        reg = self.env['firebase.registration'].search([
            ('registration_id', '=', firebase_id)]).sudo()

        if len(reg) == 0:
            # id is not yet registered in Odoo
            logging.warning("Received a notification preference for a device "
                            "not yet registered in Odoo. It should not happen "
                            "in the normal registration flow.")
            self.mobile_register(json_data, {
                'operation': 'Insert',
                'supId': partner_id,
                'firebaseId': firebase_id,
            })
        else:
            reg.receive_child_notification = json_data.get('appchild') == '1'
            reg.receive_general_notification = json_data.get('appinfo') == '1'

        return {
            "UpdateRecordingContactResult":
            "App notification Child And App notification child Info updated "
            "of Supporter ID : {} ({} {}, {})".format(
                partner_id,
                firebase_id,
                reg.receive_child_notification,
                reg.receive_general_notification,)
        }

    @api.model
    def mobile_register(self, json_data, **params):
        """
        This function redirect mobile app request to register and deregister
        Firebase ids from Odoo. It redirects to the correct function in the
        firebase_connector module.
        :param json_data: since the request is urlformencoded this field is
                          usually empty and we look for data in params
        :param params: {
                    firebaseId: the firebase token from the device
                    operation: Insert or Delete, depending if un/ registering
                    supId: optional partner_id as stored in Odoo
               }
        :return: the return value of register firebase
        """

        firebase_id = params['firebaseId']
        operation = params['operation']
        partner_id = params.get('supId', None)
        if partner_id == "":
            partner_id = None
        logging.debug(
            operation + "ing a Firebase ID from partner id: " +
            str(partner_id) + " with value: " + firebase_id)

        if operation == 'Insert':
            reg_id = Firebase().firebase_register(
                registration_id=firebase_id,
                partner_id=partner_id,
            )
        elif operation == 'Delete':
            reg_id = Firebase().firebase_unregister(
                registration_id=firebase_id,
                partner_id=partner_id
            )
        else:
            raise NotImplemented('Operation %s is not supported by Odoo' %
                                 operation)

        return reg_id
<|endoftext|>


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2012 Intel, Inc.
# Copyright (c) 2011-2012 OpenStack, LLC.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""
Filter to add support for Trusted Computing Pools.

Filter that only schedules tasks on a host if the integrity (trust)
of that host matches the trust requested in the `extra_specs' for the
flavor.  The `extra_specs' will contain a key/value pair where the
key is `trust'.  The value of this pair (`trusted'/`untrusted') must
match the integrity of that host (obtained from the Attestation
service) before the task can be scheduled on that host.

Note that the parameters to control access to the Attestation Service
are in the `nova.conf' file in a separate `trust' section.  For example,
the config file will look something like:

    [DEFAULT]
    verbose=True
    ...
    [trust]
    server=attester.mynetwork.com

Details on the specific parameters can be found in the file `trust_attest.py'.

Details on setting up and using an Attestation Service can be found at
the Open Attestation project at:

    https://github.com/OpenAttestation/OpenAttestation
"""

import httplib
import socket
import ssl

from nova import flags
from nova.openstack.common import cfg
from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging
from nova.scheduler import filters

LOG = logging.getLogger(__name__)

trusted_opts = [
    cfg.StrOpt('server',
               default=None,
               help='attestation server http'),
    cfg.StrOpt('server_ca_file',
               default=None,
               help='attestation server Cert file for Identity verification'),
    cfg.StrOpt('port',
               default='8443',
               help='attestation server port'),
    cfg.StrOpt('api_url',
               default='/OpenAttestationWebServices/V1.0',
               help='attestation web API URL'),
    cfg.StrOpt('auth_blob',
               default=None,
               help='attestation authorization blob - must change'),
]

FLAGS = flags.FLAGS
trust_group = cfg.OptGroup(name='trusted_computing', title='Trust parameters')
FLAGS.register_group(trust_group)
FLAGS.register_opts(trusted_opts, group='trusted_computing')

class HTTPSClientAuthConnection(httplib.HTTPSConnection):
    """
    Class to make a HTTPS connection, with support for full client-based
    SSL Authentication
    """

    def __init__(self, host, port, key_file, cert_file, ca_file, timeout=None):
        httplib.HTTPSConnection.__init__(self, host,
                                         key_file=key_file,
                                         cert_file=cert_file)
        self.host = host
        self.port = port
        self.key_file = key_file
        self.cert_file = cert_file
        self.ca_file = ca_file
        self.timeout = timeout

    def connect(self):
        """
        Connect to a host on a given (SSL) port.
        If ca_file is pointing somewhere, use it to check Server Certificate.

        Redefined/copied and extended from httplib.py:1105 (Python 2.6.x).
        This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to
        ssl.wrap_socket(), which forces SSL to check server certificate
        against our client certificate.
        """
        sock = socket.create_connection((self.host, self.port), self.timeout)
        self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                                    ca_certs=self.ca_file,
                                    cert_reqs=ssl.CERT_REQUIRED)

class AttestationService(httplib.HTTPSConnection):
    # Provide access wrapper to attestation server to get integrity report.

    def __init__(self):
        self.api_url = FLAGS.trusted_computing.api_url
        self.host = FLAGS.trusted_computing.server
        self.port = FLAGS.trusted_computing.port
        self.auth_blob = FLAGS.trusted_computing.auth_blob
        self.key_file = None
        self.cert_file = None
        self.ca_file = FLAGS.trusted_computing.server_ca_file
        self.request_count = 100

    def _do_request(self, method, action_url, body, headers):
        # Connects to the server and issues a request.
        # :returns: result data
        # :raises: IOError if the request fails

        action_url = "%s/%s" % (self.api_url, action_url)
        try:
            c = HTTPSClientAuthConnection(self.host, self.port,
                                          key_file=self.key_file,
                                          cert_file=self.cert_file,
                                          ca_file=self.ca_file)
            c.request(method, action_url, body, headers)
            res = c.getresponse()
            status_code = res.status
            if status_code in (httplib.OK,
                               httplib.CREATED,
                               httplib.ACCEPTED,
                               httplib.NO_CONTENT):
                return httplib.OK, res
            return status_code, None

        except (socket.error, IOError) as e:
            return IOError, None

    def _request(self, cmd, subcmd, host):
        body = {}
        body['count'] = 1
        body['hosts'] = host
        cooked = jsonutils.dumps(body)
        headers = {}
        headers['content-type'] = 'application/json'
        headers['Accept'] = 'application/json'
        if self.auth_blob:
            headers['x-auth-blob'] = self.auth_blob
        status, res = self._do_request(cmd, subcmd, cooked, headers)
        if status == httplib.OK:
            data = res.read()
            return status, jsonutils.loads(data)
        else:
            return status, None

    def _check_trust(self, data, host):
        for item in data:
            for state in item['hosts']:
                if state['host_name'] == host:
                    return state['trust_lvl']
        return ""

    def do_attestation(self, host):
        state = []
        status, data = self._request("POST", "PollHosts", host)
        if status != httplib.OK:
            return {}
        state.append(data)
        return self._check_trust(state, host)

class TrustedFilter(filters.BaseHostFilter):
    """Trusted filter to support Trusted Compute Pools."""

    def __init__(self):
        self.attestation_service = AttestationService()

    def _is_trusted(self, host, trust):
        level = self.attestation_service.do_attestation(host)
        LOG.debug(_("TCP: trust state of "
                    "%(host)s:%(level)s(%(trust)s)") % locals())
        return trust == level

    def host_passes(self, host_state, filter_properties):
        instance = filter_properties.get('instance_type', {})
        extra = instance.get('extra_specs', {})
        trust = extra.get('trust:trusted_host')
        host = host_state.host
        if trust:
            return self._is_trusted(host, trust)
        return True
<commit_msg>Clarify trusted_filter conf options<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2012 Intel, Inc.
# Copyright (c) 2011-2012 OpenStack, LLC.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""
Filter to add support for Trusted Computing Pools.

Filter that only schedules tasks on a host if the integrity (trust)
of that host matches the trust requested in the `extra_specs' for the
flavor.  The `extra_specs' will contain a key/value pair where the
key is `trust'.  The value of this pair (`trusted'/`untrusted') must
match the integrity of that host (obtained from the Attestation
service) before the task can be scheduled on that host.

Note that the parameters to control access to the Attestation Service
are in the `nova.conf' file in a separate `trust' section.  For example,
the config file will look something like:

    [DEFAULT]
    verbose=True
    ...
    [trust]
    server=attester.mynetwork.com

Details on the specific parameters can be found in the file `trust_attest.py'.

Details on setting up and using an Attestation Service can be found at
the Open Attestation project at:

    https://github.com/OpenAttestation/OpenAttestation
"""

import httplib
import socket
import ssl

from nova import flags
from nova.openstack.common import cfg
from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging
from nova.scheduler import filters

LOG = logging.getLogger(__name__)

trusted_opts = [
    cfg.StrOpt('attestation_server',
               # deprecated in Grizzly
               deprecated_name='server',
               default=None,
               help='attestation server http'),
    cfg.StrOpt('attestation_server_ca_file',
               deprecated_name='server_ca_file',
               default=None,
               help='attestation server Cert file for Identity verification'),
    cfg.StrOpt('attestation_port',
               deprecated_name='port',
               default='8443',
               help='attestation server port'),
    cfg.StrOpt('attestation_api_url',
               deprecated_name='api_url',
               default='/OpenAttestationWebServices/V1.0',
               help='attestation web API URL'),
    cfg.StrOpt('attestation_auth_blob',
               deprecated_name='auth_blob',
               default=None,
               help='attestation authorization blob - must change'),
]

FLAGS = flags.FLAGS
trust_group = cfg.OptGroup(name='trusted_computing', title='Trust parameters')
FLAGS.register_group(trust_group)
FLAGS.register_opts(trusted_opts, group='trusted_computing')

class HTTPSClientAuthConnection(httplib.HTTPSConnection):
    """
    Class to make a HTTPS connection, with support for full client-based
    SSL Authentication
    """

    def __init__(self, host, port, key_file, cert_file, ca_file, timeout=None):
        httplib.HTTPSConnection.__init__(self, host,
                                         key_file=key_file,
                                         cert_file=cert_file)
        self.host = host
        self.port = port
        self.key_file = key_file
        self.cert_file = cert_file
        self.ca_file = ca_file
        self.timeout = timeout

    def connect(self):
        """
        Connect to a host on a given (SSL) port.
        If ca_file is pointing somewhere, use it to check Server Certificate.

        Redefined/copied and extended from httplib.py:1105 (Python 2.6.x).
        This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to
        ssl.wrap_socket(), which forces SSL to check server certificate
        against our client certificate.
        """
        sock = socket.create_connection((self.host, self.port), self.timeout)
        self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                                    ca_certs=self.ca_file,
                                    cert_reqs=ssl.CERT_REQUIRED)

class AttestationService(httplib.HTTPSConnection):
    # Provide access wrapper to attestation server to get integrity report.

    def __init__(self):
        self.api_url = FLAGS.trusted_computing.attestation_api_url
        self.host = FLAGS.trusted_computing.attestation_server
        self.port = FLAGS.trusted_computing.attestation_port
        self.auth_blob = FLAGS.trusted_computing.attestation_auth_blob
        self.key_file = None
        self.cert_file = None
        self.ca_file = FLAGS.trusted_computing.attestation_server_ca_file
        self.request_count = 100

    def _do_request(self, method, action_url, body, headers):
        # Connects to the server and issues a request.
        # :returns: result data
        # :raises: IOError if the request fails

        action_url = "%s/%s" % (self.api_url, action_url)
        try:
            c = HTTPSClientAuthConnection(self.host, self.port,
                                          key_file=self.key_file,
                                          cert_file=self.cert_file,
                                          ca_file=self.ca_file)
            c.request(method, action_url, body, headers)
            res = c.getresponse()
            status_code = res.status
            if status_code in (httplib.OK,
                               httplib.CREATED,
                               httplib.ACCEPTED,
                               httplib.NO_CONTENT):
                return httplib.OK, res
            return status_code, None

        except (socket.error, IOError) as e:
            return IOError, None

    def _request(self, cmd, subcmd, host):
        body = {}
        body['count'] = 1
        body['hosts'] = host
        cooked = jsonutils.dumps(body)
        headers = {}
        headers['content-type'] = 'application/json'
        headers['Accept'] = 'application/json'
        if self.auth_blob:
            headers['x-auth-blob'] = self.auth_blob
        status, res = self._do_request(cmd, subcmd, cooked, headers)
        if status == httplib.OK:
            data = res.read()
            return status, jsonutils.loads(data)
        else:
            return status, None

    def _check_trust(self, data, host):
        for item in data:
            for state in item['hosts']:
                if state['host_name'] == host:
                    return state['trust_lvl']
        return ""

    def do_attestation(self, host):
        state = []
        status, data = self._request("POST", "PollHosts", host)
        if status != httplib.OK:
            return {}
        state.append(data)
        return self._check_trust(state, host)

class TrustedFilter(filters.BaseHostFilter):
    """Trusted filter to support Trusted Compute Pools."""

    def __init__(self):
        self.attestation_service = AttestationService()

    def _is_trusted(self, host, trust):
        level = self.attestation_service.do_attestation(host)
        LOG.debug(_("TCP: trust state of "
                    "%(host)s:%(level)s(%(trust)s)") % locals())
        return trust == level

    def host_passes(self, host_state, filter_properties):
        instance = filter_properties.get('instance_type', {})
        extra = instance.get('extra_specs', {})
        trust = extra.get('trust:trusted_host')
        host = host_state.host
        if trust:
            return self._is_trusted(host, trust)
        return True
<|endoftext|>


<commit_before>import colander
from zope.interface import implementer

from substanced.content import content
from substanced.schema import NameSchemaNode
from substanced.util import renamer

from dace.objectofcollaboration.application import Application
from dace.descriptors import CompositeMultipleProperty
from pontus.core import VisualisableElement, VisualisableElementSchema
from pontus.widget import SequenceWidget, LineWidget, TableWidget
from pontus.schema import omit

from .working_group import WorkingGroupSchema, WorkingGroup
from .organization import OrganizationSchema, Organization
from .idea import IdeaSchema, Idea
from .interface import INovaIdeoApplication
from .invitation import InvitationSchema, Invitation
from .keyword import KeywordSchema, Keyword
from novaideo import _

default_titles = [_('Mr'), _('Madam'), _('Miss')]

default_comment_intentions = [_('Ironie'), _('Humour'), _('Remarque')]

default_correlation_intentions = [_('Ironie'), _('Humour'), _('Remarque')]

default_idea_intentions = [_('Ammelioration'), _('Humour'), _('Ironie')]

default_amendment_intentions = [_('Ammelioration'), _('Humour'), _('Ironie')]

def context_is_a_root(context, request):
    return request.registry.content.istype(context, 'Root')

class NovaIdeoApplicationSchema(VisualisableElementSchema):

    name = NameSchemaNode(
        editing=context_is_a_root,
        )

    titles = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Title")
            ),
        widget=SequenceWidget(),
        default=default_titles,
        title=_('List of titles'),
        )

    comment_intention = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Comment intention")
            ),
        widget=SequenceWidget(),
        default=default_comment_intentions,
        title=_('Comment intentions'),
        )

    idea_intention = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Idea intention")
            ),
        widget=SequenceWidget(),
        default=default_idea_intentions,
        title=_('Idea intentions'),
        )

    amendment_intention = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Amendment intention")
            ),
        widget=SequenceWidget(),
        default=default_amendment_intentions,
        title=_('Amendment intentions'),
        )

    invitations = colander.SchemaNode(
        colander.Sequence(),
        omit(InvitationSchema(factory=Invitation,
                               editable=True,
                               name=_('Invitations')),['_csrf_token_']),
        title=_('List of invitation'),
        )

    working_groups = colander.SchemaNode(
        colander.Sequence(),
        omit(WorkingGroupSchema(factory=WorkingGroup,
                editable=True,
                name=_('Working group')),['_csrf_token_']),
        title=_('Working groups'),
        )

    organizations = colander.SchemaNode(
        colander.Sequence(),
        omit(OrganizationSchema(factory=Organization,
                editable=True,
                name=_('Organization')),['_csrf_token_']),
        title=_('Organizations'),
        )

    keywords = colander.SchemaNode(
        colander.Sequence(),
        omit(KeywordSchema(widget=LineWidget(),
                           factory=Keyword,
                           editable=True,
                           name='Keyword'),['_csrf_token_']),
        widget=TableWidget(min_len=1),
        title='Keywords',
        )

    ideas = colander.SchemaNode(
        colander.Sequence(),
        omit(IdeaSchema(factory=Idea,
                        name=_('Idea')),['_csrf_token_']),
        title=_('Ideas'),
        )

    participants_mini = colander.SchemaNode(
        colander.Integer(),
        title=_('Minimum number of participants for a working group'),
        default=3,
        )

    participants_maxi = colander.SchemaNode(
        colander.Integer(),
        title=_('Maximum number of participants for a working group'),
        default=12,
        )

    participations_maxi = colander.SchemaNode(
        colander.Integer(),
        title=_('Maximum number of working group by member'),
        default=5,
        )

    tokens_mini = colander.SchemaNode(
        colander.Integer(),
        title=_('Minimum number of tokens by member'),
        default=7,
        )

@content(
    'Root',
    icon='glyphicon glyphicon-home',
    after_create='after_create',
    )
@implementer(INovaIdeoApplication)
class NovaIdeoApplication(VisualisableElement, Application):
    name = renamer()
    working_groups = CompositeMultipleProperty('working_groups')
    proposals = CompositeMultipleProperty('proposals')
    organizations = CompositeMultipleProperty('organizations')
    invitations = CompositeMultipleProperty('invitations')
    ideas = CompositeMultipleProperty('ideas')
    keywords = CompositeMultipleProperty('keywords')
    correlations = CompositeMultipleProperty('correlations')

    def __init__(self, **kwargs):
        super(NovaIdeoApplication, self).__init__(**kwargs)
        self.title = 'NovaIdeo'
        self.participants_mini = 2
        self.participants_maxi = 12
        self.participations_maxi = 5
        self.tokens_mini = 7
        self.titles = default_titles
        self.comment_intentions = default_comment_intentions
        self.correlation_intentions = default_correlation_intentions
        self.idea_intentions = default_idea_intentions
        self.amendment_intentions = default_idea_intentions

    @property
    def keywords_ids(self):
        return dict([(k.title, k) for k in self.keywords])

    def get_keywords(self, keywords_ids):
        result = []
        newkeywords = []
        for k in keywords_ids:
            if k in self.keywords_ids.keys():
                result.append(self.keywords_ids[k])
            else:
                key = Keyword(title=k)
                newkeywords.append(key)

        return result, newkeywords
<commit_msg>corrections<commit_after>import colander
from zope.interface import implementer

from substanced.content import content
from substanced.schema import NameSchemaNode
from substanced.util import renamer

from dace.objectofcollaboration.application import Application
from dace.descriptors import CompositeMultipleProperty
from pontus.core import VisualisableElement, VisualisableElementSchema
from pontus.widget import SequenceWidget, LineWidget, TableWidget
from pontus.schema import omit

from .working_group import WorkingGroupSchema, WorkingGroup
from .organization import OrganizationSchema, Organization
from .idea import IdeaSchema, Idea
from .interface import INovaIdeoApplication
from .invitation import InvitationSchema, Invitation
from .keyword import KeywordSchema, Keyword
from novaideo import _

default_titles = [_('Mr'), _('Madam'), _('Miss')]

default_comment_intentions = [_('Irony'), _('Humor'), _('Remark')]

default_correlation_intentions = [_('Irony'), _('Humor'), _('Remark')]

default_idea_intentions = [_('Improvement'), _('Humor'), _('Irony')]

default_amendment_intentions = [_('Improvement'), _('Humor'), _('Irony')]

def context_is_a_root(context, request):
    return request.registry.content.istype(context, 'Root')

class NovaIdeoApplicationSchema(VisualisableElementSchema):

    name = NameSchemaNode(
        editing=context_is_a_root,
        )

    titles = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Title")
            ),
        widget=SequenceWidget(),
        default=default_titles,
        title=_('List of titles'),
        )

    comment_intention = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Comment intention")
            ),
        widget=SequenceWidget(),
        default=default_comment_intentions,
        title=_('Comment intentions'),
        )

    idea_intention = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Idea intention")
            ),
        widget=SequenceWidget(),
        default=default_idea_intentions,
        title=_('Idea intentions'),
        )

    amendment_intention = colander.SchemaNode(
        colander.Sequence(),
        colander.SchemaNode(
            colander.String(),
            name=_("Amendment intention")
            ),
        widget=SequenceWidget(),
        default=default_amendment_intentions,
        title=_('Amendment intentions'),
        )

    invitations = colander.SchemaNode(
        colander.Sequence(),
        omit(InvitationSchema(factory=Invitation,
                               editable=True,
                               name=_('Invitations')),['_csrf_token_']),
        title=_('List of invitation'),
        )

    working_groups = colander.SchemaNode(
        colander.Sequence(),
        omit(WorkingGroupSchema(factory=WorkingGroup,
                editable=True,
                name=_('Working group')),['_csrf_token_']),
        title=_('Working groups'),
        )

    organizations = colander.SchemaNode(
        colander.Sequence(),
        omit(OrganizationSchema(factory=Organization,
                editable=True,
                name=_('Organization')),['_csrf_token_']),
        title=_('Organizations'),
        )

    keywords = colander.SchemaNode(
        colander.Sequence(),
        omit(KeywordSchema(widget=LineWidget(),
                           factory=Keyword,
                           editable=True,
                           name='Keyword'),['_csrf_token_']),
        widget=TableWidget(min_len=1),
        title='Keywords',
        )

    ideas = colander.SchemaNode(
        colander.Sequence(),
        omit(IdeaSchema(factory=Idea,
                        name=_('Idea')),['_csrf_token_']),
        title=_('Ideas'),
        )

    participants_mini = colander.SchemaNode(
        colander.Integer(),
        title=_('Minimum number of participants for a working group'),
        default=3,
        )

    participants_maxi = colander.SchemaNode(
        colander.Integer(),
        title=_('Maximum number of participants for a working group'),
        default=12,
        )

    participations_maxi = colander.SchemaNode(
        colander.Integer(),
        title=_('Maximum number of working group by member'),
        default=5,
        )

    tokens_mini = colander.SchemaNode(
        colander.Integer(),
        title=_('Minimum number of tokens by member'),
        default=7,
        )

@content(
    'Root',
    icon='glyphicon glyphicon-home',
    after_create='after_create',
    )
@implementer(INovaIdeoApplication)
class NovaIdeoApplication(VisualisableElement, Application):
    name = renamer()
    working_groups = CompositeMultipleProperty('working_groups')
    proposals = CompositeMultipleProperty('proposals')
    organizations = CompositeMultipleProperty('organizations')
    invitations = CompositeMultipleProperty('invitations')
    ideas = CompositeMultipleProperty('ideas')
    keywords = CompositeMultipleProperty('keywords')
    correlations = CompositeMultipleProperty('correlations')

    def __init__(self, **kwargs):
        super(NovaIdeoApplication, self).__init__(**kwargs)
        self.title = 'NovaIdeo'
        self.participants_mini = 2
        self.participants_maxi = 12
        self.participations_maxi = 5
        self.tokens_mini = 7
        self.titles = default_titles
        self.comment_intentions = default_comment_intentions
        self.correlation_intentions = default_correlation_intentions
        self.idea_intentions = default_idea_intentions
        self.amendment_intentions = default_idea_intentions

    @property
    def keywords_ids(self):
        return dict([(k.title, k) for k in self.keywords])

    def get_keywords(self, keywords_ids):
        result = []
        newkeywords = []
        for k in keywords_ids:
            if k in self.keywords_ids.keys():
                result.append(self.keywords_ids[k])
            else:
                key = Keyword(title=k)
                newkeywords.append(key)

        return result, newkeywords
<|endoftext|>