Example #1
0
    def test_identical_when_drivers_unmatched(self):
        driver1 = CodeResourceRevision()
        driver2 = CodeResourceRevision()
        user = User()
        m1 = Method(revision_name='A', driver=driver1, user=user)
        for i in range(2):
            inp = m1.inputs.create(dataset_name='a_in_{}'.format(i),
                                   dataset_idx=i + 1)
            inp.transformationinput = inp
        for i in range(3):
            out = m1.outputs.create(dataset_name='a_out_{}'.format(i),
                                    dataset_idx=i + 1)
            out.transformationoutput = out

        m2 = Method(revision_name='B', driver=driver2, user=user)
        for i in range(2):
            inp = m2.inputs.create(dataset_name='b_in_{}'.format(i),
                                   dataset_idx=i + 1)
            inp.transformationinput = inp
        for i in range(3):
            out = m2.outputs.create(dataset_name='b_in_{}'.format(i),
                                    dataset_idx=i + 1)
            out.transformationoutput = out

        self.assertFalse(m1.is_identical(m2))
Example #2
0
    def setUp(self):
        super(CodeResourceViewMockTests, self).setUp()
        patcher = mocked_relations(KiveUser,
                                   CodeResource,
                                   CodeResourceRevision,
                                   User,
                                   Group)
        patcher.start()
        self.addCleanup(patcher.stop)

        # noinspection PyUnresolvedReferences
        patchers = [patch.object(CodeResource._meta,
                                 'default_manager',
                                 CodeResource.objects),
                    patch.object(CodeResourceRevision._meta,
                                 'default_manager',
                                 CodeResource.objects)]

        def dummy_save(r):
            r.id = id(r)

        # noinspection PyUnresolvedReferences
        patchers.append(patch.object(CodeResource, 'save', dummy_save))
        patcher = PatcherChain(patchers)
        patcher.start()
        self.addCleanup(patcher.stop)

        self.client = self.create_client()
        self.dev_group = Group(pk=groups.DEVELOPERS_PK)
        self.everyone = Group(pk=groups.EVERYONE_PK)
        Group.objects.add(self.dev_group, self.everyone)
        self.user = kive_user()
        self.user.groups.add(self.dev_group)
        self.content_file = ContentFile('some text', 'existing.txt')
        self.code_resource = CodeResource(pk='99',
                                          user=self.user,
                                          name='existing',
                                          filename='existing.txt')
        self.code_resource._state.adding = False

        self.other_user = User(pk=5)
        self.other_code_resource = CodeResource(pk='150', user=self.other_user)
        CodeResource.objects.add(self.code_resource, self.other_code_resource)

        self.code_resource_revision = CodeResourceRevision(
            pk='199',
            user=self.user,
            content_file=self.content_file)
        self.code_resource_revision.coderesource = self.code_resource
        self.other_code_resource_revision = CodeResourceRevision(
            pk='200',
            user=self.other_user)
        self.other_code_resource_revision.coderesource = self.other_code_resource
        self.other_code_resource.revisions.add(self.other_code_resource_revision)
        CodeResourceRevision.objects.add(self.code_resource_revision,
                                         self.other_code_resource_revision)
        k = KiveUser(pk=users.KIVE_USER_PK)
        k.groups.add(self.dev_group)
        KiveUser.objects.add(k)
Example #3
0
    def __init__(self, data=None, user=None, initial=None, *args, **kwargs):
        super(MethodDependencyForm, self).__init__(data, initial=initial, *args, **kwargs)

        eligible_crs = _get_code_resource_list(user)
        self.fields['coderesource'].choices = eligible_crs

        # Re-populate drop-downs before rendering if possible.
        populator = None
        if data is not None:
            populator = data
        elif initial is not None:
            populator = initial

        if populator is not None:
            # Re-populate drop-downs before rendering the template.
            cr_pk = populator["coderesource"]

            # The first entry of eligible_crs is ("", "--- CodeResource ---") so we skip it.
            if int(cr_pk) not in [int(x[0]) for x in eligible_crs[1:]]:
                raise Http404(
                    "CodeResource with ID {} used in dependency definition is invalid".format(
                        populator["coderesource"]))

            rev = CodeResourceRevision.filter_by_user(user).filter(coderesource__pk=cr_pk)
            self.fields['revisions'].widget.choices = [
                (x.pk, x.revision_name) for x in rev]
            if "revisions" in populator:
                try:
                    assert "coderesource" in populator
                    assert int(populator["revisions"]) in (x.pk for x in rev)
                except AssertionError as e:
                    raise Http404(e)
Example #4
0
    def test_no_outputs_checkOutputIndices_good(self):
        """Test output index check, one well-indexed output case."""
        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())

        foo.check_output_indices()
        foo.clean()
Example #5
0
 def setUp(self):
     patcher = mocked_relations(Method, MethodDependency, Transformation)
     patcher.start()
     self.addCleanup(patcher.stop)
     driver = CodeResourceRevision(
         coderesource=CodeResource(filename='driver.py'))
     self.method = Method(driver=driver, family=MethodFamily())
     self.dependency = self.add_dependency('helper.py')
