Giuseppe Lavagetto has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/405303 )

Change subject: Refactor conftool.action
......................................................................

Refactor conftool.action

Split the Action class, which had grown out of proportion, to a separate
list of smaller Action classes.

Change-Id: I6cccb9e62887aa9151ac2ede50e923689cfe57b2
---
M conftool/action.py
M conftool/cli/tool.py
M conftool/tests/unit/test_action.py
3 files changed, 77 insertions(+), 63 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/operations/software/conftool 
refs/changes/03/405303/1

diff --git a/conftool/action.py b/conftool/action.py
index 1870435..76d3c84 100644
--- a/conftool/action.py
+++ b/conftool/action.py
@@ -12,30 +12,60 @@
     pass
 
 
-class Action(object):
+def get_action(obj, act):
+    prefix = act[:3]
+    if prefix == 'get':
+        return GetAction(obj)
+    elif act == 'delete':
+        return DelAction(obj)
+    elif prefix == 'set':
+        return SetAction(obj, act[4:])
+    else:
+        raise ActionError("Could not parse action %s" % act)
+
+
+class GetAction(object):
+    """Action to perform when a get request is involved"""
+    def __init__(self, obj):
+        self.entity = obj
+
+    def run(self):
+        self.entity.fetch()
+        if self.entity.exists:
+            return str(self.entity)
+        else:
+            return "%s not found" % self.entity.name
+
+
+class DelAction(GetAction):
+    """Action to perform when deleting an object"""
+    def run(self):
+        self.entity.delete()
+        entity_type = self.entity.__class__.__name__,
+        return "Deleted %s %s." % (entity_type,
+                                   self.entity.name)
+
+
+class SetAction(object):
 
     def __init__(self, obj, act):
+        """Action to perform when editing an object"""
         self.entity = obj
-        self.action, self.args = self._parse_action(act)
+        if not self.entity.exists:
+            raise ActionError("Entity %s doesn't exist" % self.entity.name)
+
+        self.args = self._parse_action(act)
         self.description = ""
 
-    def _parse_action(self, act):
-        # TODO: Move this to the cli.tool submodule
+    def _parse_action(self, arg):
         # TODO: make the parsing of the argument a bit more formal
-        if act.startswith('get'):
-            return ('get', None)
-        elif act.startswith('delete'):
-            return ('delete', None)
-        elif not act.startswith('set/'):
-            raise ActionError("Cannot parse action %s" % act)
-        set_arg = act.replace('set/', '', 1)
-        if set_arg.startswith('@'):
-            return ('set', self._from_file(set_arg))
+        if arg.startswith('@'):
+            return self._from_file(arg)
         try:
-            values = dict((el.strip().split('=')) for el in set_arg.split(':'))
+            values = dict((el.strip().split('=')) for el in arg.split(':'))
         except Exception:
-            raise ActionError("Could not parse set instructions: %s" % set_arg)
-        return ('set', self._from_cli(values))
+            raise ActionError("Could not parse set instructions: %s" % arg)
+        return self._from_cli(values)
 
     def _from_cli(self, values):
         for k, v in values.items():
@@ -70,33 +100,19 @@
         return values
 
     def run(self):
