|
| 1 | +====================== |
| 2 | +Command Class Wrappers |
| 3 | +====================== |
| 4 | + |
| 5 | +When we want to deprecate a command, policy says we need to alert the user. |
| 6 | +We do this with a message logged at WARNING level before any command output |
| 7 | +is emitted. |
| 8 | + |
| 9 | +OpenStackClient command classes are derived from the ``cliff`` classes. |
| 10 | +Cliff uses ``setuptools`` entry points for dispatching the parsed command |
| 11 | +to the respective handler classes. This lends itself to modifying the |
| 12 | +command execution at run-time. |
| 13 | + |
| 14 | +The obvious approach to adding the deprecation message would be to just add |
| 15 | +the message to the command class ``take_action()`` method directly. But then |
| 16 | +the various deprecations are scattered throughout the code base. If we |
| 17 | +instead wrap the deprecated command class with a new class we can put all of |
| 18 | +the wrappers into a separate, dedicated module. This also lets us leave the |
| 19 | +original class unmodified and puts all of the deprecation bits in one place. |
| 20 | + |
| 21 | +This is an example of a minimal wrapper around a command class that logs a |
| 22 | +deprecation message as a warning to the user then calls the original class. |
| 23 | + |
| 24 | +* Subclass the deprecated command. |
| 25 | + |
| 26 | +* Set class attribute ``deprecated`` to ``True`` to signal cliff to not |
| 27 | + emit help text for this command. |
| 28 | + |
| 29 | +* Log the deprecation message at WARNING level and refer to the replacement |
| 30 | + for the deprecated command in the log warning message. |
| 31 | + |
| 32 | +* Change the entry point class in ``setup.cfg`` to point to the new class. |
| 33 | + |
| 34 | +Example Deprecation Class |
| 35 | +------------------------- |
| 36 | + |
| 37 | +.. code-block: python |
| 38 | +
|
| 39 | + class ListFooOld(ListFoo): |
| 40 | + """List resources""" |
| 41 | +
|
| 42 | + # This notifies cliff to not display the help for this command |
| 43 | + deprecated = True |
| 44 | +
|
| 45 | + log = logging.getLogger('deprecated') |
| 46 | +
|
| 47 | + def take_action(self, parsed_args): |
| 48 | + self.log.warning( |
| 49 | + "%s is deprecated, use 'foobar list'", |
| 50 | + getattr(self, 'cmd_name', 'this command'), |
| 51 | + ) |
| 52 | + return super(ListFooOld, self).take_action(parsed_args) |
0 commit comments