Example #6
0
def resource_revision_add(request, pk):
    """
    Add a code resource revision.  The form will initially be populated with values of the last
    revision to this code resource.
    """
    t = loader.get_template('method/resource_revision_add.html')
    c = {}
    creating_user = request.user
    parent_revision = CodeResourceRevision.check_accessible(pk, creating_user)
    coderesource = parent_revision.coderesource

    if request.method == 'POST':
        # Use forms here, just as in resource_add.  Again note that entries of dep_forms may be None.
        revision_form = CodeResourceRevisionForm(request.POST, request.FILES)
        if not revision_form.is_valid():
            c.update({
                'revision_form': revision_form,
                'parent_revision': parent_revision,
                'coderesource': coderesource
            })
            return HttpResponse(t.render(c, request))

        try:
            _make_crv(request.FILES.get('content_file', None),
                      creating_user,
                      revision_form,
                      parent_revision=parent_revision)
        except ValidationError:
            # The forms have all been updated with the appropriate errors.
            c.update({
                'revision_form': revision_form,
                'parent_revision': parent_revision,
                'coderesource': coderesource
            })
            return HttpResponse(
                t.render(c, request)
            )  # CodeResourceRevision object required for next steps

        # Success; return to the resources page.
        return HttpResponseRedirect('/resources')

    # Having reached here, we know that this CR is being revised.  Return a form pre-populated
    # with default info.
    parent_users_allowed = [
        x.username for x in parent_revision.users_allowed.all()
    ]
    parent_groups_allowed = [
        x.name for x in parent_revision.groups_allowed.all()
    ]
    crv_form = CodeResourceRevisionForm(
        initial={"permissions": [parent_users_allowed, parent_groups_allowed]})

    c.update({
        'revision_form': crv_form,
        'parent_revision': parent_revision,
        'coderesource': coderesource
    })
    return HttpResponse(t.render(c, request))
Example #7
0
def resource_revision_add(request, pk):
    """
    Add a code resource revision.  The form will initially be populated with values of the last
    revision to this code resource.
    """
    t = loader.get_template('method/resource_revision_add.html')
    c = {}
    creating_user = request.user
    parent_revision = CodeResourceRevision.check_accessible(pk, creating_user)
    coderesource = parent_revision.coderesource

    if request.method == 'POST':
        # Use forms here, just as in resource_add.  Again note that entries of dep_forms may be None.
        revision_form = CodeResourceRevisionForm(request.POST, request.FILES)
        if not revision_form.is_valid():
            c.update({
                'revision_form': revision_form,
                'parent_revision': parent_revision,
                'coderesource': coderesource
            })
            return HttpResponse(t.render(c, request))

        try:
            _make_crv(request.FILES.get('content_file', None), creating_user, revision_form,
                      parent_revision=parent_revision)
        except ValidationError:
            # The forms have all been updated with the appropriate errors.
            c.update(
                {
                    'revision_form': revision_form,
                    'parent_revision': parent_revision,
                    'coderesource': coderesource
                })
            return HttpResponse(t.render(c, request))  # CodeResourceRevision object required for next steps

        # Success; return to the resources page.
        return HttpResponseRedirect('/resources')

    # Having reached here, we know that this CR is being revised.  Return a form pre-populated
    # with default info.
    parent_users_allowed = [x.username for x in parent_revision.users_allowed.all()]
    parent_groups_allowed = [x.name for x in parent_revision.groups_allowed.all()]
    crv_form = CodeResourceRevisionForm(
        initial={
            "permissions": [parent_users_allowed, parent_groups_allowed]
        }
    )

    c.update(
        {
            'revision_form': crv_form,
            'parent_revision': parent_revision,
            'coderesource': coderesource
        }
    )
    return HttpResponse(t.render(c, request))
Example #8
0
    def test_method_revise_access_denied(self):
        """ Hides ungranted code revisions. """
        revision1 = CodeResourceRevision(pk=101,
                                         revision_name='alpha',
                                         revision_number=1,
                                         user=self.user)
        revision2 = CodeResourceRevision(pk=102,
                                         revision_name='beta',
                                         revision_number=2,
                                         user=self.other_user)
        self.driver.coderesource.revisions.add(revision1, revision2)

        response = self.client.get(reverse('method_revise',
                                           kwargs=dict(pk='199')))

        self.assertEqual(200, response.status_code)
        revisions = response.context['method_form']['driver_revisions']
        self.assertEqual([('101', '1: alpha')],
                         revisions.field.widget.choices)
Example #9
0
    def test_one_valid_output_checkOutputIndices_good(self):
        """Test output index check, one well-indexed output case."""

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        out = foo.outputs.create(dataset_idx=1)
        out.transformationoutput = out

        foo.check_output_indices()
        foo.clean()
Example #10
0
    def test_many_valid_outputs_scrambled_checkOutputIndices_good(self):
        """Test output index check, well-indexed multi-output (scrambled order) case."""

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        for i in (3, 1, 2):
            out = foo.outputs.create(dataset_idx=i)
            out.transformationoutput = out

        foo.check_output_indices()
        foo.clean()
Example #11
0
    def test_no_inputs_checkInputIndices_good(self):
        """
        Method with no inputs defined should have
        check_input_indices() return with no exception.
        """

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())

        # check_input_indices() should not raise a ValidationError
        foo.check_input_indices()
        foo.clean()
