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)
def __init__(self, *args, **kwargs): super(CodeResourceRevisionSerializer, self).__init__(*args, **kwargs) request = self.context.get("request", None) if request is not None: # Set the queryset of the coderesource field. cr_field = self.fields["coderesource"] cr_field.queryset = CodeResource.filter_by_user(request.user)
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()
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')
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()
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()
def __init__(self, data=None, user=None, *args, **kwargs): super(MethodForm, self).__init__(data, *args, **kwargs) # This is required to re-populate the drop-down with CRs created since first load. if user is not None: self.fields["coderesource"].choices = ( [('', '--- CodeResource ---')] + [(x.id, x.name) for x in CodeResource.filter_by_user(user).order_by('name')] ) self.fields["containerfamily"].choices = ( [('', '--- Container Family ---')] + [(x.id, x.name) for x in ContainerFamily.filter_by_user(user)])
def __init__(self, data=None, user=None, *args, **kwargs): super(MethodForm, self).__init__(data, *args, **kwargs) # This is required to re-populate the drop-down with CRs created since first load. if user is not None: self.fields["coderesource"].choices = ( [('', '--- CodeResource ---')] + [(x.id, x.name) for x in CodeResource.filter_by_user(user).order_by('name')]) self.fields["containerfamily"].choices = ( [('', '--- Container Family ---')] + [(x.id, x.name) for x in ContainerFamily.filter_by_user(user)])
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()
def _get_code_resource_list(user, but_not_this_one=None): """ Gets all CodeResources other than that of the specified one. This is required to refresh the list of eligible CodeResources during the addition of a new MethodDependency. """ if user is None: queryset = CodeResource.objects.all() else: queryset = CodeResource.filter_by_user(user).distinct() if but_not_this_one is not None: queryset = queryset.exclude(pk=but_not_this_one) return [('', '--- CodeResource ---')] + [(x.id, x.name) for x in queryset]
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()
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()
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))
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)
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)
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)
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
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))
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
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))
def add_dependency(self, filename): helper = CodeResourceRevision( coderesource=CodeResource(filename=filename)) dependency = self.method.dependencies.create(requirement=helper) dependency.method = self.method return dependency