Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions q2cli/builtin/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1764,3 +1764,42 @@ def signature_verify(input_path, name):
click.echo(CONFIG.cfg_style('success',
f'Signature {name} on Result '
f'{input_path} verified successfully.'))


@tools.command(
name='redact-metadata',
short_help='Remove metadata from an artifact.',
help='Remove all metadata from an artifact and return the artifact '
'otherwise unchanged.'
)
@click.option(
'--input-path',
required=True,
help='The path to the artifact where you wish to remove the metadata.'
)
@click.option(
'--output-path',
required=True,
help='Path to save artifact with redacted metadata to.'
)
def redact_metadata(input_path, output_path):
from rachis.sdk.result import Result
from q2cli.core.config import CONFIG

artifact = Result.load(input_path)

try:
artifact.redact_metadata()
except ValueError as e:
click.echo(CONFIG.cfg_style('error', str(e)), err=True)
raise click.Abort()

artifact.save(output_path)

click.echo(
CONFIG.cfg_style(
'success',
f'Succesfully redacted metadata from {input_path}, and saved to '
f'{output_path}.'
)
)
63 changes: 63 additions & 0 deletions q2cli/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from q2cli.builtin.tools import tools
from q2cli.commands import RootCommand
from q2cli.core.usage import ReplayCLIUsage
from rachis.sdk.result import Visualization


class TestCastMetadata(unittest.TestCase):
Expand Down Expand Up @@ -2046,5 +2047,67 @@ def test_make_report_duplicate_names(self):
self.assertIn('Multiple files share the same name', result.output)


class TestRedactMetadata(unittest.TestCase):
def setUp(self):
datadir = datadir = os.path.join(
os.path.dirname(os.path.abspath(__file__)), 'data'
)
self.tax_fp = os.path.join(datadir, 'taxonomy.qza')
self.tax_bar_fp = os.path.join(datadir, 'taxa-bar-plots.qzv')
self.demux_fp = os.path.join(datadir, 'demux.qza')
self.runner = CliRunner()
self.tempdir = tempfile.mkdtemp(prefix='qiime2-q2cli-test-temp-')
self.redacted_fp = os.path.join(self.tempdir, 'redacted')

def test_with_metadata(self):
redacted_fp = self.redacted_fp + '.qzv'
result = self.runner.invoke(tools, [
'redact-metadata', '--input-path', self.tax_bar_fp,
'--output-path', redacted_fp
])

redacted_artifact = Visualization.load(redacted_fp)
abs_md_paths, _ = redacted_artifact.metadata_paths()

for path in abs_md_paths:
self.assertEqual(os.path.getsize(path), 0)

success = f'Succesfully redacted metadata from {self.tax_bar_fp}, ' \
f'and saved to {redacted_fp}.\n'

self.assertEqual(success, result.output)

def test_fails_already_redacted(self):
'''
Redacting metadata from an Artifact twice should fail.
'''
redacted_fp = self.redacted_fp + '.qza'
self.runner.invoke(tools, [
'redact-metadata', '--input-path', self.tax_fp,
'--output-path', self.redacted_fp
])

result = self.runner.invoke(tools, [
'redact-metadata', '--input-path', redacted_fp,
'--output-path', os.path.join(self.tempdir, 'bad')
])

self.assertEqual(result.exit_code, 1)
self.assertIn('only redacted metadata', result.output)

def test_fails_no_metadata(self):
'''
Redacting metadata from an Artifact with no metadata should fail.
'''
redacted_fp = self.redacted_fp + '.qza'
result = self.runner.invoke(tools, [
'redact-metadata', '--input-path', self.demux_fp,
'--output-path', redacted_fp
])

self.assertEqual(result.exit_code, 1)
self.assertIn('Artifact without metadata', result.output)


if __name__ == "__main__":
unittest.main()
Loading