Example #12
0
    def download(self, request, pk=None):
        """
        Download the file pointed to by this CodeResourceRevision.
        """
        accessible_revisions = CodeResourceRevision.filter_by_user(request.user)
        if not accessible_revisions.filter(pk=pk).exists():
            return Response(None, status=status.HTTP_404_NOT_FOUND)

        revision = self.get_object()
        if not revision.content_file:
            return Response({"errors": "This CodeResourceRevision has no content file."},
                            status=status.HTTP_403_FORBIDDEN)

        return build_download_response(revision.content_file)
Example #13
0
    def test_single_valid_input_checkInputIndices_good(self):
        """
        Method with a single, 1-indexed input should have
        check_input_indices() return with no exception.
        """

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        inp = foo.inputs.create(dataset_idx=1)
        inp.transformationinput = inp

        # check_input_indices() should not raise a ValidationError
        foo.check_input_indices()
        foo.clean()
Example #14
0
    def test_many_ordered_valid_inputs_checkInputIndices_good(self):
        """
        Test check_input_indices on a method with several inputs,
        correctly indexed and in order.
        """

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        for i in range(3):
            inp = foo.inputs.create(dataset_idx=i + 1)
            inp.transformationinput = inp

        # check_input_indices() should not raise a ValidationError
        foo.check_input_indices()
        foo.clean()
Example #15
0
def resource_revision_view(request, pk):
    revision = CodeResourceRevision.check_accessible(pk, request.user)
    addable_users, addable_groups = revision.other_users_groups()

    if request.method == 'POST':
        # We are attempting to update the CodeResourceRevision's metadata/permissions.
        revision_form = CodeResourceRevisionDetailsForm(
            request.POST,
            addable_users=addable_users,
            addable_groups=addable_groups,
            instance=revision)

        if revision_form.is_valid():
            try:
                revision.revision_name = revision_form.cleaned_data[
                    "revision_name"]
                revision.revision_desc = revision_form.cleaned_data[
                    "revision_desc"]
                revision.save()
                revision.grant_from_json(
                    revision_form.cleaned_data["permissions"])
                revision.clean()

                # Success -- go back to the CodeResource page.
                return HttpResponseRedirect('/resource_revisions/{}'.format(
                    revision.coderesource.pk))
            except (AttributeError, ValidationError, ValueError) as e:
                LOGGER.exception(e.message)
                revision_form.add_error(None, e)

    else:
        revision_form = CodeResourceRevisionDetailsForm(
            addable_users=addable_users,
            addable_groups=addable_groups,
            initial={
                "revision_name": revision.revision_name,
                "revision_desc": revision.revision_desc
            })

    t = loader.get_template("method/resource_revision_view.html")
    c = {
        "revision": revision,
        "revision_form": revision_form,
        "is_owner": revision.user == request.user,
        "is_admin": admin_check(request.user)
    }
    return HttpResponse(t.render(c, request))
Example #16
0
    def setUp(self):
        super(MethodViewMockTests, self).setUp()
        patcher = mocked_relations(KiveUser,
                                   MethodFamily,
                                   Method,
                                   CodeResource,
                                   CodeResourceRevision,
                                   CompoundDatatype,
                                   ContainerFamily,
                                   Container,
                                   Transformation,
                                   TransformationInput,
                                   TransformationOutput,
                                   User,
                                   Group)
        patcher.start()
        self.addCleanup(patcher.stop)

        # noinspection PyUnresolvedReferences
        patcher = patch.object(MethodFamily._meta,
                               'default_manager',
                               MethodFamily.objects)
        patcher.start()
        self.addCleanup(patcher.stop)

        self.client = self.create_client()
        self.dev_group = Group(pk=groups.DEVELOPERS_PK)
        self.everyone = Group(pk=groups.EVERYONE_PK)
        Group.objects.add(self.dev_group, self.everyone)
        self.user = kive_user()
        self.user.groups.add(self.dev_group)
        self.other_user = User(pk=5)

        self.method_family = MethodFamily(pk='99',
                                          user=self.user)
        MethodFamily.objects.add(self.method_family)

        self.driver = CodeResourceRevision(user=self.user)
        self.driver.pk = 1337  # needed for viewing a method
        self.driver.coderesource = CodeResource()
        self.method = Method(pk='199', user=self.user)
        self.method.driver = self.driver
        self.method.family = self.method_family
        Method.objects.add(self.method)
        KiveUser.objects.add(KiveUser(pk=users.KIVE_USER_PK))
Example #17
0
def resource_revision_view(request, pk):
    revision = CodeResourceRevision.check_accessible(pk, request.user)
    addable_users, addable_groups = revision.other_users_groups()

    if request.method == 'POST':
        # We are attempting to update the CodeResourceRevision's metadata/permissions.
        revision_form = CodeResourceRevisionDetailsForm(
            request.POST,
            addable_users=addable_users,
            addable_groups=addable_groups,
            instance=revision
        )

        if revision_form.is_valid():
            try:
                revision.revision_name = revision_form.cleaned_data["revision_name"]
                revision.revision_desc = revision_form.cleaned_data["revision_desc"]
                revision.save()
                revision.grant_from_json(revision_form.cleaned_data["permissions"])
                revision.clean()

                # Success -- go back to the CodeResource page.
                return HttpResponseRedirect('/resource_revisions/{}'.format(revision.coderesource.pk))
            except (AttributeError, ValidationError, ValueError) as e:
                LOGGER.exception(e.message)
                revision_form.add_error(None, e)

    else:
        revision_form = CodeResourceRevisionDetailsForm(
            addable_users=addable_users,
            addable_groups=addable_groups,
            initial={
                "revision_name": revision.revision_name,
                "revision_desc": revision.revision_desc
            }
        )

    t = loader.get_template("method/resource_revision_view.html")
    c = {
        "revision": revision,
        "revision_form": revision_form,
        "is_owner": revision.user == request.user,
        "is_admin": admin_check(request.user)
    }
    return HttpResponse(t.render(c, request))
