コード例 #1
0
 def _load_single_workflow(self, app_label, version_slug, force):
     try:
         load_workflow(app_label, version_slug, force=force)
     except WorkflowError as e:
         self.stderr.write(
             'An error occurred while loading the workflow: {}'
             .format(e))
コード例 #2
0
ファイル: loadworkflow.py プロジェクト: jesseflb/orchestra
 def handle(self, *args, **options):
     try:
         load_workflow(options['app_label'],
                       version_slug=options['version_slug'],
                       force=options['force'])
     except WorkflowError as e:
         self.stderr.write(
             'An error occurred while loading the workflow: {}'.format(e))
コード例 #3
0
ファイル: loadworkflow.py プロジェクト: EM6Holdings/orchestra
 def handle(self, *args, **options):
     try:
         load_workflow(options['app_label'],
                       version_slug=options['version_slug'],
                       force=options['force'])
     except WorkflowError as e:
         self.stderr.write(
             'An error occurred while loading the workflow: {}'.format(e))
コード例 #4
0
    def test_loadworkflowsampledata(self):
        """ Ensure that workflow sample data loads correctly. """

        # Load the test workflow
        load_workflow(TEST_WORKFLOW, VERSION_1)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)

        # Calling the command with an invalid version argument should fail.
        invalid_args = (
            VERSION_1,  # Workflow slug omitted
            TEST_WORKFLOW,  # Version slug omitted
            '{}/{}/'.format(TEST_WORKFLOW, VERSION_1),  # Too many slashes
            '{}.{}'.format(TEST_WORKFLOW, VERSION_1),  # Wrong separator
        )
        for invalid_arg in invalid_args:
            invalid_stderr = StringIO()
            invalid_message = 'Please specify workflow versions in the format'
            call_command('loadworkflowsampledata',
                         invalid_arg,
                         stderr=invalid_stderr)
            self.assertIn(invalid_message, invalid_stderr.getvalue())

        # Loading valid sample data should succeed without errors
        v1_str = '{}/{}'.format(TEST_WORKFLOW, VERSION_1)
        stdout = StringIO()
        call_command('loadworkflowsampledata', v1_str, stdout=stdout)
        output = stdout.getvalue()
        success_message = 'Successfully loaded sample data'
        self.assertIn(success_message, output)

        # clean up for subsequent commands
        del sys.modules['orchestra.tests.workflows.test_dir.load_sample_data']

        # Loading sample data for a nonexistent workflow should fail
        stderr1 = StringIO()
        call_command('loadworkflowsampledata',
                     '{}/{}'.format(NONEXISTENT_WORKFLOW_SLUG, VERSION_1),
                     stderr=stderr1)
        output1 = stderr1.getvalue()
        no_workflow_error = ('Workflow {} has not been loaded into the '
                             'database'.format(NONEXISTENT_WORKFLOW_SLUG))
        self.assertIn(no_workflow_error, output1)

        # Loading sample data for a nonexistent version should fail
        stderr2 = StringIO()
        call_command('loadworkflowsampledata',
                     '{}/{}'.format(TEST_WORKFLOW, NONEXISTENT_VERSION),
                     stderr=stderr2)
        output2 = stderr2.getvalue()
        no_version_error = (
            'Version {} does not exist'.format(NONEXISTENT_VERSION))
        self.assertIn(no_version_error, output2)

        # Loading a workflow with no loading script should fail
        # Simulate this by moving the file.
        module_path = os.path.join(TEST_WORKFLOW_DIR, 'load_sample_data.py')
        new_path = os.path.join(TEST_WORKFLOW_DIR, 'load_sample_data.py.BAK')
        try:
            os.rename(module_path, new_path)
            stderr3 = StringIO()
            call_command('loadworkflowsampledata', v1_str, stderr=stderr3)
            output3 = stderr3.getvalue()
            no_module_error = 'An error occurred while loading sample data'
            self.assertIn(no_module_error, output3)
        finally:
            os.rename(new_path, module_path)

        # Loading sample data for a workflow with no load function in its JSON
        # manifest should fail.
        workflow = Workflow.objects.get(slug=TEST_WORKFLOW)
        workflow.sample_data_load_function = None
        workflow.save()
        stderr4 = StringIO()
        call_command('loadworkflowsampledata', v1_str, stderr=stderr4)
        output4 = stderr4.getvalue()
        no_load_function_error = (
            'Workflow {} does not provide sample data'.format(TEST_WORKFLOW))
        self.assertIn(no_load_function_error, output4)