-        if self.action == 'get':
-            self.entity.fetch()
-            if self.entity.exists:
-                return str(self.entity)
-            else:
-                return "%s not found" % self.entity.name
-        elif self.action == 'delete':
-            self.entity.delete()
-            entity_type = self.entity.__class__.__name__,
-            return "Deleted %s %s." % (entity_type,
-                                       self.entity.name)
-        elif self.action == 'set':
-            if not self.entity.exists:
-                raise ActionError("Entity %s doesn't exist" % self.entity.name)
-            # Validate the new data *before* updating the object
-            try:
-                self.entity.validate(self.args)
-            except Exception as e:
-                raise ActionValidationError("The provided data is not valid: 
%s" % e)
+        # Validate the new data *before* updating the object
+        try:
+            self.entity.validate(self.args)
+        except Exception as e:
+            raise ActionValidationError("The provided data is not valid: %s" % 
e)
 
-            desc = []
-            for (k, v) in self.args.items():
-                curval = getattr(self.entity, k)
-                if v != curval:
-                    msg = "%s: %s changed %s => %s" % (
-                        self.entity.name, k,
-                        curval, v)
-                    desc.append(msg)
-            self.entity.update(self.args)
-            return "\n".join(desc)
+        desc = []
+        for (k, v) in self.args.items():
+            curval = getattr(self.entity, k)
+            if v != curval:
+                msg = "%s: %s changed %s => %s" % (
+                    self.entity.name, k,
+                    curval, v)
+                desc.append(msg)
+        self.entity.update(self.args)
+        return "\n".join(desc)
diff --git a/conftool/cli/tool.py b/conftool/cli/tool.py
index 32abf34..056437d 100644
--- a/conftool/cli/tool.py
+++ b/conftool/cli/tool.py
@@ -64,7 +64,7 @@
         fail = False
         for obj in self.host_list():
             try:
-                a = action.Action(obj, self._action)
+                a = action.get_action(obj, self._action)
                 msg = a.run()
             except action.ActionError as e:
                 fail = True
diff --git a/conftool/tests/unit/test_action.py 
b/conftool/tests/unit/test_action.py
index 7a68c3a..05ace73 100644
--- a/conftool/tests/unit/test_action.py
+++ b/conftool/tests/unit/test_action.py
@@ -2,7 +2,7 @@
 import unittest
 
 from conftool import configuration
-from conftool.action import Action, ActionError
+from conftool.action import get_action, ActionError, GetAction, DelAction, 
SetAction
 from conftool.kvobject import KVObject
 from conftool.tests.unit import MockBackend, MockEntity
 from conftool.types import get_validator
@@ -13,41 +13,39 @@
         KVObject.backend = MockBackend({})
         KVObject.config = configuration.Config(driver="")
         self.entity = MockEntity('Foo', 'Bar', 'test')
-
+        self.entity.exists = True
 
     def test_init(self):
         """
         Test initialization of the Action object
         """
         # Get action
-        a = Action(self.entity, 'get')
+        a = get_action(self.entity, 'get')
         self.assertEqual(a.entity, self.entity)
-        self.assertEqual(a.action, 'get')
-        self.assertIsNone(a.args)
+        self.assertEqual(a.__class__, GetAction)
         # Delete action
-        a = Action(self.entity, 'delete')
-        self.assertEqual(a.action, 'delete')
-        self.assertIsNone(a.args)
+        a = get_action(self.entity, 'delete')
+        self.assertEqual(a.__class__, DelAction)
         # Set from file
-        with mock.patch('conftool.action.Action._from_file') as mocker:
+        with mock.patch('conftool.action.SetAction._from_file') as mocker:
             values = {'a': 10, 'b': 'test test'}
             mocker.return_value = values
-            a = Action(self.entity, 'set/@filename.yaml')
-            self.assertEqual(a.action, 'set')
+            a = get_action(self.entity, 'set/@filename.yaml')
+            self.assertEqual(a.__class__, SetAction)
             self.assertEqual(a.args, values)
         # Set from cli
-        a = Action(self.entity, 'set/a=10:b=test test')
-        self.assertEqual(a.action, 'set')
+        a = get_action(self.entity, 'set/a=10:b=test test')
+        self.assertEqual(a.__class__, SetAction)
         self.assertEqual(a.args, {'a': '10', 'b': 'test test'})
-        self.assertRaises(ActionError, Action, self.entity, 'set/a=1:')
-        a = Action(self.entity, 'set/a=true:b=a,foo,bar')
+        self.assertRaises(ActionError, get_action, self.entity, 'set/a=1:')
+        a = get_action(self.entity, 'set/a=true:b=a,foo,bar')
         self.assertEqual(a.args, {'a': 'true', 'b': 'a,foo,bar'})
 
     def test_from_cli(self):
         """
         Test parsing of cli-provided arguments
         """
-        a = Action(self.entity, 'get')
+        a = get_action(self.entity, 'set/bar=ac')
         a.entity._schema['bar'] = get_validator('list')
         self.assertEqual(a._from_cli({'bar': 'abc,def,ghi'}),
                          {'bar': ['abc', 'def', 'ghi']})
@@ -57,7 +55,7 @@
         del a.entity._schema['bar']
 
     def test_run(self):
-        a = Action(self.entity, 'get')
+        a = get_action(self.entity, 'get')
         a.entity.fetch = mock.Mock()
         a.entity.exists = False
         self.assertEqual(a.run(), "test not found")

-- 
To view, visit https://gerrit.wikimedia.org/r/405303
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6cccb9e62887aa9151ac2ede50e923689cfe57b2
Gerrit-PatchSet: 1
Gerrit-Project: operations/software/conftool
Gerrit-Branch: master
Gerrit-Owner: Giuseppe Lavagetto <glavage...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to