Example #18
0
    def test_one_invalid_output_checkOutputIndices_bad(self):
        """Test output index check, one badly-indexed output case."""

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        out = foo.outputs.create(dataset_idx=4)
        out.transformationoutput = out

        self.assertRaisesRegexp(
            ValidationError,
            "Outputs are not consecutively numbered starting from 1",
            foo.check_output_indices)

        self.assertRaisesRegexp(
            ValidationError,
            "Outputs are not consecutively numbered starting from 1",
            foo.clean)
Example #19
0
    def __init__(self, *args, **kwargs):
        super(MethodSerializer, self).__init__(*args, **kwargs)
        request = self.context.get("request")
        if request is not None:
            curr_user = request.user

            # Set the querysets of the related model fields.
            revision_parent_field = self.fields["revision_parent"]
            revision_parent_field.queryset = Method.filter_by_user(curr_user)

            family_field = self.fields["family"]
            family_field.queryset = MethodFamily.filter_by_user(curr_user)

            driver_field = self.fields["driver"]
            driver_field.queryset = CodeResourceRevision.filter_by_user(
                curr_user)

            docker_field = self.fields["docker_image"]
            docker_field.queryset = DockerImage.filter_by_user(curr_user)
Example #20
0
    def test_many_nonconsective_inputs_scrambled_checkInputIndices_bad(self):
        """Test input index check, badly-indexed multi-input case."""

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        for i in (2, 6, 1):
            inp = foo.inputs.create(dataset_idx=i)
            inp.transformationinput = inp

        self.assertRaisesRegexp(
            ValidationError,
            "Inputs are not consecutively numbered starting from 1",
            foo.check_input_indices)

        self.assertRaisesRegexp(
            ValidationError,
            "Inputs are not consecutively numbered starting from 1",
            foo.clean)
Example #21
0
    def test_one_invalid_input_checkInputIndices_bad(self):
        """
        Test input index check, one badly-indexed input case.
        """

        driver = CodeResourceRevision(coderesource=CodeResource())

        foo = Method(driver=driver, family=MethodFamily())
        inp = foo.inputs.create(dataset_idx=4)
        inp.transformationinput = inp

        # check_input_indices() should raise a ValidationError
        self.assertRaisesRegexp(
            ValidationError,
            "Inputs are not consecutively numbered starting from 1",
            foo.check_input_indices)

        self.assertRaisesRegexp(
            ValidationError,
            "Inputs are not consecutively numbered starting from 1",
            foo.clean)
Example #22
0
    def __init__(self, data=None, user=None, initial=None, *args, **kwargs):
        super(MethodDependencyForm, self).__init__(data,
                                                   initial=initial,
                                                   *args,
                                                   **kwargs)

        eligible_crs = _get_code_resource_list(user)
        self.fields['coderesource'].choices = eligible_crs

        # Re-populate drop-downs before rendering if possible.
        populator = None
        if data is not None:
            populator = data
        elif initial is not None:
            populator = initial

        if populator is not None:
            # Re-populate drop-downs before rendering the template.
            cr_pk = populator["coderesource"]

            # The first entry of eligible_crs is ("", "--- CodeResource ---") so we skip it.
            if int(cr_pk) not in [int(x[0]) for x in eligible_crs[1:]]:
                raise Http404(
                    "CodeResource with ID {} used in dependency definition is invalid"
                    .format(populator["coderesource"]))

            rev = CodeResourceRevision.filter_by_user(user).filter(
                coderesource__pk=cr_pk)
            self.fields['revisions'].widget.choices = [(x.pk, x.revision_name)
                                                       for x in rev]
            if "revisions" in populator:
                try:
                    assert "coderesource" in populator
                    assert int(populator["revisions"]) in (x.pk for x in rev)
                except AssertionError as e:
                    raise Http404(e)
Example #23
0
    def create(self, validated_data):
        """
        Create a CodeResourceRevision from the validated deserialized data.

        Note that no cleaning occurs here.  That will fall to the calling method.
        """
        crr_data = validated_data
        users_allowed = crr_data.pop(
            "users_allowed") if "users_allowed" in crr_data else []
        groups_allowed = crr_data.pop(
            "groups_allowed") if "groups_allowed" in crr_data else []

        with transaction.atomic():
            crr = CodeResourceRevision(**crr_data)
            crr.clean()  # this sets the MD5
            crr.save()
            crr.users_allowed.add(*users_allowed)
            crr.groups_allowed.add(*groups_allowed)

        return crr
