Пример #1
0
class Monitor(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True, null=True)
    engine = models.CharField(max_length=32, default='prometheus')
    metadata = YAMLField(blank=True, null=True)
    status = models.CharField(max_length=32, default='active')

    def client(self):
        client_class = utils.get_module(self.engine, 'monitor')
        return client_class(**{
            'name': self.name,
            'engine': self.engine,
            'metadata': self.metadata
        })

    def widgets(self):
        return self.metadata.get('widget', {})

    def color(self):
        if self.status == 'active':
            return 'success'
        if self.status == 'error':
            return 'danger'
        if self.status == 'build':
            return 'info'
        else:
            return 'warning'

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name']
Пример #2
0
class Inventory(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True, null=True)
    engine = models.CharField(max_length=32, default='reclass')
    metadata = YAMLField(blank=True, null=True)
    status = models.CharField(max_length=32, default='unknown')

    def client(self):
        client_class = utils.get_module(self.engine, 'inventory')
        return client_class(**{
            'name': self.name,
            'engine': self.engine,
            'metadata': self.metadata
        })

    def class_list(self, resource=None):
        return self.client().class_list(resource=None)

    def inventory(self, resource=None):
        return self.client().inventory(resource=None)

    def resource_count(self, resource=None):
        return len(self.client().inventory(resource=None))

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "Inventories"
Пример #3
0
class Problem(RespectedOrder, models.Model):
    lesson = models.ForeignKey(Lesson, related_name='problems')
    slug = models.SlugField(verbose_name="Слаг для адресной строки")
    name = models.CharField(verbose_name="Название", max_length=255)
    description = models.TextField(verbose_name="Описание", default='', blank=True)
    test_data = YAMLField(verbose_name="Тесты", default='')

    class Meta:
        order_with_respect_to = 'lesson'
        unique_together = ('lesson', 'slug')
Пример #4
0
class TargetEntity(models.Model):
    name = models.CharField(max_length=30)
    specYaml = YAMLField(blank=True)
    board = models.ForeignKey(BoardEntity, on_delete=models.CASCADE)

    def get_spec(self):
        views = [view.specYaml for view in self.viewentity_set.all()]
        filters = [filter.specYaml for filter in self.filterentity_set.all()]
        source = {
            'type': 'intake',
            'uri': os.path.join(path, 'catalog.yml'),
            'dask': False
        }

        return {
            'name': self.name,
            'title': self.name,
            'source': source,
            'views': views,
            'filters': filters
        }

    def save(self, *args, **kwargs):
        self.saveSpec()
        super().save(*args, **kwargs)

    def saveSpec(self):
        views = self.get_spec()['views']
        filters = self.get_spec()['filters']
        source = self.get_spec()['source']
        title = self.get_spec()['title']
        name = self.get_spec()['name']
        p = {'name': name, 'title': title, 'source': source}
        if len(views) > 0:
            if views[0]:
                p['views'] = views
        if len(filters) > 0:
            if filters[0]:
                p['filters'] = filters

        spec = SpecYamlCreator(**p)
        self.specYaml = spec.to_yaml()
Пример #5
0
class Option(models.Model):
    DESTINATIONS = (
        (1, 'payment'),
        (2, 'donation'),
        (3, 'payment & donation'),
    )
    name = models.CharField(
        max_length=255, help_text=_('userfriendly name of the payment option'))
    institution = models.ForeignKey(Institution)
    provider = models.CharField(max_length=255,
                                choices=get_providers_choices())
    # description = models.TextField()
    settings = YAMLField(blank=True,
                         null=True,
                         help_text="check settings for each provider")
    currency = models.CharField(max_length=3, choices=CURRENCIES)
    destination = models.PositiveIntegerField(choices=DESTINATIONS)

    def get_provider(self, payment):
        Provider = provider_factory(self.provider)
        provider = Provider(dict(self.settings or {}), payment)
        return provider

    @property
    def has_automatic_provider(self):
        return self.provider in ['cash', 'bank_transfer']

    def check_settings(self):
        Provider = provider_factory(self.provider)
        return Provider.check_settings(self.settings)

    def clean(self):
        settings_errors = self.check_settings()
        if settings_errors:
            raise ValidationError(
                _('There errors in settings: %s' % ", ".join(settings_errors)))

    def __str__(self):
        return "%s" % self.name