コード例 #5
0
    def test_load_workflow_version(self):
        """ Ensure that workflow version loading works as desired. """
        # Verify initial DB state.
        assert_test_dir_workflow_not_loaded(self)
        assert_test_dir_v1_not_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Load V1 of the workflow.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1)
        workflow = Workflow.objects.get(slug='test_dir')
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Load the JSON data for the versions.
        v1_file_path = os.path.join(WORKFLOWS['valid']['dir'],
                                    'v1/version.json')
        with open(v1_file_path, 'r') as v1_file:
            v1_data = json.load(v1_file)

        v2_file_path = os.path.join(WORKFLOWS['valid']['dir'],
                                    'v2/version.json')
        with open(v2_file_path, 'r') as v2_file:
            v2_data = json.load(v2_file)

        # Without --force, can't overwrite a version.
        # We wrap calls to load_workflow_version in transaction.atomic, because
        # the call might create corrupt database state otherwise.
        force_error = 'Version {} already exists'.format(VERSION_1)
        with self.assertRaisesMessage(WorkflowError, force_error):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow)

        # Even with --force, can't overwrite a version with a new step
        v1_data['steps'].append({'slug': 'invalid_new_step'})
        step_change_err_msg = ('Even with --force, cannot change the steps of '
                               'a workflow.')
        with self.assertRaisesMessage(WorkflowError, step_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data['steps'] = v1_data['steps'][:-1]

        # Even with --force, can't change a step's creation dependencies.
        step_2_create_dependencies = v1_data['steps'][1]['creation_depends_on']
        step_2_create_dependencies.append('s3')
        topology_change_err_msg = ('Even with --force, cannot change the '
                                   'topology of a workflow.')
        with self.assertRaisesMessage(WorkflowError, topology_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data['steps'][1]['creation_depends_on'] = (
            step_2_create_dependencies[:-1])

        # Even with --force, can't change a step's submission dependencies.
        step_3_submit_dependencies = v1_data['steps'][2][
            'submission_depends_on']
        step_3_submit_dependencies.append('s1')
        with self.assertRaisesMessage(WorkflowError, topology_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data['steps'][2]['submission_depends_on'] = (
            step_3_submit_dependencies[:-1])

        # Otherwise, --force should reload versions correctly.
        with transaction.atomic():
            load_workflow_version(v1_data, workflow, force=True)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # New versions with bad slugs should not load correctly
        v2_step_2 = v2_data['steps'][1]
        v2_step_2_create_dependencies = v2_step_2['creation_depends_on']
        v2_step_2_create_dependencies.append('not_a_real_step')
        bad_slug_error = '{}.{} contains a non-existent slug'
        with self.assertRaisesMessage(
                WorkflowError,
                bad_slug_error.format('s2', 'creation_depends_on')):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2['creation_depends_on'] = (v2_step_2_create_dependencies[:-1])

        v2_step_2_submit_dependencies = v2_step_2['submission_depends_on']
        v2_step_2_submit_dependencies.append('not_a_real_step')
        with self.assertRaisesMessage(
                WorkflowError,
                bad_slug_error.format('s2', 'submission_depends_on')):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2['submission_depends_on'] = (
            v2_step_2_submit_dependencies[:-1])

        v2_step_2_certification_dependencies = v2_step_2[
            'required_certifications']
        v2_step_2_certification_dependencies.append('not_a_real_certification')
        with self.assertRaisesMessage(
                WorkflowError,
                bad_slug_error.format('s2', 'required_certifications')):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2['required_certifications'] = (
            v2_step_2_certification_dependencies[:-1])

        # Otherwise, new versions should load correctly
        with transaction.atomic():
            load_workflow_version(v2_data, workflow)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)
コード例 #6
0
    def test_load_workflow(self):
        """ Ensure that a workflow directory loads correctly. """
        # Verify initial DB state.
        assert_test_dir_workflow_not_loaded(self)
        assert_test_dir_v1_not_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Shouldn't be able to parse a workflow with nonexistent
        # certification dependencies.
        with self.assertRaisesMessage(
                WorkflowError,
                'Certification certification1 requires non-existent '
                'certification'):
            load_workflow(WORKFLOWS['bad_certifications']['app_label'],
                          VERSION_1)

        # Shouldn't be able to load a non-existent version.
        version_error = 'Invalid version requested: {}'.format(INVALID_VERSION)
        with self.assertRaisesMessage(WorkflowError, version_error):
            load_workflow(WORKFLOWS['valid']['app_label'], INVALID_VERSION)

        # Loading a version should create the right database objects.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Loading a second version should create the right database objects.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_2)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)

        # Reloading a version without --force should fail.
        force_error = 'Version {} already exists'.format(VERSION_1)
        with self.assertRaisesMessage(WorkflowError, force_error):
            load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1)

        # Reloading versions with --force should succeed.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1, force=True)
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_2, force=True)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)
コード例 #7
0
ファイル: test_load.py プロジェクト: skamille/orchestra
    def test_load_workflow_version(self):
        """ Ensure that workflow version loading works as desired. """
        # Verify initial DB state.
        assert_test_dir_workflow_not_loaded(self)
        assert_test_dir_v1_not_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Load V1 of the workflow.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1)
        workflow = Workflow.objects.get(slug='test_dir')
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Load the JSON data for the versions.
        v1_file_path = os.path.join(WORKFLOWS['valid']['dir'],
                                    'v1/version.json')
        with open(v1_file_path, 'r') as v1_file:
            v1_data = json.load(v1_file)

        v2_file_path = os.path.join(WORKFLOWS['valid']['dir'],
                                    'v2/version.json')
        with open(v2_file_path, 'r') as v2_file:
            v2_data = json.load(v2_file)

        # Without --force, can't overwrite a version.
        # We wrap calls to load_workflow_version in transaction.atomic, because
        # the call might create corrupt database state otherwise.
        force_error = 'Version {} already exists'.format(VERSION_1)
        with self.assertRaisesMessage(WorkflowError, force_error):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow)

        # Even with --force, can't overwrite a version with a new step
        v1_data['steps'].append({'slug': 'invalid_new_step'})
        step_change_err_msg = ('Even with --force, cannot change the steps of '
                               'a workflow.')
        with self.assertRaisesMessage(WorkflowError, step_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data['steps'] = v1_data['steps'][:-1]

        # Even with --force, can't change a step's creation dependencies.
        step_2_create_dependencies = v1_data['steps'][1]['creation_depends_on']
        step_2_create_dependencies.append('s3')
        topology_change_err_msg = ('Even with --force, cannot change the '
                                   'topology of a workflow.')
        with self.assertRaisesMessage(WorkflowError, topology_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data['steps'][1]['creation_depends_on'] = (
            step_2_create_dependencies[:-1])

        # Even with --force, can't change a step's submission dependencies.
        step_3_submit_dependencies = v1_data['steps'][2][
            'submission_depends_on']
        step_3_submit_dependencies.append('s1')
        with self.assertRaisesMessage(WorkflowError, topology_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data['steps'][2]['submission_depends_on'] = (
            step_3_submit_dependencies[:-1])

        # Otherwise, --force should reload versions correctly.
        with transaction.atomic():
            load_workflow_version(v1_data, workflow, force=True)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # New versions with bad slugs should not load correctly
        v2_step_2 = v2_data['steps'][1]
        v2_step_2_create_dependencies = v2_step_2['creation_depends_on']
        v2_step_2_create_dependencies.append('not_a_real_step')
        bad_slug_error = '{}.{} contains a non-existent slug'
        with self.assertRaisesMessage(
                WorkflowError,
                bad_slug_error.format('s2', 'creation_depends_on')):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2['creation_depends_on'] = (
            v2_step_2_create_dependencies[:-1])

        v2_step_2_submit_dependencies = v2_step_2['submission_depends_on']
        v2_step_2_submit_dependencies.append('not_a_real_step')
        with self.assertRaisesMessage(
                WorkflowError,
                bad_slug_error.format('s2', 'submission_depends_on')):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2['submission_depends_on'] = (
            v2_step_2_submit_dependencies[:-1])

        v2_step_2_certification_dependencies = v2_step_2[
            'required_certifications']
        v2_step_2_certification_dependencies.append('not_a_real_certification')
        with self.assertRaisesMessage(
                WorkflowError,
                bad_slug_error.format('s2', 'required_certifications')):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2['required_certifications'] = (
            v2_step_2_certification_dependencies[:-1])

        # Otherwise, new versions should load correctly
        with transaction.atomic():
            load_workflow_version(v2_data, workflow)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)
コード例 #8
0
ファイル: test_load.py プロジェクト: skamille/orchestra
    def test_load_workflow(self):
        """ Ensure that a workflow directory loads correctly. """
        # Verify initial DB state.
        assert_test_dir_workflow_not_loaded(self)
        assert_test_dir_v1_not_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Shouldn't be able to parse a workflow with nonexistent
        # certification dependencies.
        with self.assertRaisesMessage(
                WorkflowError,
                'Certification certification1 requires non-existent '
                'certification'):
            load_workflow(WORKFLOWS['bad_certifications']['app_label'],
                          VERSION_1)

        # Shouldn't be able to load a non-existent version.
        version_error = 'Invalid version requested: {}'.format(
            INVALID_VERSION)
        with self.assertRaisesMessage(WorkflowError, version_error):
            load_workflow(WORKFLOWS['valid']['app_label'], INVALID_VERSION)

        # Loading a version should create the right database objects.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Loading a second version should create the right database objects.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_2)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)

        # Reloading a version without --force should fail.
        force_error = 'Version {} already exists'.format(VERSION_1)
        with self.assertRaisesMessage(WorkflowError, force_error):
            load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1)

        # Reloading versions with --force should succeed.
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_1, force=True)
        load_workflow(WORKFLOWS['valid']['app_label'], VERSION_2, force=True)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)