Example #24
0
def _make_crv(file_in_memory,
              creating_user,
              crv_form,
              parent_revision=None,
              code_resource=None):
    """
    Helper that creates a CodeResourceRevision (and a CodeResource as well if appropriate).
    """
    assert isinstance(crv_form, (CodeResourcePrototypeForm, CodeResourceRevisionForm))
    # If parent_revision is specified, we are only making a CodeResourceRevision and not its parent CodeResource.
    assert not (parent_revision is None and isinstance(crv_form, CodeResourceRevision))

    cr_filename = "" if file_in_memory is None else file_in_memory.name

    if code_resource is None and parent_revision is not None:
        code_resource = parent_revision.coderesource
    if code_resource is None:
        # crv_form is a CodeResourcePrototypeForm.
        code_resource = CodeResource(
            name=crv_form.cleaned_data['resource_name'],
            description=crv_form.cleaned_data['resource_desc'],
            filename=cr_filename,
            user=creating_user
        )
        try:
            code_resource.full_clean()
            # Skip the clean until later; after all, we're protected by a transaction here.
            code_resource.save()
        except ValidationError as e:
            crv_form.add_error('content_file', e.error_dict.get('filename', []))
            crv_form.add_error('resource_name', e.error_dict.get('name', []))
            crv_form.add_error('resource_desc', e.error_dict.get('description', []))
            raise e

        code_resource.grant_from_json(crv_form.cleaned_data["permissions"])

        rev_name = "Prototype"
        rev_desc = crv_form.cleaned_data["resource_desc"]
    else:
        rev_name = crv_form.cleaned_data["revision_name"]
        rev_desc = crv_form.cleaned_data["revision_desc"]

    # Modify actual filename prior to saving revision object.
    if file_in_memory is not None:
        file_in_memory.name += '_' + datetime.now().strftime('%Y%m%d%H%M%S')

    revision = CodeResourceRevision(
        revision_parent=parent_revision,
        revision_name=rev_name,
        revision_desc=rev_desc,
        coderesource=code_resource,
        content_file=file_in_memory,
        user=creating_user
    )
    # This sets the MD5.

    try:
        revision.clean()
    except ValidationError as e:
        crv_form.add_error(None, e)
        raise e

    revision.save()
    revision.grant_from_json(crv_form.cleaned_data["permissions"])

    try:
        code_resource.full_clean()
        revision.full_clean()
    except ValidationError as e:
        crv_form.add_error(None, e)
        raise e

    return revision
Example #25
0
def resource_revisions(request, pk):
    """
    Display a list of all revisions of a specific Code Resource in database.
    """
    coderesource = CodeResource.check_accessible(pk, request.user)

    addable_users, addable_groups = coderesource.other_users_groups()

    if request.method == 'POST':
        # We are attempting to update the CodeResource's metadata/permissions.
        resource_form = CodeResourceDetailsForm(
            request.POST,
            addable_users=addable_users,
            addable_groups=addable_groups,
            instance=coderesource
        )

        if resource_form.is_valid():
            try:
                coderesource.name = resource_form.cleaned_data["name"]
                coderesource.description = resource_form.cleaned_data["description"]
                coderesource.clean()
                coderesource.save()
                coderesource.grant_from_json(resource_form.cleaned_data["permissions"])

                # Success -- go back to the resources page.
                return HttpResponseRedirect('/resources')
            except (AttributeError, ValidationError, ValueError) as e:
                LOGGER.exception(e.message)
                resource_form.add_error(None, e)

    else:
        resource_form = CodeResourceDetailsForm(
            addable_users=addable_users,
            addable_groups=addable_groups,
            initial={"name": coderesource.name, "description": coderesource.description}
        )

    revisions = CodeResourceRevision.filter_by_user(
        request.user,
        queryset=coderesource.revisions.all()).order_by('-revision_number')
    if len(revisions) == 0:
        # Go to the resource_revision_add page to create a first revision.
        t = loader.get_template('method/resource_revision_add.html')
        crv_form = CodeResourceRevisionForm()

        c = {
            'revision_form': crv_form,
            'parent_revision': None,
            'coderesource': coderesource,
        }
        return HttpResponse(t.render(c, request))

    # Load template, setup context
    t = loader.get_template('method/resource_revisions.html')
    c = {
        'coderesource': coderesource,
        "resource_form": resource_form,
        'revisions': revisions,
        'is_admin': admin_check(request.user),
        "is_owner": request.user == coderesource.user
    }
    return HttpResponse(t.render(c, request))