Пример #6
0
class StudyCondition(models.Model):
    '''Groupings of participants within a study.'''
    study = models.ForeignKey('signalbox.Study', blank=True, null=True)
    users = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                   through='Membership')
    tag = models.SlugField(max_length=255, default="main")
    display_name = models.CharField(
        max_length=30,
        blank=True,
        null=True,
        help_text="""A label for this condition which can be shown to
        the Participant (e.g. a non-descriptive name used to identify a
        condition in an experimental session without breaking a blind.""",
    )
    weight = models.IntegerField(
        default=1,
        help_text="""Relative weights to allocate users to conditions""")
    scripts = models.ManyToManyField('signalbox.Script', blank=True)
    metadata = YAMLField(
        blank=True,
        null=True,
        help_text=
        """YAML meta data available describing this condition. Can be used on Questionnaires,
        e.g. to conditionally display questions.""")

    def expected_n(self):
        """Return the expected number of participants based on the total currently allocated to the parent study."""
        weights = [i.weight for i in self.study.studycondition_set.all()]
        w = self.weight / sum(weights)
        return self.study.membership_set.count() * w

    class Meta:
        ordering = ['study', 'tag']
        app_label = 'signalbox'

    def __unicode__(self):
        return "%s > %s " % (self.study.name, self.tag)
Пример #7
0
class Resource(models.Model):
    uid = models.CharField(max_length=511)
    name = models.CharField(max_length=511)
    monitor = models.ForeignKey(Monitor, on_delete=models.CASCADE)
    kind = models.CharField(max_length=32)
    size = models.IntegerField(default=1)
    metadata = YAMLField(blank=True, null=True)
    status = models.CharField(max_length=32, default='unknown')

    def __str__(self):
        return '{} {}'.format(self.kind, self.name)

    def color(self):
        if self.status == 'active':
            return 'success'
        if self.status == 'error':
            return 'danger'
        if self.status == 'build':
            return 'info'
        else:
            return 'warning'

    class Meta:
        ordering = ['name']
