Repository: alerta/python-alerta-client

Issue:
Error in Alerta class tabular 
 In Alerta CLI 5.2.0, I get an error in `alerta.tabular` method. 

Looking at the code (https://github.com/alerta/python-alerta-client/blob/master/alertaclient/models/alert.py#L156) I don't understand why there calling ` #'history': [h.serialize(timezone) for h in self.history]` instead of  `'history': [h for h in self.history]`


Discussion:

Patch:
diff --git a/alertaclient/__main__.py b/alertaclient/__main__.py
deleted file mode 100644
index d59779a..0000000
--- a/alertaclient/__main__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from alertaclient.cli import cli
-
-cli()
diff --git a/alertaclient/cli.py b/alertaclient/cli.py
index 0065906..6e3934c 100644
--- a/alertaclient/cli.py
+++ b/alertaclient/cli.py
@@ -9,8 +9,7 @@ from alertaclient.config import Config
 
 CONTEXT_SETTINGS = dict(
     auto_envvar_prefix='ALERTA',
-    default_map={'query': {'compact': True}},
-    help_option_names=['-h', '--help'],
+    default_map={'query': {'compact': True}}
 )
 cmd_folder = os.path.abspath(os.path.join(os.path.dirname(__file__), 'commands'))
 
diff --git a/alertaclient/commands/cmd_login.py b/alertaclient/commands/cmd_login.py
index 24d99ba..8e83c96 100644
--- a/alertaclient/commands/cmd_login.py
+++ b/alertaclient/commands/cmd_login.py
@@ -9,9 +9,8 @@ from alertaclient.auth.token import Jwt
 
 
 @click.command('login', short_help='Login with user credentials')
-@click.argument('username', required=False)
 @click.pass_obj
-def cli(obj, username):
+def cli(obj):
     """Authenticate using Github, Gitlab, Google OAuth2 or Basic Auth
     username/password instead of using an API key."""
     client = obj['client']
@@ -24,12 +23,10 @@ def cli(obj, username):
         elif provider == 'gitlab':
             token = gitlab.login(client, obj['gitlab_url'], client_id)['token']
         elif provider == 'google':
-            if not username:
-                username = click.prompt('Email')
+            username = click.prompt('Email')
             token = google.login(client, username, client_id)['token']
         elif provider == 'basic':
-            if not username:
-                username = click.prompt('Email')
+            username = click.prompt('Email')
             password = click.prompt('Password', hide_input=True)
             token = client.login(username, password)['token']
         else:
@@ -39,10 +36,10 @@ def cli(obj, username):
         raise AuthError(e)
 
     jwt = Jwt()
-    preferred_username = jwt.parse(token)['preferred_username']
-    if preferred_username:
-        save_token(client.endpoint, preferred_username, token)
-        click.echo('Logged in as {}'.format(preferred_username))
+    username = jwt.parse(token)['preferred_username']
+    if username:
+        save_token(client.endpoint, username, token)
+        click.echo('Logged in as {}'.format(username))
     else:
         click.echo('Failed to login.')
         sys.exit(1)
diff --git a/alertaclient/models/alert.py b/alertaclient/models/alert.py
index 525c231..69ddab7 100644
--- a/alertaclient/models/alert.py
+++ b/alertaclient/models/alert.py
@@ -153,5 +153,5 @@ class Alert(object):
                 'receiveTime': DateTime.localtime(self.receive_time, timezone),
                 'lastReceiveId': self.last_receive_id,
                 'lastReceiveTime': DateTime.localtime(self.last_receive_time, timezone),
-                'history': [h.serialize(timezone) for h in self.history]
+                'history': self.history
             }


Test patch:
diff --git a/tests/test_formats.py b/tests/test_formats.py
new file mode 100644
index 0000000..19d11b9
--- /dev/null
+++ b/tests/test_formats.py
@@ -0,0 +1,105 @@
+import unittest
+
+import requests_mock
+
+from alertaclient.api import Client
+
+
+class FormatsTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.client = Client()
+
+        self.alert = """
+            {
+                "alert": {
+                  "attributes": {
+                    "ip": "127.0.0.1"
+                  },
+                  "correlate": [],
+                  "createTime": "2018-04-08T19:01:44.979Z",
+                  "customer": null,
+                  "duplicateCount": 0,
+                  "environment": "Development",
+                  "event": "foo",
+                  "group": "Misc",
+                  "history": [
+                    {
+                      "event": "foo",
+                      "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                      "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                      "severity": null,
+                      "status": "shelved",
+                      "text": "shelved by Test90",
+                      "type": "status",
+                      "updateTime": "2018-04-09T09:11:43.502Z",
+                      "value": null
+                    },
+                    {
+                      "event": "foo",
+                      "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                      "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                      "severity": null,
+                      "status": "open",
+                      "text": "bulk status change via console by test",
+                      "type": "status",
+                      "updateTime": "2018-04-24T17:52:40.088Z",
+                      "value": null
+                    },
+                    {
+                      "event": "foo",
+                      "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                      "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                      "severity": "minor",
+                      "status": "shelved",
+                      "text": "status change via console by Scott Wenzel",
+                      "type": "action",
+                      "updateTime": "2018-05-18T03:38:50.333Z",
+                      "value": null
+                    }
+                  ],
+                  "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                  "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                  "lastReceiveId": "d1bb37cf-e976-429e-96f5-82b2a48aa50b",
+                  "lastReceiveTime": "2018-04-08T19:01:46.090Z",
+                  "origin": "alertad/fdaa33ca.lan",
+                  "previousSeverity": "indeterminate",
+                  "rawData": null,
+                  "receiveTime": "2018-04-08T19:01:46.090Z",
+                  "repeat": false,
+                  "resource": "quux",
+                  "service": [
+                    "Bar"
+                  ],
+                  "severity": "minor",
+                  "status": "shelved",
+                  "tags": [
+                    "watch:Scott Wenzel"
+                  ],
+                  "text": "",
+                  "timeout": 3600,
+                  "trendIndication": "moreSevere",
+                  "type": "exceptionAlert",
+                  "value": null
+                }
+            }
+        """
+
+    @requests_mock.mock()
+    def test_alert(self, m):
+        m.post('http://localhost:8080/alert', text=self.alert)
+        msg = {'event': 'foo', 'service': ['Bar']}
+
+        id, alert, message = self.client.send_alert(
+            environment='Production',
+            resource='quux',
+            **msg
+        )
+        alert_summary = alert.tabular(fields='summary', timezone='UTC')
+        self.assertEqual(alert_summary['id'], 'd1bb37cf')
+
+        alert_summary = alert.tabular(fields='details', timezone='UTC')
+        self.assertEqual(alert_summary['severity'], 'indeterminate -> minor')
+
+        alert_summary = alert.tabular(fields='all', timezone='UTC')
+        self.assertEqual(alert_summary['history'][0]['status'], 'shelved')
\ No newline at end of file