Example #26
0
def method_revise(request, pk):
    """
    Add a revision of an existing Method.  revision_parent is defined by the
    previous version.
    """
    t = loader.get_template('method/method.html')
    c = {}
    creating_user = request.user

    # Retrieve the most recent member of this Method's family.
    parent_method = Method.check_accessible(pk, creating_user)
    family = parent_method.family

    # Retrieve the most recent revision of the corresponding CR.
    parent_revision = parent_method.driver
    if not parent_revision:
        this_code_resource = None
        all_revisions = []
    else:
        this_code_resource = parent_revision.coderesource
        # Filter the available revisions by user.
        all_revisions = CodeResourceRevision.filter_by_user(
            creating_user,
            queryset=this_code_resource.revisions.all()).order_by(
                '-revision_DateTime')

    parent_container = parent_method.container
    if not parent_container:
        this_container_family = None
        all_containers = []
    else:
        this_container_family = parent_container.family
        all_containers = Container.filter_by_user(
            creating_user, queryset=this_container_family.containers.all())

    if request.method == 'POST':
        # Because there is no CodeResource specified, the second value is of type MethodReviseForm.
        family_form, method_revise_form,\
            dep_forms, input_form_tuples,\
            output_form_tuples, _ = create_method_forms(request.POST, creating_user, family=family)
        if not _method_forms_check_valid(family_form, method_revise_form,
                                         dep_forms, input_form_tuples,
                                         output_form_tuples):
            # Bail out now if there are any problems.
            c.update({
                'coderesource': this_code_resource,
                'containerfamily': this_container_family,
                'method_revise_form': method_revise_form,
                'dep_forms': dep_forms,
                'input_forms': input_form_tuples,
                'output_forms': output_form_tuples,
                'family': family,
                'family_form': family_form,
                'parent': parent_method,
                'docker_default': DockerImage.DEFAULT_IMAGE
            })
            return HttpResponse(t.render(c, request))

        # Next, attempt to build the Method and add it to family.
        create_method_from_forms(family_form,
                                 method_revise_form,
                                 dep_forms,
                                 input_form_tuples,
                                 output_form_tuples,
                                 creating_user,
                                 family=family,
                                 parent_method=parent_method)
        if _method_forms_check_valid(family_form, method_revise_form,
                                     dep_forms, input_form_tuples,
                                     output_form_tuples):
            # Success!
            return HttpResponseRedirect('/methods/{}'.format(family.pk))

    else:
        # Initialize forms with values of parent Method.
        family_form = MethodFamilyForm({
            "name": family.name,
            "description": family.description
        })
        parent_users_allowed = [
            x.username for x in parent_method.users_allowed.all()
        ]
        parent_groups_allowed = [
            x.name for x in parent_method.groups_allowed.all()
        ]
        method_revise_form = MethodReviseForm(
            initial={
                "revision_desc": parent_method.revision_desc,
                "driver_revisions": parent_revision and parent_revision.pk,
                "docker_image": parent_method.docker_image_id,
                "reusable": parent_method.reusable,
                "threads": parent_method.threads,
                "memory": parent_method.memory,
                "permissions": [parent_users_allowed, parent_groups_allowed]
            })

        dependencies = parent_method.dependencies.all()
        dep_forms = []
        for i, dependency in enumerate(dependencies):
            its_crv = dependency.requirement
            its_cr = its_crv.coderesource
            dep_form = MethodDependencyForm(user=creating_user,
                                            auto_id='id_%s_' + str(i),
                                            initial={
                                                'coderesource': its_cr.pk,
                                                'revisions': its_crv.pk,
                                                'path': dependency.path,
                                                'filename': dependency.filename
                                            })
            dep_forms.append(dep_form)
        # If the parent Method has no dependencies, add a blank form.
        if len(dep_forms) == 0:
            dep_forms.append(
                MethodDependencyForm(user=creating_user, auto_id='id_%s_0'))

        xput_forms = []
        inputs = parent_method.inputs.order_by("dataset_idx")
        outputs = parent_method.outputs.order_by("dataset_idx")
        for xput_type, xputs in (("in", inputs), ("out", outputs)):
            forms = []
            for xput in xputs:
                tx_form = TransformationXputForm(auto_id='id_%s_{}_{}'.format(
                    xput_type, len(forms)),
                                                 initial={
                                                     'dataset_name':
                                                     xput.dataset_name,
                                                     'dataset_idx':
                                                     xput.dataset_idx
                                                 })
                if xput.has_structure:
                    structure = xput.structure
                    xs_form = XputStructureForm(
                        user=creating_user,
                        auto_id='id_%s_{}_{}'.format(xput_type, len(forms)),
                        initial={
                            'compounddatatype': structure.compounddatatype.id,
                            'min_row': structure.min_row,
                            'max_row': structure.max_row
                        })
                else:
                    xs_form = XputStructureForm(
                        user=creating_user,
                        auto_id='id_%s_{}_{}'.format(xput_type, len(forms)),
                        initial={'compounddatatype': '__raw__'})

                forms.append((tx_form, xs_form))
            xput_forms.append(forms)

        input_form_tuples, output_form_tuples = xput_forms
        # if previous Method has no inputs, provide blank forms
        if len(input_form_tuples) == 0:
            tx_form = TransformationXputForm(auto_id='id_%s_in_0')
            xs_form = XputStructureForm(user=creating_user,
                                        auto_id='id_%s_in_0')
            input_form_tuples.append((tx_form, xs_form))

    method_revise_form.fields['driver_revisions'].widget.choices = [
        (str(x.id), '{}: {}'.format(x.revision_number, x.revision_name))
        for x in all_revisions
    ]
    method_revise_form.fields['container'].widget.choices = [
        (str(x.id), x.tag) for x in all_containers
    ]
    c.update({
        'coderesource': this_code_resource,
        'containerfamily': this_container_family,
        'method_form': method_revise_form,
        'dep_forms': dep_forms,
        'input_forms': input_form_tuples,
        'output_forms': output_form_tuples,
        'family': family,
        'family_form': family_form,
        'parent': parent_method,
        'docker_default': DockerImage.DEFAULT_IMAGE
    })
    return HttpResponse(t.render(c, request))