Пример #8
0
class Asker(models.Model):

    objects = AskerManager()

    def natural_key(self):
        return (self.slug, )

    allow_unauthenticated_download_of_anonymous_data = models.BooleanField(
        default=False)
    anonymous_download_token = ShortUUIDField(auto=True)

    name = models.CharField(max_length=255, null=True)

    slug = models.SlugField(max_length=128,
                            help_text="""To use in URLs etc""",
                            unique=True,
                            verbose_name="""Reference code""")

    success_message = models.TextField(
        default="Questionnaire complete.",
        help_text=
        """Message which appears in banner on users screen on completion of the  questionnaire."""
    )

    redirect_url = models.CharField(
        max_length=128,
        default="/profile/",
        help_text=""""URL to redirect to when Questionnaire is complete.""")

    show_progress = models.BooleanField(default=False,
                                        help_text="""Show a
            progress field in the header of each page.""")

    finish_on_last_page = models.BooleanField(
        default=False,
        help_text="""Mark the reply as complete
        when the user gets to the last page. NOTE this implies there should be not questions
        requiring input on the last page, or these values will never be saved."""
    )

    step_navigation = models.BooleanField(default=True,
                                          help_text="""Allow navigation
        to steps.""")

    steps_are_sequential = models.BooleanField(default=True,
                                               help_text="""Each page
        in the questionnaire must be completed before the next; if unchecked
        then respondents can skip around within the questionnaire and complete
        the pages 'out of order'.""")

    hide_menu = models.BooleanField(default=True)

    system_audio = YAMLField(blank=True,
                             help_text="""A mapping of slugs to text strings or
        urls which store audio files, for the system to play on errors etc. during IVR calls"""
                             )

    width = models.PositiveIntegerField(default=12)

    def get_phrase(self, key):
        if self.system_audio:
            return self.system_audio.get(key, IVR_SYSTEM_MESSAGES.get(key))
        else:
            return IVR_SYSTEM_MESSAGES.get(key, None)

    def anonymous_replies(self):
        from signalbox.models import Reply
        return Reply.objects.filter(asker=self)

    def anonymous_reply_stats(self):
        replies = self.anonymous_replies()
        return {
            'Complete total':
            replies.filter(complete=True).count(),
            'Complete past month':
            replies.filter(complete=True,
                           last_submit__lt=datetime.now() -
                           timedelta(days=30)).count(),
            'Incomplete total':
            replies.filter(complete=False).count(),
            'Incomplete past month':
            replies.filter(complete=False,
                           last_submit__lt=datetime.now() -
                           timedelta(days=30)).count(),
        }

    def used_in_studies(self):
        from signalbox.models import Study
        return Study.objects.filter(studycondition__scripts__asker=self)

    def used_in_scripts(self):
        from signalbox.models import Script
        return Script.objects.filter(asker=self)

    def used_in_study_conditions(self):
        """Return a queryset of the StudyConditions in which this Asker appears."""
        from signalbox.models import StudyCondition
        scripts = self.used_in_scripts()
        conds = set(StudyCondition.objects.filter(scripts__in=scripts))
        return conds

    def approximate_time_to_complete(self):
        """Returns the approximate number of minutes the asker will take to complete.
        Rounded to the nearest 5 minutes (with a minumum of 5 minutes)."""

        baseround = lambda x, base=5: int(base * round(float(x) / base))
        n_questions = Question.objects.filter(
            page__in=self.askpage_set.all()).count()
        mins = (n_questions * .5) * .9
        return max([5, baseround(mins, 5)])

    def scoresheets(self):
        return itertools.chain(
            *[i.scoresheets() for i in self.askpage_set.all()])

    def summary_scores(self, reply):
        answers = reply.answer_set.all()
        return {i.name: i.compute(answers) for i in self.scoresheets()}

    @contract
    def questions(self, reply=None):
        """All questions, filtered by previous answers if a reply is passed in, see methods on Page.
        :rtype: list
        """

        questionsbypage = [
            i.get_questions(reply=reply) for i in self.askpage_set.all()
        ]

        for i, pagelist in enumerate(questionsbypage):
            for q in pagelist:
                q.on_page = i

        questions = list(itertools.chain(*questionsbypage))
        return questions

    def first_page(self):
        return self.askpage_set.all()[0]

    def page_count(self):
        return self.askpage_set.all().count()

    def admin_edit_url(self):
        return admin_edit_url(self)

    def get_absolute_url(self):
        return reverse('preview_asker',
                       kwargs={
                           'asker_id': self.id,
                           'page_num': 0
                       })

    def get_anonymous_url(self, request):
        return reverse('start_anonymous_survey', kwargs={'asker_id': self.id})

    def json_export(self):
        """Export Asker and related objects as json.

        Export everything needed to recreate this questionnaire on
        another signalbox instance (or 3rd party system) with the
        exception of question assets."""

        _asdict = lambda object, fields: {
            i: str(supergetattr(object, i))
            for i in fields
        }

        pages = self.askpage_set.all()
        questionlists = [i.get_questions() for i in pages]
        questions = list(itertools.chain(*questionlists))

        choicesets = set([i.choiceset for i in questions if i.choiceset])
        choices = Choice.objects.filter(choiceset__in=choicesets)

        QUESTION_FIELDS = ('natural_key', 'variable_name', 'order', 'required',
                           'help_text', 'text', 'choiceset.pk', 'q_type',
                           'showif')
        CHOICESET_FIELDS = ('natural_key', 'name')
        CHOICE_FIELDS = ('choiceset.natural_key', 'is_default_value', 'order',
                         'label', 'score')

        qdicts = [_asdict(i, QUESTION_FIELDS) for i in questions]
        # give a consistent ordering to everything
        [d.update({'order': i}) for i, d in enumerate(qdicts)]

        output = {
            'meta': {
                'name': self.slug,
                'show_progress': self.show_progress,
                'generated': str(datetime.now()),
            },
            'questions': qdicts,
            'choicesets': [_asdict(i, CHOICESET_FIELDS) for i in choicesets],
            'choices': [_asdict(i, CHOICE_FIELDS) for i in choices],
            'scoresheets':
            [i.as_simplified_dict() for i in self.scoresheets()]
        }

        jsonstring = json.dumps(output, indent=4)

        return "{}".format(jsonstring)

    def reply_count(self):
        return self.reply_set.all().count()

    @contract
    def as_markdown(self):
        """A helper to convert an asker and associated models to markdown format.
        :rtype: string
        """

        _fields = "slug name steps_are_sequential redirect_url finish_on_last_page \
            show_progress success_message step_navigation system_audio width".split(
        )

        metayaml = yaml.safe_dump({i: getattr(self, i)
                                   for i in _fields},
                                  default_flow_style=False)

        _pages_questions = [(i.as_markdown(),
                             [j.as_markdown() for j in i.get_questions()])
                            for i in self.askpage_set.all()]
        qstrings = "\n\n".join(flatten(flatten(_pages_questions)))

        return "---\n" + metayaml + "---\n\n" + qstrings

    class Meta:
        permissions = (("can_preview", "Can preview surveys"), )
        verbose_name = "Questionnaire"
        app_label = "ask"
        ordering = ['name']

    def save(self, *args, **kwargs):
        # set defaults for system_audio if none exist
        if self.system_audio:
            if isinstance(self.system_audio, dict):
                IVR_SYSTEM_MESSAGES.update(self.system_audio)
            self.system_audio = IVR_SYSTEM_MESSAGES

        super(Asker, self).save(*args, **kwargs)

    def __unicode__(self):
        return "{}".format(self.name or self.slug)