コード例 #9
0
ファイル: test_load.py プロジェクト: ehdr/orchestra
    def test_load_workflow_version(self):
        """ Ensure that workflow version loading works as desired. """
        # Verify initial DB state.
        assert_test_dir_workflow_not_loaded(self)
        assert_test_dir_v1_not_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Load V1 of the workflow.
        load_workflow(WORKFLOWS["valid"]["app_label"], VERSION_1)
        workflow = Workflow.objects.get(slug="test_dir")
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # Load the JSON data for the versions.
        v1_file_path = os.path.join(WORKFLOWS["valid"]["dir"], "v1/version.json")
        with open(v1_file_path, "r") as v1_file:
            v1_data = json.load(v1_file)

        v2_file_path = os.path.join(WORKFLOWS["valid"]["dir"], "v2/version.json")
        with open(v2_file_path, "r") as v2_file:
            v2_data = json.load(v2_file)

        # Without --force, can't overwrite a version.
        # We wrap calls to load_workflow_version in transaction.atomic, because
        # the call might create corrupt database state otherwise.
        force_error = "Version {} already exists".format(VERSION_1)
        with self.assertRaisesMessage(WorkflowError, force_error):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow)

        # Even with --force, can't overwrite a version with a new step
        v1_data["steps"].append({"slug": "invalid_new_step"})
        step_change_err_msg = "Even with --force, cannot change the steps of " "a workflow."
        with self.assertRaisesMessage(WorkflowError, step_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data["steps"] = v1_data["steps"][:-1]

        # Even with --force, can't change a step's creation dependencies.
        step_2_create_dependencies = v1_data["steps"][1]["creation_depends_on"]
        step_2_create_dependencies.append("s3")
        topology_change_err_msg = "Even with --force, cannot change the " "topology of a workflow."
        with self.assertRaisesMessage(WorkflowError, topology_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data["steps"][1]["creation_depends_on"] = step_2_create_dependencies[:-1]

        # Even with --force, can't change a step's submission dependencies.
        step_3_submit_dependencies = v1_data["steps"][2]["submission_depends_on"]
        step_3_submit_dependencies.append("s1")
        with self.assertRaisesMessage(WorkflowError, topology_change_err_msg):
            with transaction.atomic():
                load_workflow_version(v1_data, workflow, force=True)
        v1_data["steps"][2]["submission_depends_on"] = step_3_submit_dependencies[:-1]

        # Otherwise, --force should reload versions correctly.
        with transaction.atomic():
            load_workflow_version(v1_data, workflow, force=True)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_not_loaded(self)

        # New versions with bad slugs should not load correctly
        v2_step_2 = v2_data["steps"][1]
        v2_step_2_create_dependencies = v2_step_2["creation_depends_on"]
        v2_step_2_create_dependencies.append("not_a_real_step")
        bad_slug_error = "{}.{} contains a non-existent slug"
        with self.assertRaisesMessage(WorkflowError, bad_slug_error.format("s2", "creation_depends_on")):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2["creation_depends_on"] = v2_step_2_create_dependencies[:-1]

        v2_step_2_submit_dependencies = v2_step_2["submission_depends_on"]
        v2_step_2_submit_dependencies.append("not_a_real_step")
        with self.assertRaisesMessage(WorkflowError, bad_slug_error.format("s2", "submission_depends_on")):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2["submission_depends_on"] = v2_step_2_submit_dependencies[:-1]

        v2_step_2_certification_dependencies = v2_step_2["required_certifications"]
        v2_step_2_certification_dependencies.append("not_a_real_certification")
        with self.assertRaisesMessage(WorkflowError, bad_slug_error.format("s2", "required_certifications")):
            with transaction.atomic():
                load_workflow_version(v2_data, workflow)
        v2_step_2["required_certifications"] = v2_step_2_certification_dependencies[:-1]

        # Otherwise, new versions should load correctly
        with transaction.atomic():
            load_workflow_version(v2_data, workflow)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)
        assert_test_dir_v2_loaded(self)
コード例 #10
0
    def test_loadworkflowsampledata(self):
        """ Ensure that workflow sample data loads correctly. """

        # Load the test workflow
        load_workflow(TEST_WORKFLOW, VERSION_1)
        assert_test_dir_workflow_loaded(self)
        assert_test_dir_v1_loaded(self)

        # Calling the command with an invalid version argument should fail.
        invalid_args = (
            VERSION_1,  # Workflow slug omitted
            TEST_WORKFLOW,  # Version slug omitted
            '{}/{}/'.format(TEST_WORKFLOW, VERSION_1),  # Too many slashes
            '{}.{}'.format(TEST_WORKFLOW, VERSION_1),  # Wrong separator
        )
        for invalid_arg in invalid_args:
            invalid_stderr = StringIO()
            invalid_message = 'Please specify workflow versions in the format'
            call_command('loadworkflowsampledata', invalid_arg,
                         stderr=invalid_stderr)
            self.assertIn(invalid_message, invalid_stderr.getvalue())

        # Loading valid sample data should succeed without errors
        v1_str = '{}/{}'.format(TEST_WORKFLOW, VERSION_1)
        stdout = StringIO()
        call_command('loadworkflowsampledata', v1_str, stdout=stdout)
        output = stdout.getvalue()
        success_message = 'Successfully loaded sample data'
        self.assertIn(success_message, output)

        # clean up for subsequent commands
        del sys.modules['orchestra.tests.workflows.test_dir.load_sample_data']

        # Loading sample data for a nonexistent workflow should fail
        stderr1 = StringIO()
        call_command(
            'loadworkflowsampledata',
            '{}/{}'.format(NONEXISTENT_WORKFLOW_SLUG, VERSION_1),
            stderr=stderr1)
        output1 = stderr1.getvalue()
        no_workflow_error = ('Workflow {} has not been loaded into the '
                             'database'.format(NONEXISTENT_WORKFLOW_SLUG))
        self.assertIn(no_workflow_error, output1)

        # Loading sample data for a nonexistent version should fail
        stderr2 = StringIO()
        call_command(
            'loadworkflowsampledata',
            '{}/{}'.format(TEST_WORKFLOW, NONEXISTENT_VERSION),
            stderr=stderr2)
        output2 = stderr2.getvalue()
        no_version_error = ('Version {} does not exist'
                            .format(NONEXISTENT_VERSION))
        self.assertIn(no_version_error, output2)

        # Loading a workflow with no loading script should fail
        # Simulate this by moving the file.
        module_path = os.path.join(TEST_WORKFLOW_DIR, 'load_sample_data.py')
        new_path = os.path.join(TEST_WORKFLOW_DIR, 'load_sample_data.py.BAK')
        try:
            os.rename(module_path, new_path)
            stderr3 = StringIO()
            call_command('loadworkflowsampledata', v1_str, stderr=stderr3)
            output3 = stderr3.getvalue()
            no_module_error = 'An error occurred while loading sample data'
            self.assertIn(no_module_error, output3)
        finally:
            os.rename(new_path, module_path)

        # Loading sample data for a workflow with no load function in its JSON
        # manifest should fail.
        workflow = Workflow.objects.get(slug=TEST_WORKFLOW)
        workflow.sample_data_load_function = None
        workflow.save()
        stderr4 = StringIO()
        call_command('loadworkflowsampledata', v1_str, stderr=stderr4)
        output4 = stderr4.getvalue()
        no_load_function_error = ('Workflow {} does not provide sample data'
                                  .format(TEST_WORKFLOW))
        self.assertIn(no_load_function_error, output4)