Example #27
0
def resource_revisions(request, pk):
    """
    Display a list of all revisions of a specific Code Resource in database.
    """
    coderesource = CodeResource.check_accessible(pk, request.user)

    addable_users, addable_groups = coderesource.other_users_groups()

    if request.method == 'POST':
        # We are attempting to update the CodeResource's metadata/permissions.
        resource_form = CodeResourceDetailsForm(request.POST,
                                                addable_users=addable_users,
                                                addable_groups=addable_groups,
                                                instance=coderesource)

        if resource_form.is_valid():
            try:
                coderesource.name = resource_form.cleaned_data["name"]
                coderesource.description = resource_form.cleaned_data[
                    "description"]
                coderesource.clean()
                coderesource.save()
                coderesource.grant_from_json(
                    resource_form.cleaned_data["permissions"])

                # Success -- go back to the resources page.
                return HttpResponseRedirect('/resources')
            except (AttributeError, ValidationError, ValueError) as e:
                LOGGER.exception(e.message)
                resource_form.add_error(None, e)

    else:
        resource_form = CodeResourceDetailsForm(addable_users=addable_users,
                                                addable_groups=addable_groups,
                                                initial={
                                                    "name":
                                                    coderesource.name,
                                                    "description":
                                                    coderesource.description
                                                })

    revisions = CodeResourceRevision.filter_by_user(
        request.user,
        queryset=coderesource.revisions.all()).order_by('-revision_number')
    if len(revisions) == 0:
        # Go to the resource_revision_add page to create a first revision.
        t = loader.get_template('method/resource_revision_add.html')
        crv_form = CodeResourceRevisionForm()

        c = {
            'revision_form': crv_form,
            'parent_revision': None,
            'coderesource': coderesource,
        }
        return HttpResponse(t.render(c, request))

    # Load template, setup context
    t = loader.get_template('method/resource_revisions.html')
    c = {
        'coderesource': coderesource,
        "resource_form": resource_form,
        'revisions': revisions,
        'is_admin': admin_check(request.user),
        "is_owner": request.user == coderesource.user
    }
    return HttpResponse(t.render(c, request))
Example #28
0
def method_revise(request, pk):
    """
    Add a revision of an existing Method.  revision_parent is defined by the
    previous version.
    """
    t = loader.get_template('method/method.html')
    c = {}
    creating_user = request.user

    # Retrieve the most recent member of this Method's family.
    parent_method = Method.check_accessible(pk, creating_user)
    family = parent_method.family

    # Retrieve the most recent revision of the corresponding CR.
    parent_revision = parent_method.driver
    if not parent_revision:
        this_code_resource = None
        all_revisions = []
    else:
        this_code_resource = parent_revision.coderesource
        # Filter the available revisions by user.
        all_revisions = CodeResourceRevision.filter_by_user(
            creating_user,
            queryset=this_code_resource.revisions.all()).order_by('-revision_DateTime')

    parent_container = parent_method.container
    if not parent_container:
        this_container_family = None
        all_containers = []
    else:
        this_container_family = parent_container.family
        all_containers = Container.filter_by_user(
            creating_user,
            queryset=this_container_family.containers.all())

    if request.method == 'POST':
        # Because there is no CodeResource specified, the second value is of type MethodReviseForm.
        family_form, method_revise_form,\
            dep_forms, input_form_tuples,\
            output_form_tuples, _ = create_method_forms(request.POST, creating_user, family=family)
        if not _method_forms_check_valid(family_form, method_revise_form, dep_forms,
                                         input_form_tuples, output_form_tuples):
            # Bail out now if there are any problems.
            c.update(
                {
                    'coderesource': this_code_resource,
                    'containerfamily': this_container_family,
                    'method_revise_form': method_revise_form,
                    'dep_forms': dep_forms,
                    'input_forms': input_form_tuples,
                    'output_forms': output_form_tuples,
                    'family': family,
                    'family_form': family_form,
                    'parent': parent_method,
                    'docker_default': DockerImage.DEFAULT_IMAGE
                })
            return HttpResponse(t.render(c, request))

        # Next, attempt to build the Method and add it to family.
        create_method_from_forms(
            family_form, method_revise_form, dep_forms, input_form_tuples, output_form_tuples, creating_user,
            family=family, parent_method=parent_method
        )
        if _method_forms_check_valid(family_form, method_revise_form, dep_forms,
                                     input_form_tuples, output_form_tuples):
            # Success!
            return HttpResponseRedirect('/methods/{}'.format(family.pk))

    else:
        # Initialize forms with values of parent Method.
        family_form = MethodFamilyForm({"name": family.name, "description": family.description})
        parent_users_allowed = [x.username for x in parent_method.users_allowed.all()]
        parent_groups_allowed = [x.name for x in parent_method.groups_allowed.all()]
        method_revise_form = MethodReviseForm(
            initial={
                "revision_desc": parent_method.revision_desc,
                "driver_revisions": parent_revision and parent_revision.pk,
                "docker_image": parent_method.docker_image_id,
                "reusable": parent_method.reusable,
                "threads": parent_method.threads,
                "memory": parent_method.memory,
                "permissions": [parent_users_allowed, parent_groups_allowed]
            })

        dependencies = parent_method.dependencies.all()
        dep_forms = []
        for i, dependency in enumerate(dependencies):
            its_crv = dependency.requirement
            its_cr = its_crv.coderesource
            dep_form = MethodDependencyForm(
                user=creating_user,
                auto_id='id_%s_'+str(i),
                initial={
                    'coderesource': its_cr.pk,
                    'revisions': its_crv.pk,
                    'path': dependency.path,
                    'filename': dependency.filename
                }
            )
            dep_forms.append(dep_form)
        # If the parent Method has no dependencies, add a blank form.
        if len(dep_forms) == 0:
            dep_forms.append(MethodDependencyForm(user=creating_user, auto_id='id_%s_0'))

        xput_forms = []
        inputs = parent_method.inputs.order_by("dataset_idx")
        outputs = parent_method.outputs.order_by("dataset_idx")
        for xput_type, xputs in (("in", inputs), ("out", outputs)):
            forms = []
            for xput in xputs:
                tx_form = TransformationXputForm(auto_id='id_%s_{}_{}'.format(xput_type, len(forms)),
                                                 initial={'dataset_name': xput.dataset_name,
                                                          'dataset_idx': xput.dataset_idx})
                if xput.has_structure:
                    structure = xput.structure
                    xs_form = XputStructureForm(user=creating_user,
                                                auto_id='id_%s_{}_{}'.format(xput_type, len(forms)),
                                                initial={'compounddatatype': structure.compounddatatype.id,
                                                         'min_row': structure.min_row,
                                                         'max_row': structure.max_row})
                else:
                    xs_form = XputStructureForm(user=creating_user,
                                                auto_id='id_%s_{}_{}'.format(xput_type, len(forms)),
                                                initial={'compounddatatype': '__raw__'})

                forms.append((tx_form, xs_form))
            xput_forms.append(forms)

        input_form_tuples, output_form_tuples = xput_forms
        # if previous Method has no inputs, provide blank forms
        if len(input_form_tuples) == 0:
            tx_form = TransformationXputForm(auto_id='id_%s_in_0')
            xs_form = XputStructureForm(user=creating_user, auto_id='id_%s_in_0')
            input_form_tuples.append((tx_form, xs_form))

    method_revise_form.fields['driver_revisions'].widget.choices = [
        (str(x.id), '{}: {}'.format(x.revision_number, x.revision_name)) for x in all_revisions
    ]
    method_revise_form.fields['container'].widget.choices = [
        (str(x.id), x.tag) for x in all_containers]
    c.update(
        {
            'coderesource': this_code_resource,
            'containerfamily': this_container_family,
            'method_form': method_revise_form,
            'dep_forms': dep_forms,
            'input_forms': input_form_tuples,
            'output_forms': output_form_tuples,
            'family': family,
            'family_form': family_form,
            'parent': parent_method,
            'docker_default': DockerImage.DEFAULT_IMAGE
        }
    )
    return HttpResponse(t.render(c, request))