Пример #9
0
class FlowRuleException(models.Model):
    flow_id = models.CharField(max_length=200, blank=False, null=False)
    participation = models.ForeignKey(Participation, db_index=True)
    expiration = models.DateTimeField(blank=True, null=True)

    creator = models.ForeignKey(User, null=True)
    creation_time = models.DateTimeField(default=now, db_index=True)

    comment = models.TextField(blank=True, null=True)

    kind = models.CharField(max_length=50,
                            blank=False,
                            null=False,
                            choices=FLOW_RULE_KIND_CHOICES)
    rule = YAMLField(blank=False, null=False)
    active = models.BooleanField(default=True)

    def __unicode__(self):
        return "%s exception for '%s' to '%s' in '%s'" % (
            self.kind, self.participation.user, self.flow_id,
            self.participation.course)

    def clean(self):
        if (self.kind == flow_rule_kind.grading
                and self.expiration is not None):
            raise ValidationError("grading rules may not expire")

        from course.validation import (ValidationError as
                                       ContentValidationError,
                                       validate_session_start_rule,
                                       validate_session_access_rule,
                                       validate_session_grading_rule,
                                       ValidationContext)
        from course.content import (get_course_repo, get_course_commit_sha,
                                    get_flow_desc)

        from relate.utils import dict_to_struct
        rule = dict_to_struct(self.rule)

        repo = get_course_repo(self.participation.course)
        commit_sha = get_course_commit_sha(self.participation.course,
                                           self.participation)
        ctx = ValidationContext(repo=repo, commit_sha=commit_sha)

        flow_desc = get_flow_desc(repo, self.participation.course,
                                  self.flow_id, commit_sha)

        tags = None
        if hasattr(flow_desc, "rules"):
            tags = getattr(flow_desc.rules, "tags", None)

        try:
            if self.kind == flow_rule_kind.start:
                validate_session_start_rule(ctx, unicode(self), rule, tags)
            elif self.kind == flow_rule_kind.access:
                validate_session_access_rule(ctx, unicode(self), rule, tags)
            elif self.kind == flow_rule_kind.grading:
                validate_session_grading_rule(ctx, unicode(self), rule, tags)
            else:
                raise ValidationError("invalid rule kind: " + self.kind)

        except ContentValidationError as e:
            raise ValidationError("invalid existing_session_rules: " + str(e))