diff --git a/AUTHORS b/AUTHORS index 0dea5bb2..204e0f42 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,2 @@ Randy Barlow (rbarlow@redhat.com) +Sayli Karmarkar (skarmark@redhat.com) diff --git a/docs/user-docs/getting_started.rst b/docs/user-docs/getting_started.rst index 43165005..606f1307 100644 --- a/docs/user-docs/getting_started.rst +++ b/docs/user-docs/getting_started.rst @@ -88,7 +88,7 @@ that clients can install the package from Pulp:: Install a Package From a Pulp Hosted Python Repository ------------------------------------------------------ -To conclude our tutorial, we will now install our package on another machine using pip:: +We will now install our package on another machine using pip:: $ pip install -i http://pulp.example.com/pulp/python/web/my_own_pypi/simple/ pulp_python_plugins Downloading/unpacking pulp-python-plugins @@ -101,3 +101,22 @@ To conclude our tutorial, we will now install our package on another machine usi Successfully installed pulp-python-plugins Cleaning up... + +Remove Python Packages From a Pulp Python Repository +---------------------------------------------------- + +Occasionally, we may want to remove uploaded packages from the repository:: + + $ pulp-admin python repo remove --repo-id my_own_pypi --str-eq="name=pulp_python_plugins" + This command may be exited via ctrl+c without affecting the request. + + + [\] + Running... + + Units Removed: + pulp_python_plugins-0.0.0 + +Note that this only removes the association of given packages with the repository. Uploaded packages still exist +on the server. Python packages which are not associated with any repositories can be removed from the server using +`pulp-admin orphan remove --type python_package` command. diff --git a/extensions_admin/pulp_python/extensions/admin/packages.py b/extensions_admin/pulp_python/extensions/admin/packages.py index b31cd1f4..1b9bfcae 100644 --- a/extensions_admin/pulp_python/extensions/admin/packages.py +++ b/extensions_admin/pulp_python/extensions/admin/packages.py @@ -5,10 +5,12 @@ from pulp.client.commands import options from pulp.client.commands.criteria import DisplayUnitAssociationsCommand +from pulp.client.commands.unit import UnitRemoveCommand from pulp_python.common import constants +DESC_REMOVE = _('remove packages from a repository') DESC_SEARCH = _('search for packages in a repository') @@ -48,3 +50,35 @@ def run(self, **kwargs): order = ['name', 'version', 'author'] self.prompt.render_document_list(packages, order=order) + + +class PackageRemoveCommand(UnitRemoveCommand): + """ + Class for executing unit remove commands for python package units + """ + + def __init__(self, context): + """ + Initialize the command. + + :param context: The CLI context + :type context: pulp.client.extensions.core.ClientContext + """ + UnitRemoveCommand.__init__(self, context, name='remove', description=DESC_REMOVE, + type_id=constants.PACKAGE_TYPE_ID) + + @staticmethod + def get_formatter_for_type(type_id): + """ + Returns a method that can be used to format the unit key of a python package + for display purposes + + :param type_id: the type_id of the unit key to get a formatter for + :type type_id: str + :return: function + :rtype: callable + """ + if type_id != constants.PACKAGE_TYPE_ID: + raise ValueError(_("The python package formatter can not process %s units.") % type_id) + + return lambda x: '%s-%s' % (x['name'], x['version']) diff --git a/extensions_admin/pulp_python/extensions/admin/pulp_cli.py b/extensions_admin/pulp_python/extensions/admin/pulp_cli.py index ab8efd34..adc06274 100644 --- a/extensions_admin/pulp_python/extensions/admin/pulp_cli.py +++ b/extensions_admin/pulp_python/extensions/admin/pulp_cli.py @@ -56,6 +56,7 @@ def _add_repo_section(context, parent_section): repo_section.add_command(upload.UploadPackageCommand(context)) repo_section.add_command(packages.PackagesCommand(context)) + repo_section.add_command(packages.PackageRemoveCommand(context)) def _add_publish_section(context, parent_section): diff --git a/extensions_admin/test/unit/admin/test_packages.py b/extensions_admin/test/unit/admin/test_packages.py index 59d523dd..fb57e2b1 100644 --- a/extensions_admin/test/unit/admin/test_packages.py +++ b/extensions_admin/test/unit/admin/test_packages.py @@ -84,3 +84,39 @@ def search(_repo_id, **_kwargs): c.prompt.render_document_list.assert_called_once_with(['package_1', 'package_2'], order=['name', 'version', 'author']) + + +class TestPackageRemoveCommand(unittest.TestCase): + """ + This class contains tests for the PackageRemoveCommand class. + """ + @mock.patch('pulp_python.extensions.admin.packages.UnitRemoveCommand.__init__') + def test___init__(self, super___init__): + """ + Assert correct behavior from __init__(). + """ + context = mock.MagicMock() + + c = packages.PackageRemoveCommand(context) + + super___init__.assert_called_once_with(c, context, name='remove', + description=packages.DESC_REMOVE, + type_id=constants.PACKAGE_TYPE_ID) + + def test_get_formatter_for_type(self): + """ + Assert correct behavior from get_formatter_for_type(). + """ + context = mock.MagicMock() + command = packages.PackageRemoveCommand(context) + + formatter = command.get_formatter_for_type(constants.PACKAGE_TYPE_ID) + self.assertEquals('test-name-test-version', formatter({'name': 'test-name', + 'version': 'test-version'})) + + def test_get_formatter_for_type_raises_value_error(self): + """ + Assert wrong type_id for get_formatter_for_type() raises ValueError. + """ + self.assertRaises(ValueError, packages.PackageRemoveCommand.get_formatter_for_type, + 'foo-type') diff --git a/extensions_admin/test/unit/admin/test_pulp_cli.py b/extensions_admin/test/unit/admin/test_pulp_cli.py index 9dec19a4..216ae0dc 100644 --- a/extensions_admin/test/unit/admin/test_pulp_cli.py +++ b/extensions_admin/test/unit/admin/test_pulp_cli.py @@ -33,6 +33,7 @@ def test_structure(self): self.assertTrue(isinstance(repo_section.commands['list'], ListRepositoriesCommand)) self.assertTrue(isinstance(repo_section.commands['upload'], upload.UploadPackageCommand)) self.assertTrue(isinstance(repo_section.commands['packages'], packages.PackagesCommand)) + self.assertTrue(isinstance(repo_section.commands['remove'], packages.PackageRemoveCommand)) section = repo_section.subsections['sync'] self.assertTrue(isinstance(section.commands['run'], RunSyncRepositoryCommand))