Example #29
0
def _make_crv(file_in_memory,
              creating_user,
              crv_form,
              parent_revision=None,
              code_resource=None):
    """
    Helper that creates a CodeResourceRevision (and a CodeResource as well if appropriate).
    """
    assert isinstance(crv_form,
                      (CodeResourcePrototypeForm, CodeResourceRevisionForm))
    # If parent_revision is specified, we are only making a CodeResourceRevision and not its parent CodeResource.
    assert not (parent_revision is None
                and isinstance(crv_form, CodeResourceRevision))

    cr_filename = "" if file_in_memory is None else file_in_memory.name

    if code_resource is None and parent_revision is not None:
        code_resource = parent_revision.coderesource
    if code_resource is None:
        # crv_form is a CodeResourcePrototypeForm.
        code_resource = CodeResource(
            name=crv_form.cleaned_data['resource_name'],
            description=crv_form.cleaned_data['resource_desc'],
            filename=cr_filename,
            user=creating_user)
        try:
            code_resource.full_clean()
            # Skip the clean until later; after all, we're protected by a transaction here.
            code_resource.save()
        except ValidationError as e:
            crv_form.add_error('content_file',
                               e.error_dict.get('filename', []))
            crv_form.add_error('resource_name', e.error_dict.get('name', []))
            crv_form.add_error('resource_desc',
                               e.error_dict.get('description', []))
            raise e

        code_resource.grant_from_json(crv_form.cleaned_data["permissions"])

        rev_name = "Prototype"
        rev_desc = crv_form.cleaned_data["resource_desc"]
    else:
        rev_name = crv_form.cleaned_data["revision_name"]
        rev_desc = crv_form.cleaned_data["revision_desc"]

    # Modify actual filename prior to saving revision object.
    if file_in_memory is not None:
        file_in_memory.name += '_' + datetime.now().strftime('%Y%m%d%H%M%S')

    revision = CodeResourceRevision(revision_parent=parent_revision,
                                    revision_name=rev_name,
                                    revision_desc=rev_desc,
                                    coderesource=code_resource,
                                    content_file=file_in_memory,
                                    user=creating_user)
    # This sets the MD5.

    try:
        revision.clean()
    except ValidationError as e:
        crv_form.add_error(None, e)
        raise e

    revision.save()
    revision.grant_from_json(crv_form.cleaned_data["permissions"])

    try:
        code_resource.full_clean()
        revision.full_clean()
    except ValidationError as e:
        crv_form.add_error(None, e)
        raise e

    return revision
Example #30
0
 def test_identical_self(self):
     """A Method should be identical to itself."""
     m = Method(driver=CodeResourceRevision(), user=User())
     self.assertTrue(m.is_identical(m))
Example #31
0
 def add_dependency(self, filename):
     helper = CodeResourceRevision(
         coderesource=CodeResource(filename=filename))
     dependency = self.method.dependencies.create(requirement=helper)
     dependency.method = self.method
     return dependency