You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@predictionio.apache.org by sh...@apache.org on 2017/10/25 13:51:08 UTC

[01/24] incubator-predictionio-sdk-python git commit: Fixed indentation Deleted obsolete examples Moved obsolete test suite to 'test-obsolete' (port as we go) Added tox test bootstrapping Ignored pycharm, test output Removed obsolete (<0.8) support PEP8/

Repository: incubator-predictionio-sdk-python
Updated Branches:
  refs/heads/master 41d0c11c0 -> 903b2f6e7


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/predictionio_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_test.py b/tests-obsolete/predictionio_test.py
new file mode 100644
index 0000000..696718c
--- /dev/null
+++ b/tests-obsolete/predictionio_test.py
@@ -0,0 +1,257 @@
+"""
+Test Python SDK
+"""
+import unittest
+
+import predictionio
+import time
+
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
+API_URL = "http://localhost:8000"  # PredictoinIO Server
+
+MIN_VERSION = '0.6.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+# print predictionio.__version__
+# predictionio.connection.enable_log()
+
+
+class TestPredictionIO(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_status(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+        status = client.get_status()
+        self.assertEqual(status, "PredictionIO Output API is online.")
+        client.close()
+
+    def _test_user(self, uids):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        uid1 = uids[0]
+        uid2 = uids[1]
+        uid3 = uids[2]
+        uid4 = uids[3]
+        uid5 = uids[4]
+
+        # create users and get them back
+        client.create_user(uid1)
+        # create user with optional attributes
+        client.create_user(uid2, {"pio_latlng": [1.2, 33.3]})
+        client.create_user(uid3, {"pio_latlng": [4.5, 67.8], "pio_inactive": True})
+        # create user with custom attributes
+        client.create_user(uid4, {"pio_latlng": [1.2, 33.3], "custom1": "value1", "custom2": "value2"})
+        client.create_user(uid5, {"custom1": "u5c1", "custom2": "u5c2"})
+
+        user1 = client.get_user(uid1)
+        user2 = client.get_user(uid2)
+        user3 = client.get_user(uid3)
+        user4 = client.get_user(uid4)
+        user5 = client.get_user(uid5)
+
+        self.assertEqual(user1, {"pio_uid": uid1})
+        self.assertEqual(user2, {"pio_uid": uid2, "pio_latlng": [1.2, 33.3]})
+        self.assertEqual(user3, {"pio_uid": uid3, "pio_latlng": [4.5, 67.8], "pio_inactive": True})
+        self.assertEqual(user4, {"pio_uid": uid4, "pio_latlng": [1.2, 33.3], "custom1": "value1", "custom2": "value2"})
+        self.assertEqual(user5, {"pio_uid": uid5, "custom1": "u5c1", "custom2": "u5c2"})
+
+        # delete user and then try to get it
+        client.delete_user(uid1)
+
+        try:
+            client.get_user(uid1)
+        except predictionio.UserNotFoundError as e:  # noqa
+            pass  # expected exception
+        except:
+            raise
+
+        # other users still exist
+        user2 = client.get_user(uid2)
+        self.assertEqual(user2, {"pio_uid": uid2, "pio_latlng": [1.2, 33.3]})
+
+        # read, modify, write
+        user3 = client.get_user(uid3)
+        self.assertEqual(user3, {"pio_uid": uid3, "pio_latlng": [4.5, 67.8], "pio_inactive": True})
+        del user3["pio_uid"]
+        user3["pio_latlng"] = [5.6, 10.11]
+        user3["pio_inactive"] = False
+        user3["custom1"] = "food"
+        client.create_user(uid3, user3)
+        updated_user3 = client.get_user(uid3)
+        self.assertEqual(updated_user3,
+                         {"pio_uid": uid3, "pio_latlng": [5.6, 10.11], "pio_inactive": False, "custom1": "food"})
+
+        user4 = client.get_user(uid4)
+        self.assertEqual(user4, {"pio_uid": uid4, "pio_latlng": [1.2, 33.3], "custom1": "value1", "custom2": "value2"})
+        del user4["pio_uid"]
+        user4["custom1"] = "new value"
+        client.create_user(uid4, user4)
+        updated_user4 = client.get_user(uid4)
+        self.assertEqual(updated_user4,
+                         {"pio_uid": uid4, "pio_latlng": [1.2, 33.3], "custom1": "new value", "custom2": "value2"})
+
+        client.close()
+
+    def test_user(self):
+        self._test_user(["u1", "u2", "u3", "u4", "u5"])
+        # test special characters in uid
+        self._test_user(["u1@a.com", "u2@ap/ple", "u3@foo.bar", "u4/a/b", "&^%$()u5"])
+
+    def _test_item(self, iids):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        iid1 = iids[0]
+        iid2 = iids[1]
+        iid3 = iids[2]
+        iid4 = iids[3]
+        iid5 = iids[4]
+
+        # create items and read back
+        client.create_item(iid1, ("t1", "t2", "t3"))
+        client.create_item(iid2, ("t1",))
+        client.create_item(iid3, ("t2",),
+                           {"pio_price": 4.99, "pio_profit": 2.0, "pio_startT": 12345667, "pio_endT": 4567788,
+                            "pio_latlng": [1.345, 9.876], "pio_inactive": True})
+        client.create_item(iid4, ("t2",), {"pio_latlng": [1.2345, 10.11], "custom1": "value1"})
+        client.create_item(iid5, ("t1", "t2"), {"custom1": "i5value1", "custom2": "i5value2"})
+
+        item1 = client.get_item(iid1)
+        item2 = client.get_item(iid2)
+        item3 = client.get_item(iid3)
+        item4 = client.get_item(iid4)
+        item5 = client.get_item(iid5)
+
+        del item1["pio_startT"]  # pio_startT is automatically inserted, don't compare
+        self.assertEqual(item1, {"pio_iid": iid1, "pio_itypes": ("t1", "t2", "t3")})
+        del item2["pio_startT"]
+        self.assertEqual(item2, {"pio_iid": iid2, "pio_itypes": ("t1",)})
+        self.assertEqual(item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 4.99, "pio_profit": 2.0,
+                                 "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876],
+                                 "pio_inactive": True})
+        del item4["pio_startT"]
+        self.assertEqual(item4,
+                         {"pio_iid": iid4, "pio_itypes": ("t2",), "pio_latlng": [1.2345, 10.11], "custom1": "value1"})
+        del item5["pio_startT"]
+        self.assertEqual(item5,
+                         {"pio_iid": iid5, "pio_itypes": ("t1", "t2"), "custom1": "i5value1", "custom2": "i5value2"})
+
+        # delete and then try to get it
+        client.delete_item(iid2)
+
+        try:
+            item2 = client.get_item(iid2)
+        except predictionio.ItemNotFoundError as e:  # noqa
+            pass  # expected exception
+        except:
+            raise
+
+        # others still exist
+        item3 = client.get_item(iid3)
+        self.assertEqual(item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 4.99, "pio_profit": 2.0,
+                                 "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876],
+                                 "pio_inactive": True})
+
+        # read, modify, write
+        del item3["pio_iid"]
+        item3_itypes = item3.pop("pio_itypes")
+        item3["pio_price"] = 6.99
+        item3["custom1"] = "some value"
+        client.create_item(iid3, item3_itypes, item3)
+        updated_item3 = client.get_item(iid3)
+        self.assertEqual(updated_item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 6.99, "pio_profit": 2.0,
+                                         "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876],
+                                         "pio_inactive": True, "custom1": "some value"})
+
+        client.close()
+
+    def test_item(self):
+        self._test_item(["i1", "i2", "i3", "i4", "i5"])
+        # test special characters in iid
+        self._test_item(["i1@abc.com", "i2/f/bar//@@foo", "$$i3%%$~~", "http://www.i4.com", "``i5/apple/"])
+
+    def test_u2iAction_deprecated(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        client.user_like_item("u1", "i1")
+        client.user_dislike_item("u2", "i2")
+        client.user_view_item("u3", "i3")
+        client.user_rate_item("u4", "i4", 4)
+        client.user_conversion_item("u5", "i5")
+
+        client.close()
+
+    def test_u2iAction(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        client.identify("u101")
+
+        # required param
+        client.record_action_on_item("like", "i1")
+        client.record_action_on_item("dislike", "i2")
+        client.record_action_on_item("view", "i3")
+        client.record_action_on_item("rate", "i4", {"pio_rate": 1})
+        client.record_action_on_item("conversion", "i5")
+
+        client.identify("u102")
+
+        # with optional param
+        client.record_action_on_item("like", "i1", {"pio_latlng": [1.23, 4.56]})
+        client.record_action_on_item("dislike", "i2", {"pio_t": 1234567689})
+        client.record_action_on_item("view", "i3", {"pio_latlng": [4.67, 1.44], "pio_t": 3445566778})
+        client.record_action_on_item("rate", "i4", {"pio_rate": 1, "pio_latlng": [66.78, 9.10]})
+        client.record_action_on_item("conversion", "i5", {"pio_price": 12.5})
+
+        # uid and iid with special characters
+        client.identify("u1@a.com")
+        client.record_action_on_item("view", "i3@bb.com")
+        client.record_action_on_item("view", "http://www.yahoo.com")
+
+        client.close()
+
+    def test_pending_requests(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        client.identify("u111")
+        for i in range(100):
+            client.arecord_action_on_item("like", str(i))
+
+        n = 1
+        while n > 0:
+            n = client.pending_requests()
+            time.sleep(0.1)
+            # print n
+
+        client.close()
+
+    def test_qsize(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL, qsize=10)
+
+        client.identify("u222")
+        for i in range(100):
+            client.arecord_action_on_item("like", str(i))
+
+        n = 1
+        while n > 0:
+            n = client.pending_requests()
+            time.sleep(0.1)
+            # print n
+
+        client.close()
+
+
+"""
+to run individual test:
+$ python -m unittest predictionio_test.TestPredictionIO.test_user
+
+to run ALL tests:
+% python predictionio_test.py
+"""
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/.keep
----------------------------------------------------------------------
diff --git a/tests/.keep b/tests/.keep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/conversion_test.py
----------------------------------------------------------------------
diff --git a/tests/conversion_test.py b/tests/conversion_test.py
deleted file mode 100644
index ffcd90f..0000000
--- a/tests/conversion_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import timeit
-import json
-
-if __name__ == "__main__":
-	a = True
-
-	t = timeit.Timer("json.dumps(True)", "import json")
-
-	t_bool2json = t.timeit(1000)/1000
-	print "bool 2 json"
-	print t_bool2json
-
-	t = timeit.Timer("str(True).lower()", "")
-
-	t_bool2string = t.timeit(1000)/1000
-	print "bool 2 string"
-	print t_bool2string
-
-
-
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/import_testdata.py
----------------------------------------------------------------------
diff --git a/tests/import_testdata.py b/tests/import_testdata.py
deleted file mode 100644
index 57ec48c..0000000
--- a/tests/import_testdata.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-Import simple test data for testing getting itemrec
-"""
-import predictionio
-
-APP_KEY = "tGgZ7bJDpSyxLndJUBWgyAUwfBgVSTjO6KkhjnMpzCi7vSgPoYnXYptyVlg3vjLH"
-API_URL = "http://localhost:8000"
-
-MIN_VERSION = '0.5.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-if __name__ == "__main__":
-	client = predictionio.Client(APP_KEY, 1, API_URL)
-
-	client.create_user("u0")
-	client.create_user("u1")
-	client.create_user("u2")
-	client.create_user("u3")
-
-	client.create_item("i0", ("t1",), {"custom1": "i0c1"})
-	client.create_item("i1", ("t1","t2"), {"custom1": "i1c1", "custom2": "i1c2"})
-	client.create_item("i2", ("t1","t2"), {"custom2": "i2c2"})
-	client.create_item("i3", ("t1",))
-
-	client.identify("u0")
-	client.record_action_on_item("rate", "i0", { "pio_rate": 2 })
-	client.record_action_on_item("rate", "i1", { "pio_rate": 3 })
-	client.record_action_on_item("rate", "i2", { "pio_rate": 4 })
-	
-	client.identify("u1")
-	client.record_action_on_item("rate", "i2", { "pio_rate": 4 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 1 })
-
-	client.identify("u2")
-	client.record_action_on_item("rate", "i1", { "pio_rate": 2 })
-	client.record_action_on_item("rate", "i2", { "pio_rate": 1 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 3 })
-
-	client.identify("u3")
-	client.record_action_on_item("rate", "i0", { "pio_rate": 5 })
-	client.record_action_on_item("rate", "i1", { "pio_rate": 3 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 2 })
-
-	client.close()
-	
-
-	
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/import_testdata_id_mismatch.py
----------------------------------------------------------------------
diff --git a/tests/import_testdata_id_mismatch.py b/tests/import_testdata_id_mismatch.py
deleted file mode 100644
index 17d707a..0000000
--- a/tests/import_testdata_id_mismatch.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-Import simple test data for testing getting itemrec
-"""
-import predictionio
-
-APP_KEY = "7zwXYnroz52gemLdHEU20Nn8c2SyobFpnrzoTGOolCe8ZRH2zmGyhVknj9Sa7P6x"
-API_URL = "http://localhost:8000"
-
-MIN_VERSION = '0.5.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-if __name__ == "__main__":
-	client = predictionio.Client(APP_KEY, 1, API_URL)
-
-	client.create_user("u0")
-	client.create_user("u1")
-	client.create_user("u2")
-	client.create_user("u3")
-
-	client.create_item("i0", ("t1",), {"custom1": "i0c1"})
-	client.create_item("i1", ("t1","t2"), {"custom1": "i1c1", "custom2": "i1c2"})
-	client.create_item("i2", ("t1","t2"), {"custom2": "i2c2"})
-	client.create_item("i3", ("t1",))
-
-	client.identify("u0x")
-	client.record_action_on_item("rate", "i0", { "pio_rate": 2 })
-	client.record_action_on_item("rate", "i1", { "pio_rate": 3 })
-	client.record_action_on_item("rate", "i2", { "pio_rate": 4 })
-	
-	client.identify("u1x")
-	client.record_action_on_item("rate", "i2", { "pio_rate": 4 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 1 })
-
-	client.identify("u2x")
-	client.record_action_on_item("rate", "i1", { "pio_rate": 2 })
-	client.record_action_on_item("rate", "i2", { "pio_rate": 1 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 3 })
-
-	client.identify("u3x")
-	client.record_action_on_item("rate", "i0", { "pio_rate": 5 })
-	client.record_action_on_item("rate", "i1", { "pio_rate": 3 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 2 })
-
-	client.close()
-	
-
-	
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/import_testdata_special_char.py
----------------------------------------------------------------------
diff --git a/tests/import_testdata_special_char.py b/tests/import_testdata_special_char.py
deleted file mode 100644
index e9445be..0000000
--- a/tests/import_testdata_special_char.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-Import simple test data (id with special characters) for testing getting itemrec
-"""
-import predictionio
-
-APP_KEY = "GToKwk78As0LBp2fAx2YNUBPZFZvtwy6MJkGwRASiD6Q77JjBnTaXBxzBTd52ICE"
-API_URL = "http://localhost:8000"
-
-MIN_VERSION = '0.5.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-if __name__ == "__main__":
-	client = predictionio.Client(APP_KEY, 1, API_URL)
-
-	client.create_user("u0@u.n")
-	client.create_user("u1@u.n")
-	client.create_user("http://u2.com")
-	client.create_user("u3@u.n")
-
-	client.create_item("http://i0.com", ("t1",), {"custom1": "i0c1"})
-	client.create_item("i1@i1", ("t1","t2"), {"custom1": "i1c1", "custom2": "i1c2"})
-	client.create_item("i2.org", ("t1","t2"), {"custom2": "i2c2"})
-	client.create_item("i3", ("t1",))
-
-	client.identify("u0@u.n")
-	client.record_action_on_item("rate", "http://i0.com", { "pio_rate": 2 })
-	client.record_action_on_item("rate", "i1@i1", { "pio_rate": 3 })
-	client.record_action_on_item("rate", "i2.org", { "pio_rate": 4 })
-	
-	client.identify("u1@u.n")
-	client.record_action_on_item("rate", "i2.org", { "pio_rate": 4 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 1 })
-
-	client.identify("http://u2.com")
-	client.record_action_on_item("rate", "i1@i1", { "pio_rate": 2 })
-	client.record_action_on_item("rate", "i2.org", { "pio_rate": 1 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 3 })
-
-	client.identify("u3@u.n")
-	client.record_action_on_item("rate", "http://i0.com", { "pio_rate": 5 })
-	client.record_action_on_item("rate", "i1@i1", { "pio_rate": 3 })
-	client.record_action_on_item("rate", "i3", { "pio_rate": 2 })
-
-	client.close()
-	
-
-	
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/predictionio_itemrec_test.py
----------------------------------------------------------------------
diff --git a/tests/predictionio_itemrec_test.py b/tests/predictionio_itemrec_test.py
deleted file mode 100644
index 5f91501..0000000
--- a/tests/predictionio_itemrec_test.py
+++ /dev/null
@@ -1,300 +0,0 @@
-"""
-Test getting itemrec after algo training completes.
-"""
-import predictionio
-import unittest
-import time
-
-APP_KEY = "y2Fk4BACEGYeJnqBF4zL9TmrIBdF9va3gyFaLsnM7PVyUNf0G00zC8vCnyBx5hdA" # replace this with your AppKey
-API_URL = "http://localhost:8000" # PredictoinIO Server
-
-DEBUG = True
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-	err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-	raise Exception(err)
-
-class TestPredictionIO(unittest.TestCase):
-	def setUp(self):
-		pass
-
-	def tearDown(self):
-		pass
-
-	def test_get_itemrec_exception_deprecated(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		try:
-			itemrec = client.get_itemrec("uidwithoutrec", 10, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected exception
-		except:
-			raise
-
-		client.close()
-
-	def test_get_itemrec_exception(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		client.identify("uidwithoutrec")
-
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected exception
-		except:
-			raise
-
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, { "pio_itypes": ("t1",), "pio_latlng": [1.34, 5.67], "pio_within": 5.0, "pio_unit": "km", "pio_attributes": ["custom1", "custom2"]  })
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected exception
-		except:
-			raise
-
-		client.close()
-
-	def test_get_itemrec_deprecated(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		# request more
-		try:
-			itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-		try:
-			itemrec = client.get_itemrec("u1", 10, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": ["i2", "i1", "i0", "i3"]}) or 
-						 (itemrec == {"pio_iids": ["i2", "i0", "i1", "i3"]}) )
-
-		try:
-			itemrec = client.get_itemrec("u2", 10, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": ["i3", "i0", "i1", "i2"]}) or
-						 (itemrec == {"pio_iids": ["i3", "i1", "i0", "i2"]}) )
-
-		try:
-			itemrec = client.get_itemrec("u3", 6, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": ["i0", "i1", "i2", "i3"]}) or
-						 (itemrec == {"pio_iids": ["i0", "i2", "i1", "i3"]}) )
-
-		# request less
-		try:
-			itemrec = client.get_itemrec("u0", 1, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2"]})
-
-		try:
-			itemrec = client.get_itemrec("u0", 2, "python-itemrec-engine")
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3"]})
-
-		# request with optional attributes
-
-		# pio_itypes
-		try:
-			itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t1","t2"))
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-		# subset itypes
-		try:
-			itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t2",))
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i1"]})
-
-		# nonexisting itypes
-		try:
-			itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("other-itype",))
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected no recommendation
-		except:
-			raise
-
-		# pio_attributes
-		try:
-			itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t1",), pio_attributes=["custom1", "custom2"])
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"], "custom1": [None, None, "i1c1", "i0c1"], "custom2": ["i2c2", None, "i1c2", None]})
-
-		client.close()
-
-
-	def test_get_itemrec(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		# request more
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-		client.identify("u1")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": ["i2", "i1", "i0", "i3"]}) or 
-						 (itemrec == {"pio_iids": ["i2", "i0", "i1", "i3"]}) )
-
-		client.identify("u2")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": ["i3", "i0", "i1", "i2"]}) or
-						 (itemrec == {"pio_iids": ["i3", "i1", "i0", "i2"]}) )
-
-		client.identify("u3")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 6)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": ["i0", "i1", "i2", "i3"]}) or
-						 (itemrec == {"pio_iids": ["i0", "i2", "i1", "i3"]}) )
-
-		# request less
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 1)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2"]})
-
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 2)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3"]})
-
-		# request with optional attributes
-
-		# pio_itypes
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t1","t2")})
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-		# subset itypes
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t2",)})
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i1"]})
-
-		# nonexisting itypes
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("other-itype",)})
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected no recommendation
-		except:
-			raise
-
-		# pio_attributes
-		client.identify("u0")
-		try:
-			itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"], "custom1": [None, None, "i1c1", "i0c1"], "custom2": ["i2c2", None, "i1c2", None]})
-
-		# TODO pio_latlng
-		# TODO pio_within
-		# TODO pio_unit
-
-		client.close()
-
-if __name__ == "__main__" :
-	unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/predictionio_itemrec_test_special_char.py
----------------------------------------------------------------------
diff --git a/tests/predictionio_itemrec_test_special_char.py b/tests/predictionio_itemrec_test_special_char.py
deleted file mode 100644
index e4ac6c8..0000000
--- a/tests/predictionio_itemrec_test_special_char.py
+++ /dev/null
@@ -1,291 +0,0 @@
-"""
-Test getting itemrec after algo training completes.
-"""
-import predictionio
-import unittest
-import time
-
-APP_KEY = "GToKwk78As0LBp2fAx2YNUBPZFZvtwy6MJkGwRASiD6Q77JjBnTaXBxzBTd52ICE" # replace this with your AppKey
-API_URL = "http://localhost:8000" # PredictoinIO Server
-
-DEBUG = True
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-	err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-	raise Exception(err)
-
-class TestPredictionIO(unittest.TestCase):
-	def setUp(self):
-		pass
-
-	def tearDown(self):
-		pass
-
-	def test_get_itemrec_deprecated(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		uid0 = "u0@u.n"
-		uid1 = "u1@u.n"
-		uid2 = "http://u2.com"
-		uid3 = "u3@u.n"
-
-		iid0 = "http://i0.com"
-		iid1 = "i1@i1"
-		iid2 = "i2.org"
-		iid3 = "i3"
-
-		engine_name = "itemrec"
-
-		# request more
-		try:
-			itemrec = client.get_itemrec(uid0, 10, engine_name)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-		try:
-			itemrec = client.get_itemrec(uid1, 10, engine_name)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": [iid2, iid1, iid0, iid3]}) or 
-						 (itemrec == {"pio_iids": [iid2, iid0, iid1, iid3]}) )
-
-		try:
-			itemrec = client.get_itemrec(uid2, 10, engine_name)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": [iid3, iid0, iid1, iid2]}) or
-						 (itemrec == {"pio_iids": [iid3, iid1, iid0, iid2]}) )
-
-		try:
-			itemrec = client.get_itemrec(uid3, 6, engine_name)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": [iid0, iid1, iid2, iid3]}) or
-						 (itemrec == {"pio_iids": [iid0, iid2, iid1, iid3]}) )
-
-		# request less
-		try:
-			itemrec = client.get_itemrec(uid0, 1, engine_name)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2]})
-
-		try:
-			itemrec = client.get_itemrec(uid0, 2, engine_name)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3]})
-
-		# request with optional attributes
-
-		# pio_itypes
-		try:
-			itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t1","t2"))
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-		# subset itypes
-		try:
-			itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t2",))
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid1]})
-
-		# nonexisting itypes
-		try:
-			itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("other-itype",))
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected no recommendation
-		except:
-			raise
-
-		# pio_attributes
-		try:
-			itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t1",), pio_attributes=["custom1", "custom2"])
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0], "custom1": [None, None, "i1c1", "i0c1"], "custom2": ["i2c2", None, "i1c2", None]})
-
-		client.close()
-
-
-	def test_get_itemrec(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		uid0 = "u0@u.n"
-		uid1 = "u1@u.n"
-		uid2 = "http://u2.com"
-		uid3 = "u3@u.n"
-
-		iid0 = "http://i0.com"
-		iid1 = "i1@i1"
-		iid2 = "i2.org"
-		iid3 = "i3"
-
-		engine_name = "itemrec"
-		
-		# request more
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-		client.identify(uid1)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": [iid2, iid1, iid0, iid3]}) or 
-						 (itemrec == {"pio_iids": [iid2, iid0, iid1, iid3]}) )
-
-		client.identify(uid2)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": [iid3, iid0, iid1, iid2]}) or
-						 (itemrec == {"pio_iids": [iid3, iid1, iid0, iid2]}) )
-
-		client.identify(uid3)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 6)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertTrue( (itemrec == {"pio_iids": [iid0, iid1, iid2, iid3]}) or
-						 (itemrec == {"pio_iids": [iid0, iid2, iid1, iid3]}) )
-
-		# request less
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 1)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2]})
-
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 2)
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3]})
-
-		# request with optional attributes
-
-		# pio_itypes
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t1","t2")})
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-		# subset itypes
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t2",)})
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid1]})
-
-		# nonexisting itypes
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("other-itype",)})
-		except predictionio.ItemRecNotFoundError as e:
-			pass # expected no recommendation
-		except:
-			raise
-
-		# pio_attributes
-		client.identify(uid0)
-		try:
-			itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
-		except predictionio.ItemRecNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemrec
-		self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0], "custom1": [None, None, "i1c1", "i0c1"], "custom2": ["i2c2", None, "i1c2", None]})
-
-		# TODO pio_latlng
-		# TODO pio_within
-		# TODO pio_unit
-
-		client.close()
-
-if __name__ == "__main__" :
-	unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/predictionio_itemsim_test.py
----------------------------------------------------------------------
diff --git a/tests/predictionio_itemsim_test.py b/tests/predictionio_itemsim_test.py
deleted file mode 100644
index c540f02..0000000
--- a/tests/predictionio_itemsim_test.py
+++ /dev/null
@@ -1,160 +0,0 @@
-"""
-Test getting itemsim after algo training completes (pdio-itemsimcf with cosine sim).
-"""
-import predictionio
-import unittest
-import time
-
-APP_KEY = "y2Fk4BACEGYeJnqBF4zL9TmrIBdF9va3gyFaLsnM7PVyUNf0G00zC8vCnyBx5hdA" # replace this with your AppKey
-API_URL = "http://localhost:8000" # PredictoinIO Server
-
-DEBUG = True
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-	err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-	raise Exception(err)
-
-class TestPredictionIO(unittest.TestCase):
-	def setUp(self):
-		pass
-
-	def tearDown(self):
-		pass
-
-	def test_get_itemsim_exception(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "iidwithoutsim", 10)
-		except predictionio.ItemSimNotFoundError as e:
-			pass # expected exception
-		except:
-			raise
-
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "iidwithoutsim", 10, { "pio_itypes": ("t1",), "pio_latlng": [1.34, 5.67], "pio_within": 5.0, "pio_unit": "km", "pio_attributes": ["custom1", "custom2"]  })
-		except predictionio.ItemSimNotFoundError as e:
-			pass # expected exception
-		except:
-			raise
-
-		client.close()
-
-	def test_get_itemsim(self):
-		client = predictionio.Client(APP_KEY, 1, API_URL)
-
-		# request more than what is available
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i0", 10)
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertTrue( (itemsim == {"pio_iids": ["i1", "i2", "i3"]}) or
-						 (itemsim == {"pio_iids": ["i1", "i3", "i2"]}) )
-
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10)
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertTrue( (itemsim == {"pio_iids": ["i2", "i3", "i0"]}) )
-
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i2", 10)
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertTrue( (itemsim == {"pio_iids": ["i1", "i3", "i0"]}) )
-
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i3", 10)
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertTrue( (itemsim == {"pio_iids": ["i1", "i2", "i0"]}) )
-
-		# request less
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 1)
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertEqual(itemsim, {"pio_iids": ["i2"]})
-
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 2)
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertEqual(itemsim, {"pio_iids": ["i2", "i3"]})
-
-		# request with optional attributes
-
-		# pio_itypes
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t1","t2")})
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertEqual(itemsim, {"pio_iids": ["i2", "i3", "i0"]})
-
-		# subset itypes
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t2",)})
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertEqual(itemsim, {"pio_iids": ["i2"]})
-
-		# nonexisting itypes
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i0", 10, {"pio_itypes": ("other-itype",)})
-		except predictionio.ItemSimNotFoundError as e:
-			pass # expected no recommendation
-		except:
-			raise
-
-		# pio_attributes
-		try:
-			itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
-		except predictionio.ItemSimNotFoundError as e:
-			print "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-			raise
-		except:
-			raise
-		if DEBUG: print itemsim
-		self.assertEqual(itemsim, {"pio_iids": ["i2", "i3", "i0"], "custom1": [None, None, "i0c1"], "custom2": ["i2c2", None, None]})
-
-		# TODO pio_latlng
-		# TODO pio_within
-		# TODO pio_unit
-
-		client.close()
-
-if __name__ == "__main__" :
-	unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests/predictionio_test.py
----------------------------------------------------------------------
diff --git a/tests/predictionio_test.py b/tests/predictionio_test.py
deleted file mode 100644
index 28b3d06..0000000
--- a/tests/predictionio_test.py
+++ /dev/null
@@ -1,246 +0,0 @@
-"""
-Test Python SDK
-"""
-import predictionio
-import unittest
-import time
-
-APP_KEY = "GToKwk78As0LBp2fAx2YNUBPZFZvtwy6MJkGwRASiD6Q77JjBnTaXBxzBTd52ICE" # replace this with your AppKey
-API_URL = "http://localhost:8000" # PredictoinIO Server
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-#print predictionio.__version__
-#predictionio.connection.enable_log()
-
-class TestPredictionIO(unittest.TestCase):
-
-    def setUp(self):
-        pass
-
-    def tearDown(self):
-        pass
-
-    def test_status(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-        status = client.get_status()
-        self.assertEqual(status, "PredictionIO Output API is online.")
-        client.close()
-
-    def _test_user(self, uids):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        uid1 = uids[0]
-        uid2 = uids[1]
-        uid3 = uids[2]
-        uid4 = uids[3]
-        uid5 = uids[4]
-
-        # create users and get them back
-        client.create_user(uid1)
-        # create user with optional attributes
-        client.create_user(uid2, { "pio_latlng": [1.2,33.3] })
-        client.create_user(uid3, { "pio_latlng": [4.5,67.8], "pio_inactive": True } )
-        # create user with custom attributes
-        client.create_user(uid4, { "pio_latlng": [1.2,33.3], "custom1": "value1", "custom2": "value2" })
-        client.create_user(uid5, { "custom1": "u5c1", "custom2": "u5c2" })
-
-        user1 = client.get_user(uid1)
-        user2 = client.get_user(uid2)
-        user3 = client.get_user(uid3)
-        user4 = client.get_user(uid4)
-        user5 = client.get_user(uid5)
-
-        self.assertEqual(user1, {"pio_uid" : uid1})
-        self.assertEqual(user2, {"pio_uid" : uid2, "pio_latlng": [1.2,33.3]})
-        self.assertEqual(user3, {"pio_uid" : uid3, "pio_latlng" : [4.5,67.8], "pio_inactive" : True})
-        self.assertEqual(user4, {"pio_uid" : uid4, "pio_latlng": [1.2,33.3], "custom1": "value1", "custom2": "value2" })
-        self.assertEqual(user5, {"pio_uid" : uid5, "custom1": "u5c1", "custom2": "u5c2"  })
-
-        # delete user and then try to get it
-        client.delete_user(uid1)
-
-        try:
-            user = client.get_user(uid1)
-        except predictionio.UserNotFoundError as e:
-            pass # expected exception
-        except:
-            raise
-
-        # other users still exist
-        user2 = client.get_user(uid2)
-        self.assertEqual(user2, {"pio_uid" : uid2, "pio_latlng": [1.2,33.3]})
-
-        # read, modify, write
-        user3 = client.get_user(uid3)
-        self.assertEqual(user3, {"pio_uid" : uid3, "pio_latlng" : [4.5,67.8], "pio_inactive" : True})
-        del user3["pio_uid"]
-        user3["pio_latlng"] = [5.6,10.11]
-        user3["pio_inactive"] = False
-        user3["custom1"] = "food"
-        client.create_user(uid3, user3)
-        updated_user3 = client.get_user(uid3)
-        self.assertEqual(updated_user3, {"pio_uid" : uid3, "pio_latlng" : [5.6,10.11], "pio_inactive" : False, "custom1" : "food"} )
-
-        user4 = client.get_user(uid4)
-        self.assertEqual(user4, {"pio_uid" : uid4, "pio_latlng": [1.2,33.3], "custom1": "value1", "custom2": "value2" })
-        del user4["pio_uid"]
-        user4["custom1"] = "new value"
-        client.create_user(uid4, user4)
-        updated_user4 = client.get_user(uid4)
-        self.assertEqual(updated_user4, {"pio_uid" : uid4, "pio_latlng": [1.2,33.3], "custom1": "new value", "custom2": "value2" })
-
-        client.close()
-
-    def test_user(self):
-        self._test_user(["u1", "u2", "u3", "u4", "u5"])
-        # test special characters in uid
-        self._test_user(["u1@a.com", "u2@ap/ple", "u3@foo.bar", "u4/a/b", "&^%$()u5"])
-
-    def _test_item(self, iids):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        iid1 = iids[0]
-        iid2 = iids[1]
-        iid3 = iids[2]
-        iid4 = iids[3]
-        iid5 = iids[4]
-
-        # create items and read back
-        client.create_item(iid1, ("t1","t2","t3"))
-        client.create_item(iid2, ("t1",))
-        client.create_item(iid3, ("t2",), {"pio_price": 4.99, "pio_profit": 2.0, "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876], "pio_inactive": True })
-        client.create_item(iid4, ("t2",), {"pio_latlng": [1.2345, 10.11], "custom1": "value1"})
-        client.create_item(iid5, ("t1", "t2"), {"custom1": "i5value1", "custom2": "i5value2"} )
-
-        item1 = client.get_item(iid1)
-        item2 = client.get_item(iid2)
-        item3 = client.get_item(iid3)
-        item4 = client.get_item(iid4)
-        item5 = client.get_item(iid5)
-
-        del item1["pio_startT"] # pio_startT is automatically inserted, don't compare
-        self.assertEqual(item1, {"pio_iid": iid1, "pio_itypes": ("t1", "t2", "t3") } )
-        del item2["pio_startT"]
-        self.assertEqual(item2, {"pio_iid": iid2, "pio_itypes": ("t1",)} )
-        self.assertEqual(item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 4.99, "pio_profit": 2.0, "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876], "pio_inactive": True } )
-        del item4["pio_startT"]
-        self.assertEqual(item4, {"pio_iid": iid4, "pio_itypes": ("t2",), "pio_latlng": [1.2345, 10.11], "custom1": "value1"})
-        del item5["pio_startT"]
-        self.assertEqual(item5, {"pio_iid": iid5, "pio_itypes": ("t1","t2"), "custom1": "i5value1", "custom2": "i5value2"})
-
-        # delete and then try to get it
-        client.delete_item(iid2)
-
-        try:
-          item2 = client.get_item(iid2)
-        except predictionio.ItemNotFoundError as e:
-            pass # expected exception
-        except:
-            raise
-
-        # others still exist
-        item3 = client.get_item(iid3)
-        self.assertEqual(item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 4.99, "pio_profit": 2.0, "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876], "pio_inactive": True } )
-
-        # read, modify, write
-        del item3["pio_iid"]
-        item3_itypes = item3.pop("pio_itypes")
-        item3["pio_price"] = 6.99
-        item3["custom1"] = "some value"
-        client.create_item(iid3, item3_itypes, item3)
-        updated_item3 = client.get_item(iid3)
-        self.assertEqual(updated_item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 6.99, "pio_profit": 2.0, "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876], "pio_inactive": True, "custom1": "some value" } )
-
-        client.close()
-
-    def test_item(self):
-        self._test_item(["i1", "i2", "i3", "i4", "i5"])
-        # test special characters in iid
-        self._test_item(["i1@abc.com", "i2/f/bar//@@foo", "$$i3%%$~~", "http://www.i4.com", "``i5/apple/"])
-
-    def test_u2iAction_deprecated(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.user_like_item("u1", "i1")
-        client.user_dislike_item("u2", "i2")
-        client.user_view_item("u3", "i3")
-        client.user_rate_item("u4", "i4", 4)
-        client.user_conversion_item("u5", "i5")
-
-        client.close()
-
-    def test_u2iAction(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.identify("u101")
-
-        # required param
-        client.record_action_on_item("like", "i1")
-        client.record_action_on_item("dislike", "i2")
-        client.record_action_on_item("view", "i3")
-        client.record_action_on_item("rate", "i4", { "pio_rate": 1 })
-        client.record_action_on_item("conversion", "i5")
-
-        client.identify("u102")
-
-        # with optional param
-        client.record_action_on_item("like", "i1", { "pio_latlng": [1.23, 4.56] })
-        client.record_action_on_item("dislike", "i2", { "pio_t": 1234567689 })
-        client.record_action_on_item("view", "i3", { "pio_latlng": [4.67, 1.44], "pio_t": 3445566778})
-        client.record_action_on_item("rate", "i4", { "pio_rate": 1, "pio_latlng": [66.78, 9.10] })
-        client.record_action_on_item("conversion", "i5", { "pio_price" : 12.5 })
-
-
-        # uid and iid with special characters
-        client.identify("u1@a.com")
-        client.record_action_on_item("view", "i3@bb.com")
-        client.record_action_on_item("view", "http://www.yahoo.com")
-
-        client.close()
-
-
-    def test_pending_requests(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.identify("u111")
-        for i in range(100):
-            client.arecord_action_on_item("like", str(i))
-
-        n = 1
-        while n > 0:
-            n = client.pending_requests()
-            time.sleep(0.1)
-            #print n
-
-        client.close()
-
-    def test_qsize(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL, qsize=10)
-
-        client.identify("u222")
-        for i in range(100):
-            client.arecord_action_on_item("like", str(i))
-
-        n = 1
-        while n > 0:
-            n = client.pending_requests()
-            time.sleep(0.1)
-            #print n
-
-        client.close()
-
-
-
-"""
-to run individual test:
-$ python -m unittest predictionio_test.TestPredictionIO.test_user
-
-to run ALL tests:
-% python predictionio_test.py
-"""
-if __name__ == "__main__" :
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tox.ini
----------------------------------------------------------------------
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..23d96e4
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,9 @@
+[tox]
+envlist = py27,py34
+
+[testenv]
+deps = flake8
+       pandas
+
+commands = flake8 --ignore=E501 --filename=*.py --exclude=doc,setup.py,*/tests/*
+           python -m unittest discover --pattern=*.py tests


[13/24] incubator-predictionio-sdk-python git commit: remove reference to obsolete

Posted by sh...@apache.org.
remove reference to obsolete


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/73adea9d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/73adea9d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/73adea9d

Branch: refs/heads/master
Commit: 73adea9d6f5093538f4f738f7d01941309500496
Parents: e63bf7f
Author: EmergentOrder <le...@gmail.com>
Authored: Tue Nov 3 14:11:32 2015 -0400
Committer: EmergentOrder <le...@gmail.com>
Committed: Tue Nov 3 14:11:32 2015 -0400

----------------------------------------------------------------------
 predictionio/__init__.py | 3 ---
 1 file changed, 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/73adea9d/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index e5e5387..699b2db 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -6,9 +6,6 @@ Python applications with PredictionIO REST API services.
 
 __version__ = "0.9.6"
 
-# import deprecated libraries.
-from predictionio.obsolete import Client, InvalidArgumentError
-
 # import packages
 import re
 try:


[11/24] incubator-predictionio-sdk-python git commit: Merge branch 'fcvarela-develop' into develop

Posted by sh...@apache.org.
Merge branch 'fcvarela-develop' into develop


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/77ef0dd3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/77ef0dd3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/77ef0dd3

Branch: refs/heads/master
Commit: 77ef0dd39669157a18ca1ff260e735107eeb8e82
Parents: b85d044 7b6e210
Author: EmergentOrder <le...@gmail.com>
Authored: Tue Nov 3 13:04:46 2015 -0400
Committer: EmergentOrder <le...@gmail.com>
Committed: Tue Nov 3 13:04:46 2015 -0400

----------------------------------------------------------------------
 .gitignore                                      |    4 +
 docs/source/conf.py                             |  110 +-
 examples/demo-movielens/appdata.py              |  316 ++---
 examples/demo-movielens/batch_import.py         |  246 ++--
 examples/event_sample.py                        |   48 +-
 examples/import_yahoo.py                        |  261 ++--
 examples/itemrank_quick_query.py                |   18 +-
 examples/itemrank_quick_start.py                |   69 +-
 examples/obsolete/__init__.py                   |    0
 examples/obsolete/itemrec/__init__.py           |    0
 examples/obsolete/itemrec/movies/.gitignore     |    3 -
 examples/obsolete/itemrec/movies/README.md      |   15 -
 examples/obsolete/itemrec/movies/__init__.py    |    0
 examples/obsolete/itemrec/movies/app_config.py  |    2 -
 examples/obsolete/itemrec/movies/appdata.py     |  148 ---
 .../obsolete/itemrec/movies/batch_import.py     |   65 -
 .../obsolete/itemrec/movies/movie_rec_app.py    |  152 ---
 predictionio/__init__.py                        |   40 +-
 predictionio/connection.py                      |  537 ++++----
 predictionio/obsolete.py                        | 1205 ------------------
 setup.py                                        |   32 +-
 tests-obsolete/conversion_test.py               |   16 +
 tests-obsolete/import_testdata.py               |   46 +
 tests-obsolete/import_testdata_id_mismatch.py   |   46 +
 tests-obsolete/import_testdata_special_char.py  |   46 +
 tests-obsolete/predictionio_itemrec_test.py     |  336 +++++
 .../predictionio_itemrec_test_special_char.py   |  366 ++++++
 tests-obsolete/predictionio_itemsim_test.py     |  200 +++
 tests-obsolete/predictionio_test.py             |  257 ++++
 tests/.keep                                     |    0
 tests/conversion_test.py                        |   23 -
 tests/import_testdata.py                        |   52 -
 tests/import_testdata_id_mismatch.py            |   52 -
 tests/import_testdata_special_char.py           |   52 -
 tests/predictionio_itemrec_test.py              |  300 -----
 tests/predictionio_itemrec_test_special_char.py |  291 -----
 tests/predictionio_itemsim_test.py              |  160 ---
 tests/predictionio_test.py                      |  246 ----
 tox.ini                                         |    9 +
 39 files changed, 2171 insertions(+), 3598 deletions(-)
----------------------------------------------------------------------



[15/24] incubator-predictionio-sdk-python git commit: Add travis test and Refactoring

Posted by sh...@apache.org.
Add travis test and Refactoring

Closes #22


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/8e35e33d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/8e35e33d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/8e35e33d

Branch: refs/heads/master
Commit: 8e35e33da89323b8f49d026d7035dac172997cf1
Parents: cd72584
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Sun Sep 10 10:35:50 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Sun Sep 10 10:35:50 2017 +0900

----------------------------------------------------------------------
 .travis.yml                                     |  34 ++
 README.txt                                      | 122 +++----
 predictionio/__init__.py                        |  14 +-
 tests-obsolete/conversion_test.py               |  16 -
 tests-obsolete/import_testdata.py               |  46 ---
 tests-obsolete/import_testdata_id_mismatch.py   |  46 ---
 tests-obsolete/import_testdata_special_char.py  |  46 ---
 tests-obsolete/predictionio_itemrec_test.py     | 336 -----------------
 .../predictionio_itemrec_test_special_char.py   | 366 -------------------
 tests-obsolete/predictionio_itemsim_test.py     | 200 ----------
 tests-obsolete/predictionio_test.py             | 257 -------------
 tests/.keep                                     |   0
 tests/after_script.travis.sh                    |   5 +
 tests/before_script.travis.sh                   |  27 ++
 tests/engineclient_test.py                      |  48 +++
 tests/eventclient_test.py                       | 251 +++++++++++++
 tests/fileexport_test.py                        |  74 ++++
 tox.ini                                         |   7 +-
 18 files changed, 511 insertions(+), 1384 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..50d98a9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,34 @@
+sudo: required
+
+language: python
+
+jdk:
+  - oraclejdk8
+
+python:
+  - 2.7
+  - 3.4
+  - 3.5
+  - 3.6
+
+cache:
+  directories:
+    - $HOME/.ivy2/cache
+    - $HOME/.sbt/boot
+    - $HOME/.sbt/launchers
+
+install:
+  - pip install tox tox-travis
+  - pip install coverage coveralls
+
+before_script:
+  - java -version
+  - ./tests/before_script.travis.sh
+  - export PATH=$PATH:$PWD/predictionio-setup/predictionio/bin
+
+script:
+  - pio status
+  - tox -r
+
+after_script:
+  - ./tests/after_script.travis.sh

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/README.txt
----------------------------------------------------------------------
diff --git a/README.txt b/README.txt
index 2a542a0..4740ff5 100644
--- a/README.txt
+++ b/README.txt
@@ -1,63 +1,59 @@
-PredictionIO Python SDK
-=======================
-
-
-Installation
-============
-
-To install the module from PyPI, you may
-
-    $ pip install predictionio
-
-or
-
-    $ easy_install predictionio
-
-If you have cloned the repository and want to install directly from there,
-do the following in the root directory of the repository:
-
-    $ python setup.py install
-
-This will install the "predictionio" module to your Python distribution.
-
-
-Usage
-=====
-
-To use predictionio in your Python script,
-
-    >>> import predictionio
-
-
-Documentation
-=============
-
-The latest documentation is located at http://pythonhosted.org/PredictionIO/
-
-If you want to build a local copy, please install Sphinx
-(http://sphinx-doc.org/install.html).
-
-To generate documentation,
-
-    % cd docs
-    % make html
-
-To view the generated documentation, go to docs/build/html/index.html.
-
-
-SUPPORT
-=======
-
-
-Forum
------
-
-https://groups.google.com/group/predictionio-user
-
-
-Issue Tracker
--------------
-
-https://predictionio.atlassian.net
-
-If you are unsure whether a behavior is an issue, bringing it up in the forum is highly encouraged.
+PredictionIO Python SDK
+=======================
+
+
+Installation
+============
+
+To install the module from PyPI, you may
+
+    $ pip install predictionio
+
+or
+
+    $ easy_install predictionio
+
+If you have cloned the repository and want to install directly from there,
+do the following in the root directory of the repository:
+
+    $ python setup.py install
+
+This will install the "predictionio" module to your Python distribution.
+
+
+Usage
+=====
+
+To use predictionio in your Python script,
+
+    >>> import predictionio
+
+
+Documentation
+=============
+
+The latest documentation is located at http://pythonhosted.org/PredictionIO/
+
+If you want to build a local copy, please install Sphinx
+(http://sphinx-doc.org/install.html).
+
+To generate documentation,
+
+    % cd docs
+    % make html
+
+To view the generated documentation, go to docs/build/html/index.html.
+
+
+SUPPORT
+=======
+
+http://predictionio.incubator.apache.org/support/
+
+
+Issue Tracker
+-------------
+
+https://issues.apache.org/jira/projects/PIO
+
+If you are unsure whether a behavior is an issue, bringing it up in the forum is highly encouraged.

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index b429b4e..01ac045 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -21,6 +21,12 @@ except ImportError:
   # pylint: disable=F0401,E0611
   from urllib.parse import urlencode
 
+try:
+  from urllib import quote
+except ImportError:
+  # pylint: disable=F0401,E0611
+  from urllib.parse import quote
+
 import json
 import urllib
 
@@ -260,7 +266,7 @@ class EventClient(BaseClient):
     if self.channel is not None:
       qparam["channel"] = self.channel
 
-    enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
+    enc_event_id = quote(event_id, "") # replace special char with %xx
     path = "/events/%s.json" % (enc_event_id, )
     request = AsyncRequest("GET", path, **qparam)
     request.set_rfunc(self._aget_resp)
@@ -335,7 +341,7 @@ class EventClient(BaseClient):
     if self.channel is not None:
       qparam["channel"] = self.channel
 
-    enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
+    enc_event_id = quote(event_id, "") # replace special char with %xx
     path = "/events/%s.json" % (enc_event_id, )
     request = AsyncRequest("DELETE", path, **qparam)
     request.set_rfunc(self._adelete_resp)
@@ -519,7 +525,7 @@ class FileExporter(object):
 
   def create_event(self, event, entity_type, entity_id,
       target_entity_type=None, target_entity_id=None, properties=None,
-      event_time=None):
+      event_time=None, ensure_ascii=True):
     """Create an event and write to the file.
     (please refer to EventClient's create_event())
     """
@@ -544,7 +550,7 @@ class FileExporter(object):
     et_str = et.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + et.strftime("%z")
     data["eventTime"] = et_str
 
-    j = json.dumps(data)
+    j = json.dumps(data, ensure_ascii=ensure_ascii)
     self._file.write(j+"\n")
 
   def close(self):

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/conversion_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/conversion_test.py b/tests-obsolete/conversion_test.py
deleted file mode 100644
index b9dca97..0000000
--- a/tests-obsolete/conversion_test.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import timeit
-
-if __name__ == "__main__":
-    a = True
-
-    t = timeit.Timer("json.dumps(True)", "import json")
-
-    t_bool2json = t.timeit(1000) / 1000
-    print("bool 2 json")
-    print(t_bool2json)
-
-    t = timeit.Timer("str(True).lower()", "")
-
-    t_bool2string = t.timeit(1000) / 1000
-    print("bool 2 string")
-    print(t_bool2string)

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/import_testdata.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/import_testdata.py b/tests-obsolete/import_testdata.py
deleted file mode 100644
index e5338c0..0000000
--- a/tests-obsolete/import_testdata.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-Import simple test data for testing getting itemrec
-"""
-import predictionio
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
-API_URL = "http://localhost:7070"
-
-MIN_VERSION = '0.5.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-if __name__ == "__main__":
-    client = predictionio.Client(APP_KEY, 1, API_URL)
-
-    client.create_user("u0")
-    client.create_user("u1")
-    client.create_user("u2")
-    client.create_user("u3")
-
-    client.create_item("i0", ("t1",), {"custom1": "i0c1"})
-    client.create_item("i1", ("t1", "t2"), {"custom1": "i1c1", "custom2": "i1c2"})
-    client.create_item("i2", ("t1", "t2"), {"custom2": "i2c2"})
-    client.create_item("i3", ("t1",))
-
-    client.identify("u0")
-    client.record_action_on_item("rate", "i0", {"pio_rate": 2})
-    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
-    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
-
-    client.identify("u1")
-    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 1})
-
-    client.identify("u2")
-    client.record_action_on_item("rate", "i1", {"pio_rate": 2})
-    client.record_action_on_item("rate", "i2", {"pio_rate": 1})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 3})
-
-    client.identify("u3")
-    client.record_action_on_item("rate", "i0", {"pio_rate": 5})
-    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 2})
-
-    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/import_testdata_id_mismatch.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/import_testdata_id_mismatch.py b/tests-obsolete/import_testdata_id_mismatch.py
deleted file mode 100644
index 104f75c..0000000
--- a/tests-obsolete/import_testdata_id_mismatch.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-Import simple test data for testing getting itemrec
-"""
-import predictionio
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
-API_URL = "http://localhost:8000"
-
-MIN_VERSION = '0.5.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-if __name__ == "__main__":
-    client = predictionio.Client(APP_KEY, 1, API_URL)
-
-    client.create_user("u0")
-    client.create_user("u1")
-    client.create_user("u2")
-    client.create_user("u3")
-
-    client.create_item("i0", ("t1",), {"custom1": "i0c1"})
-    client.create_item("i1", ("t1", "t2"), {"custom1": "i1c1", "custom2": "i1c2"})
-    client.create_item("i2", ("t1", "t2"), {"custom2": "i2c2"})
-    client.create_item("i3", ("t1",))
-
-    client.identify("u0x")
-    client.record_action_on_item("rate", "i0", {"pio_rate": 2})
-    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
-    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
-
-    client.identify("u1x")
-    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 1})
-
-    client.identify("u2x")
-    client.record_action_on_item("rate", "i1", {"pio_rate": 2})
-    client.record_action_on_item("rate", "i2", {"pio_rate": 1})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 3})
-
-    client.identify("u3x")
-    client.record_action_on_item("rate", "i0", {"pio_rate": 5})
-    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 2})
-
-    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/import_testdata_special_char.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/import_testdata_special_char.py b/tests-obsolete/import_testdata_special_char.py
deleted file mode 100644
index c047b6a..0000000
--- a/tests-obsolete/import_testdata_special_char.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-Import simple test data (id with special characters) for testing getting itemrec
-"""
-import predictionio
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
-API_URL = "http://localhost:8000"
-
-MIN_VERSION = '0.5.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-if __name__ == "__main__":
-    client = predictionio.Client(APP_KEY, 1, API_URL)
-
-    client.create_user("u0@u.n")
-    client.create_user("u1@u.n")
-    client.create_user("http://u2.com")
-    client.create_user("u3@u.n")
-
-    client.create_item("http://i0.com", ("t1",), {"custom1": "i0c1"})
-    client.create_item("i1@i1", ("t1", "t2"), {"custom1": "i1c1", "custom2": "i1c2"})
-    client.create_item("i2.org", ("t1", "t2"), {"custom2": "i2c2"})
-    client.create_item("i3", ("t1",))
-
-    client.identify("u0@u.n")
-    client.record_action_on_item("rate", "http://i0.com", {"pio_rate": 2})
-    client.record_action_on_item("rate", "i1@i1", {"pio_rate": 3})
-    client.record_action_on_item("rate", "i2.org", {"pio_rate": 4})
-
-    client.identify("u1@u.n")
-    client.record_action_on_item("rate", "i2.org", {"pio_rate": 4})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 1})
-
-    client.identify("http://u2.com")
-    client.record_action_on_item("rate", "i1@i1", {"pio_rate": 2})
-    client.record_action_on_item("rate", "i2.org", {"pio_rate": 1})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 3})
-
-    client.identify("u3@u.n")
-    client.record_action_on_item("rate", "http://i0.com", {"pio_rate": 5})
-    client.record_action_on_item("rate", "i1@i1", {"pio_rate": 3})
-    client.record_action_on_item("rate", "i3", {"pio_rate": 2})
-
-    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/predictionio_itemrec_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_itemrec_test.py b/tests-obsolete/predictionio_itemrec_test.py
deleted file mode 100644
index 3105f0f..0000000
--- a/tests-obsolete/predictionio_itemrec_test.py
+++ /dev/null
@@ -1,336 +0,0 @@
-"""
-Test getting itemrec after algo training completes.
-"""
-
-from __future__ import print_function
-
-import unittest
-
-import predictionio
-
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
-API_URL = "http://localhost:8000"  # PredictoinIO Server
-
-DEBUG = True
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-
-class TestPredictionIO(unittest.TestCase):
-    def setUp(self):
-        pass
-
-    def tearDown(self):
-        pass
-
-    def test_get_itemrec_exception_deprecated(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        try:
-            client.get_itemrec("uidwithoutrec", 10, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:  # noqa
-            pass  # expected exception
-        except:
-            raise
-
-        client.close()
-
-    def test_get_itemrec_exception(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.identify("uidwithoutrec")
-
-        try:
-            client.get_itemrec_topn("python-itemrec-engine", 10)
-        except predictionio.ItemRecNotFoundError as e:  # noqa
-            pass  # expected exception
-        except:
-            raise
-
-        try:
-            client.get_itemrec_topn("python-itemrec-engine", 10,
-                                    {"pio_itypes": ("t1",), "pio_latlng": [1.34, 5.67], "pio_within": 5.0,
-                                     "pio_unit": "km", "pio_attributes": ["custom1", "custom2"]})
-        except predictionio.ItemRecNotFoundError as e:  # noqa
-            pass  # expected exception
-        except:
-            raise
-
-        client.close()
-
-    def test_get_itemrec_deprecated(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        # request more
-        try:
-            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-        try:
-            itemrec = client.get_itemrec("u1", 10, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": ["i2", "i1", "i0", "i3"]}) or
-                        (itemrec == {"pio_iids": ["i2", "i0", "i1", "i3"]}))
-
-        try:
-            itemrec = client.get_itemrec("u2", 10, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertTrue((itemrec == {"pio_iids": ["i3", "i0", "i1", "i2"]}) or
-                        (itemrec == {"pio_iids": ["i3", "i1", "i0", "i2"]}))
-
-        try:
-            itemrec = client.get_itemrec("u3", 6, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertTrue((itemrec == {"pio_iids": ["i0", "i1", "i2", "i3"]}) or
-                        (itemrec == {"pio_iids": ["i0", "i2", "i1", "i3"]}))
-
-        # request less
-        try:
-            itemrec = client.get_itemrec("u0", 1, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2"]})
-
-        try:
-            itemrec = client.get_itemrec("u0", 2, "python-itemrec-engine")
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3"]})
-
-        # request with optional attributes
-
-        # pio_itypes
-        try:
-            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t1", "t2"))
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-        # subset itypes
-        try:
-            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t2",))
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i1"]})
-
-        # nonexisting itypes
-        try:
-            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("other-itype",))
-        except predictionio.ItemRecNotFoundError as e:
-            pass  # expected no recommendation
-        except:
-            raise
-
-        # pio_attributes
-        try:
-            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t1",),
-                                         pio_attributes=["custom1", "custom2"])
-        except predictionio.ItemRecNotFoundError as e:  # noqa
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"], "custom1": [None, None, "i1c1", "i0c1"],
-                                   "custom2": ["i2c2", None, "i1c2", None]})
-
-        client.close()
-
-    def test_get_itemrec(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        # request more
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-        client.identify("u1")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertTrue((itemrec == {"pio_iids": ["i2", "i1", "i0", "i3"]}) or
-                        (itemrec == {"pio_iids": ["i2", "i0", "i1", "i3"]}))
-
-        client.identify("u2")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertTrue((itemrec == {"pio_iids": ["i3", "i0", "i1", "i2"]}) or
-                        (itemrec == {"pio_iids": ["i3", "i1", "i0", "i2"]}))
-
-        client.identify("u3")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 6)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertTrue((itemrec == {"pio_iids": ["i0", "i1", "i2", "i3"]}) or
-                        (itemrec == {"pio_iids": ["i0", "i2", "i1", "i3"]}))
-
-        # request less
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 1)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2"]})
-
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 2)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3"]})
-
-        # request with optional attributes
-
-        # pio_itypes
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t1", "t2")})
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
-
-        # subset itypes
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t2",)})
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-        if DEBUG:
-            print(itemrec)
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i1"]})
-
-        # nonexisting itypes
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("other-itype",)})
-        except predictionio.ItemRecNotFoundError as e:
-            pass  # expected no recommendation
-        except:
-            raise
-
-        # pio_attributes
-        client.identify("u0")
-        try:
-            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10,
-                                              {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
-        except predictionio.ItemRecNotFoundError as e:  # noqa
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"], "custom1": [None, None, "i1c1", "i0c1"],
-                                   "custom2": ["i2c2", None, "i1c2", None]})
-
-        # TODO pio_latlng
-        # TODO pio_within
-        # TODO pio_unit
-
-        client.close()
-
-
-if __name__ == "__main__":
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/predictionio_itemrec_test_special_char.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_itemrec_test_special_char.py b/tests-obsolete/predictionio_itemrec_test_special_char.py
deleted file mode 100644
index a622800..0000000
--- a/tests-obsolete/predictionio_itemrec_test_special_char.py
+++ /dev/null
@@ -1,366 +0,0 @@
-"""
-Test getting itemrec after algo training completes.
-"""
-import unittest
-
-import predictionio
-
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
-API_URL = "http://localhost:8000"  # PredictoinIO Server
-
-DEBUG = True
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-
-class TestPredictionIO(unittest.TestCase):
-    def setUp(self):
-        pass
-
-    def tearDown(self):
-        pass
-
-    def test_get_itemrec_deprecated(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        uid0 = "u0@u.n"
-        uid1 = "u1@u.n"
-        uid2 = "http://u2.com"
-        uid3 = "u3@u.n"
-
-        iid0 = "http://i0.com"
-        iid1 = "i1@i1"
-        iid2 = "i2.org"
-        iid3 = "i3"
-
-        engine_name = "itemrec"
-
-        # request more
-        try:
-            itemrec = client.get_itemrec(uid0, 10, engine_name)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-        try:
-            itemrec = client.get_itemrec(uid1, 10, engine_name)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": [iid2, iid1, iid0, iid3]}) or
-                        (itemrec == {"pio_iids": [iid2, iid0, iid1, iid3]}))
-
-        try:
-            itemrec = client.get_itemrec(uid2, 10, engine_name)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": [iid3, iid0, iid1, iid2]}) or
-                        (itemrec == {"pio_iids": [iid3, iid1, iid0, iid2]}))
-
-        try:
-            itemrec = client.get_itemrec(uid3, 6, engine_name)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": [iid0, iid1, iid2, iid3]}) or
-                        (itemrec == {"pio_iids": [iid0, iid2, iid1, iid3]}))
-
-        # request less
-        try:
-            itemrec = client.get_itemrec(uid0, 1, engine_name)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2]})
-
-        try:
-            itemrec = client.get_itemrec(uid0, 2, engine_name)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3]})
-
-        # request with optional attributes
-
-        # pio_itypes
-        try:
-            itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t1", "t2"))
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-        # subset itypes
-        try:
-            itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t2",))
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid1]})
-
-        # nonexisting itypes
-        try:
-            client.get_itemrec(uid0, 10, engine_name, pio_itypes=("other-itype",))
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            pass  # expected no recommendation
-        except:
-            raise
-
-        # pio_attributes
-        try:
-            itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t1",),
-                                         pio_attributes=["custom1", "custom2"])
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0], "custom1": [None, None, "i1c1", "i0c1"],
-                                   "custom2": ["i2c2", None, "i1c2", None]})
-
-        client.close()
-
-    def test_get_itemrec(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        uid0 = "u0@u.n"
-        uid1 = "u1@u.n"
-        uid2 = "http://u2.com"
-        uid3 = "u3@u.n"
-
-        iid0 = "http://i0.com"
-        iid1 = "i1@i1"
-        iid2 = "i2.org"
-        iid3 = "i3"
-
-        engine_name = "itemrec"
-
-        # request more
-        client.identify(uid0)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 10)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-        client.identify(uid1)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 10)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": [iid2, iid1, iid0, iid3]}) or
-                        (itemrec == {"pio_iids": [iid2, iid0, iid1, iid3]}))
-
-        client.identify(uid2)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 10)
-        except predictionio.ItemRecNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": [iid3, iid0, iid1, iid2]}) or
-                        (itemrec == {"pio_iids": [iid3, iid1, iid0, iid2]}))
-
-        client.identify(uid3)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 6)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertTrue((itemrec == {"pio_iids": [iid0, iid1, iid2, iid3]}) or
-                        (itemrec == {"pio_iids": [iid0, iid2, iid1, iid3]}))
-
-        # request less
-        client.identify(uid0)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 1)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2]})
-
-        client.identify(uid0)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 2)
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3]})
-
-        # request with optional attributes
-
-        # pio_itypes
-        client.identify(uid0)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t1", "t2")})
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
-
-        # subset itypes
-        client.identify(uid0)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t2",)})
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid1]})
-
-        # nonexisting itypes
-        client.identify(uid0)
-        try:
-            client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("other-itype",)})
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            pass  # expected no recommendation
-        except:
-            raise
-
-        # pio_attributes
-        client.identify(uid0)
-        try:
-            itemrec = client.get_itemrec_topn(engine_name, 10,
-                                              {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
-        except predictionio.ItemRecNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemrec)
-
-        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0], "custom1": [None, None, "i1c1", "i0c1"],
-                                   "custom2": ["i2c2", None, "i1c2", None]})
-
-        # TODO pio_latlng
-        # TODO pio_within
-        # TODO pio_unit
-
-        client.close()
-
-
-if __name__ == "__main__":
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/predictionio_itemsim_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_itemsim_test.py b/tests-obsolete/predictionio_itemsim_test.py
deleted file mode 100644
index 45fa151..0000000
--- a/tests-obsolete/predictionio_itemsim_test.py
+++ /dev/null
@@ -1,200 +0,0 @@
-"""
-Test getting itemsim after algo training completes (pdio-itemsimcf with cosine sim).
-"""
-import unittest
-
-import predictionio
-
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
-API_URL = "http://localhost:8000"  # PredictoinIO Server
-
-DEBUG = True
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-
-class TestPredictionIO(unittest.TestCase):
-    def setUp(self):
-        pass
-
-    def tearDown(self):
-        pass
-
-    def test_get_itemsim_exception(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        try:
-            client.get_itemsim_topn("python-itemsim-engine", "iidwithoutsim", 10)
-        except predictionio.ItemSimNotFoundError as e:
-            pass  # expected exception
-        except:
-            raise
-
-        try:
-            client.get_itemsim_topn("python-itemsim-engine", "iidwithoutsim", 10,
-                                    {"pio_itypes": ("t1",), "pio_latlng": [1.34, 5.67], "pio_within": 5.0,
-                                     "pio_unit": "km", "pio_attributes": ["custom1", "custom2"]})
-        except predictionio.ItemSimNotFoundError as e:
-            if DEBUG:
-                print(e)
-            pass  # expected exception
-        except:
-            raise
-
-        client.close()
-
-    def test_get_itemsim(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        # request more than what is available
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i0", 10)
-        except predictionio.ItemSimNotFoundError as e:
-            print
-            "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertTrue((itemsim == {"pio_iids": ["i1", "i2", "i3"]}) or
-                        (itemsim == {"pio_iids": ["i1", "i3", "i2"]}))
-
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10)
-        except predictionio.ItemSimNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertTrue((itemsim == {"pio_iids": ["i2", "i3", "i0"]}))
-
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i2", 10)
-        except predictionio.ItemSimNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertTrue((itemsim == {"pio_iids": ["i1", "i3", "i0"]}))
-
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i3", 10)
-        except predictionio.ItemSimNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertTrue((itemsim == {"pio_iids": ["i1", "i2", "i0"]}))
-
-        # request less
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 1)
-        except predictionio.ItemSimNotFoundError as e:
-            print
-            "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertEqual(itemsim, {"pio_iids": ["i2"]})
-
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 2)
-        except predictionio.ItemSimNotFoundError as e:
-            print
-            "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertEqual(itemsim, {"pio_iids": ["i2", "i3"]})
-
-        # request with optional attributes
-
-        # pio_itypes
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t1", "t2")})
-        except predictionio.ItemSimNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertEqual(itemsim, {"pio_iids": ["i2", "i3", "i0"]})
-
-        # subset itypes
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t2",)})
-        except predictionio.ItemSimNotFoundError as e:
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertEqual(itemsim, {"pio_iids": ["i2"]})
-
-        # nonexisting itypes
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i0", 10, {"pio_itypes": ("other-itype",)})
-        except predictionio.ItemSimNotFoundError as e:
-            pass  # expected no recommendation
-        except:
-            raise
-
-        # pio_attributes
-        try:
-            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10,
-                                              {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
-        except predictionio.ItemSimNotFoundError as e:
-            print(e)
-            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
-            raise
-        except:
-            raise
-
-        if DEBUG:
-            print(itemsim)
-
-        self.assertEqual(itemsim, {"pio_iids": ["i2", "i3", "i0"], "custom1": [None, None, "i0c1"],
-                                   "custom2": ["i2c2", None, None]})
-
-        # TODO pio_latlng
-        # TODO pio_within
-        # TODO pio_unit
-
-        client.close()
-
-
-if __name__ == "__main__":
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests-obsolete/predictionio_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_test.py b/tests-obsolete/predictionio_test.py
deleted file mode 100644
index 696718c..0000000
--- a/tests-obsolete/predictionio_test.py
+++ /dev/null
@@ -1,257 +0,0 @@
-"""
-Test Python SDK
-"""
-import unittest
-
-import predictionio
-import time
-
-
-APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
-API_URL = "http://localhost:8000"  # PredictoinIO Server
-
-MIN_VERSION = '0.6.0'
-if predictionio.__version__ < MIN_VERSION:
-    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
-    raise Exception(err)
-
-# print predictionio.__version__
-# predictionio.connection.enable_log()
-
-
-class TestPredictionIO(unittest.TestCase):
-    def setUp(self):
-        pass
-
-    def tearDown(self):
-        pass
-
-    def test_status(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-        status = client.get_status()
-        self.assertEqual(status, "PredictionIO Output API is online.")
-        client.close()
-
-    def _test_user(self, uids):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        uid1 = uids[0]
-        uid2 = uids[1]
-        uid3 = uids[2]
-        uid4 = uids[3]
-        uid5 = uids[4]
-
-        # create users and get them back
-        client.create_user(uid1)
-        # create user with optional attributes
-        client.create_user(uid2, {"pio_latlng": [1.2, 33.3]})
-        client.create_user(uid3, {"pio_latlng": [4.5, 67.8], "pio_inactive": True})
-        # create user with custom attributes
-        client.create_user(uid4, {"pio_latlng": [1.2, 33.3], "custom1": "value1", "custom2": "value2"})
-        client.create_user(uid5, {"custom1": "u5c1", "custom2": "u5c2"})
-
-        user1 = client.get_user(uid1)
-        user2 = client.get_user(uid2)
-        user3 = client.get_user(uid3)
-        user4 = client.get_user(uid4)
-        user5 = client.get_user(uid5)
-
-        self.assertEqual(user1, {"pio_uid": uid1})
-        self.assertEqual(user2, {"pio_uid": uid2, "pio_latlng": [1.2, 33.3]})
-        self.assertEqual(user3, {"pio_uid": uid3, "pio_latlng": [4.5, 67.8], "pio_inactive": True})
-        self.assertEqual(user4, {"pio_uid": uid4, "pio_latlng": [1.2, 33.3], "custom1": "value1", "custom2": "value2"})
-        self.assertEqual(user5, {"pio_uid": uid5, "custom1": "u5c1", "custom2": "u5c2"})
-
-        # delete user and then try to get it
-        client.delete_user(uid1)
-
-        try:
-            client.get_user(uid1)
-        except predictionio.UserNotFoundError as e:  # noqa
-            pass  # expected exception
-        except:
-            raise
-
-        # other users still exist
-        user2 = client.get_user(uid2)
-        self.assertEqual(user2, {"pio_uid": uid2, "pio_latlng": [1.2, 33.3]})
-
-        # read, modify, write
-        user3 = client.get_user(uid3)
-        self.assertEqual(user3, {"pio_uid": uid3, "pio_latlng": [4.5, 67.8], "pio_inactive": True})
-        del user3["pio_uid"]
-        user3["pio_latlng"] = [5.6, 10.11]
-        user3["pio_inactive"] = False
-        user3["custom1"] = "food"
-        client.create_user(uid3, user3)
-        updated_user3 = client.get_user(uid3)
-        self.assertEqual(updated_user3,
-                         {"pio_uid": uid3, "pio_latlng": [5.6, 10.11], "pio_inactive": False, "custom1": "food"})
-
-        user4 = client.get_user(uid4)
-        self.assertEqual(user4, {"pio_uid": uid4, "pio_latlng": [1.2, 33.3], "custom1": "value1", "custom2": "value2"})
-        del user4["pio_uid"]
-        user4["custom1"] = "new value"
-        client.create_user(uid4, user4)
-        updated_user4 = client.get_user(uid4)
-        self.assertEqual(updated_user4,
-                         {"pio_uid": uid4, "pio_latlng": [1.2, 33.3], "custom1": "new value", "custom2": "value2"})
-
-        client.close()
-
-    def test_user(self):
-        self._test_user(["u1", "u2", "u3", "u4", "u5"])
-        # test special characters in uid
-        self._test_user(["u1@a.com", "u2@ap/ple", "u3@foo.bar", "u4/a/b", "&^%$()u5"])
-
-    def _test_item(self, iids):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        iid1 = iids[0]
-        iid2 = iids[1]
-        iid3 = iids[2]
-        iid4 = iids[3]
-        iid5 = iids[4]
-
-        # create items and read back
-        client.create_item(iid1, ("t1", "t2", "t3"))
-        client.create_item(iid2, ("t1",))
-        client.create_item(iid3, ("t2",),
-                           {"pio_price": 4.99, "pio_profit": 2.0, "pio_startT": 12345667, "pio_endT": 4567788,
-                            "pio_latlng": [1.345, 9.876], "pio_inactive": True})
-        client.create_item(iid4, ("t2",), {"pio_latlng": [1.2345, 10.11], "custom1": "value1"})
-        client.create_item(iid5, ("t1", "t2"), {"custom1": "i5value1", "custom2": "i5value2"})
-
-        item1 = client.get_item(iid1)
-        item2 = client.get_item(iid2)
-        item3 = client.get_item(iid3)
-        item4 = client.get_item(iid4)
-        item5 = client.get_item(iid5)
-
-        del item1["pio_startT"]  # pio_startT is automatically inserted, don't compare
-        self.assertEqual(item1, {"pio_iid": iid1, "pio_itypes": ("t1", "t2", "t3")})
-        del item2["pio_startT"]
-        self.assertEqual(item2, {"pio_iid": iid2, "pio_itypes": ("t1",)})
-        self.assertEqual(item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 4.99, "pio_profit": 2.0,
-                                 "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876],
-                                 "pio_inactive": True})
-        del item4["pio_startT"]
-        self.assertEqual(item4,
-                         {"pio_iid": iid4, "pio_itypes": ("t2",), "pio_latlng": [1.2345, 10.11], "custom1": "value1"})
-        del item5["pio_startT"]
-        self.assertEqual(item5,
-                         {"pio_iid": iid5, "pio_itypes": ("t1", "t2"), "custom1": "i5value1", "custom2": "i5value2"})
-
-        # delete and then try to get it
-        client.delete_item(iid2)
-
-        try:
-            item2 = client.get_item(iid2)
-        except predictionio.ItemNotFoundError as e:  # noqa
-            pass  # expected exception
-        except:
-            raise
-
-        # others still exist
-        item3 = client.get_item(iid3)
-        self.assertEqual(item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 4.99, "pio_profit": 2.0,
-                                 "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876],
-                                 "pio_inactive": True})
-
-        # read, modify, write
-        del item3["pio_iid"]
-        item3_itypes = item3.pop("pio_itypes")
-        item3["pio_price"] = 6.99
-        item3["custom1"] = "some value"
-        client.create_item(iid3, item3_itypes, item3)
-        updated_item3 = client.get_item(iid3)
-        self.assertEqual(updated_item3, {"pio_iid": iid3, "pio_itypes": ("t2",), "pio_price": 6.99, "pio_profit": 2.0,
-                                         "pio_startT": 12345667, "pio_endT": 4567788, "pio_latlng": [1.345, 9.876],
-                                         "pio_inactive": True, "custom1": "some value"})
-
-        client.close()
-
-    def test_item(self):
-        self._test_item(["i1", "i2", "i3", "i4", "i5"])
-        # test special characters in iid
-        self._test_item(["i1@abc.com", "i2/f/bar//@@foo", "$$i3%%$~~", "http://www.i4.com", "``i5/apple/"])
-
-    def test_u2iAction_deprecated(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.user_like_item("u1", "i1")
-        client.user_dislike_item("u2", "i2")
-        client.user_view_item("u3", "i3")
-        client.user_rate_item("u4", "i4", 4)
-        client.user_conversion_item("u5", "i5")
-
-        client.close()
-
-    def test_u2iAction(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.identify("u101")
-
-        # required param
-        client.record_action_on_item("like", "i1")
-        client.record_action_on_item("dislike", "i2")
-        client.record_action_on_item("view", "i3")
-        client.record_action_on_item("rate", "i4", {"pio_rate": 1})
-        client.record_action_on_item("conversion", "i5")
-
-        client.identify("u102")
-
-        # with optional param
-        client.record_action_on_item("like", "i1", {"pio_latlng": [1.23, 4.56]})
-        client.record_action_on_item("dislike", "i2", {"pio_t": 1234567689})
-        client.record_action_on_item("view", "i3", {"pio_latlng": [4.67, 1.44], "pio_t": 3445566778})
-        client.record_action_on_item("rate", "i4", {"pio_rate": 1, "pio_latlng": [66.78, 9.10]})
-        client.record_action_on_item("conversion", "i5", {"pio_price": 12.5})
-
-        # uid and iid with special characters
-        client.identify("u1@a.com")
-        client.record_action_on_item("view", "i3@bb.com")
-        client.record_action_on_item("view", "http://www.yahoo.com")
-
-        client.close()
-
-    def test_pending_requests(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL)
-
-        client.identify("u111")
-        for i in range(100):
-            client.arecord_action_on_item("like", str(i))
-
-        n = 1
-        while n > 0:
-            n = client.pending_requests()
-            time.sleep(0.1)
-            # print n
-
-        client.close()
-
-    def test_qsize(self):
-        client = predictionio.Client(APP_KEY, 1, API_URL, qsize=10)
-
-        client.identify("u222")
-        for i in range(100):
-            client.arecord_action_on_item("like", str(i))
-
-        n = 1
-        while n > 0:
-            n = client.pending_requests()
-            time.sleep(0.1)
-            # print n
-
-        client.close()
-
-
-"""
-to run individual test:
-$ python -m unittest predictionio_test.TestPredictionIO.test_user
-
-to run ALL tests:
-% python predictionio_test.py
-"""
-if __name__ == "__main__":
-    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests/.keep
----------------------------------------------------------------------
diff --git a/tests/.keep b/tests/.keep
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests/after_script.travis.sh
----------------------------------------------------------------------
diff --git a/tests/after_script.travis.sh b/tests/after_script.travis.sh
new file mode 100755
index 0000000..e2ea03f
--- /dev/null
+++ b/tests/after_script.travis.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+cd predictionio-setup
+./bin/pio-setup stop
+

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests/before_script.travis.sh
----------------------------------------------------------------------
diff --git a/tests/before_script.travis.sh b/tests/before_script.travis.sh
new file mode 100755
index 0000000..a38a6ee
--- /dev/null
+++ b/tests/before_script.travis.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+mkdir -p predictionio-setup/bin
+cd predictionio-setup
+curl -o bin/pio-setup https://raw.githubusercontent.com/jpioug/predictionio-setup/master/bin/pio-setup
+chmod +x bin/pio-setup
+
+PIO_GIT_USER=apache PIO_GIT_BRANCH=develop PIO_EVENTDATA_REFRESH=true ./bin/pio-setup deploy
+touch target/pio-setup.log
+tail -f target/pio-setup.log &
+
+counter=1
+ret=7
+while [ $ret = 7 -a $counter != 10 ] ; do
+  ./bin/pio-setup start
+  sleep 5
+  curl -v 127.0.0.1:7070/events.json
+  ret=$?
+  echo "Checking Java processes..."
+  ps aux | grep java
+  echo "Checking 7070 port..."
+  netstat | grep 7070
+  counter=`expr $counter + 1`
+done
+
+./bin/pio-setup status
+tail -f ~/pio.log &

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests/engineclient_test.py
----------------------------------------------------------------------
diff --git a/tests/engineclient_test.py b/tests/engineclient_test.py
new file mode 100644
index 0000000..276328b
--- /dev/null
+++ b/tests/engineclient_test.py
@@ -0,0 +1,48 @@
+import random
+import subprocess
+import unittest
+
+from predictionio import EventClient
+
+app_name ='EngineClientApp'
+access_key = 'FILE_EXPORT_TEST'
+
+class EngineClientTest(unittest.TestCase):
+
+    def setUp(self):
+        subprocess.call(['pio', 'app', 'new', '--access-key', access_key, app_name])
+
+    def tearDown(self):
+        subprocess.call(['pio', 'app', 'delete', '-f', app_name])
+
+    def test_query(self):
+        random.seed()
+
+        client = EventClient(access_key=access_key, url="http://127.0.0.1:7070")
+
+        # Check status
+        print("Check status")
+        print(client.get_status())
+        self.assertEqual(client.get_status(), {'status': 'alive'})
+
+        user_ids = [str(i) for i in range(1, 3)]
+        for user_id in user_ids:
+            print("Set user", user_id)
+            client.set_user(user_id)
+            # TODO assert
+
+        item_ids = [str(i) for i in range(1, 5)]
+        for item_id in item_ids:
+            print("Set item", item_id)
+            client.set_item(item_id, {"itypes": ['1']})
+            # TODO assert
+
+            # each user randomly views 10 items
+            for user_id in user_ids:
+                for viewed_item in random.sample(item_ids, 2):
+                    print("User", user_id, "views item", viewed_item)
+                    client.record_user_action_on_item("view", user_id, viewed_item)
+                    # TODO assert
+
+        client.close()
+

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests/eventclient_test.py
----------------------------------------------------------------------
diff --git a/tests/eventclient_test.py b/tests/eventclient_test.py
new file mode 100644
index 0000000..900c48b
--- /dev/null
+++ b/tests/eventclient_test.py
@@ -0,0 +1,251 @@
+import pytz
+import subprocess
+import unittest
+
+from datetime import datetime
+from predictionio import EventClient
+from predictionio import NotFoundError
+
+app_name ='EventClientApp'
+access_key = 'EVENT_CLIENT_TEST'
+channel = 'Test'
+
+class EventClientTest(unittest.TestCase):
+
+    def setUp(self):
+        subprocess.call(['pio', 'app', 'new', '--access-key', access_key, app_name])
+        subprocess.call(['pio', 'app', 'show', app_name])
+
+    def tearDown(self):
+        subprocess.call(['pio', 'app', 'delete', '-f', app_name])
+
+    def test_eventclient(self):
+        client = EventClient(access_key=access_key, url="http://127.0.0.1:7070")
+
+        # Check status
+        print("Check status")
+        print(client.get_status())
+        self.assertEqual(client.get_status(), {'status': 'alive'})
+
+        # First event
+        first_event_properties = {
+            "prop1": 1,
+            "prop2": "value2",
+            "prop3": [1, 2, 3],
+            "prop4": True,
+            "prop5": ["a", "b", "c"],
+            "prop6": 4.56,
+        }
+        first_event_time = datetime(
+            2004, 12, 13, 21, 39, 45, 618000, pytz.timezone('US/Mountain'))
+        first_event_response = client.create_event(
+            event="my_event",
+            entity_type="user",
+            entity_id="uid",
+            properties=first_event_properties,
+            event_time=first_event_time,
+        )
+        print("First Event response")
+        print(first_event_response)
+        self.assertEqual(first_event_response.status, 201)
+
+        # Second event
+        second_event_properties = {
+            "someProperty": "value1",
+            "anotherProperty": "value2",
+        }
+        second_event_response = client.create_event(
+            event="my_event",
+            entity_type="user",
+            entity_id="uid",
+            target_entity_type="item",
+            target_entity_id="iid",
+            properties=second_event_properties,
+            event_time=datetime(2014, 12, 13, 21, 38, 45, 618000, pytz.utc))
+        print("Second Event response")
+        print(second_event_response)
+        self.assertEqual(second_event_response.status, 201)
+
+
+        # Get the first event from Event Server
+        first_event_id = first_event_response.json_body["eventId"]
+        print("Get Event")
+        event = client.get_event(first_event_id)
+        print(event)
+        self.assertEqual(event.get('eventId'), first_event_id)
+
+
+        # Delete the first event from Event Server
+        print("Delete Event")
+        delete_response = client.delete_event(first_event_id)
+        print(delete_response)
+        self.assertEqual(delete_response.decode('utf-8'), '{"message":"Found"}')
+
+
+        # Delete the first event from Event Server again should yield exception.
+        print("Delete Event Again")
+        try:
+            delete_response = client.delete_event(first_event_id)
+            self.fail()
+        except NotFoundError as ex:
+            print("The expected error: {0}".format(ex))
+
+
+        # "user"-helper methods
+
+        # Set user properties implicitly create a user
+        # This call creates a user "foo", and set the properties of "foo".
+        print("Create user foo")
+        foo_properties = {"city": "sunnyvale", "car": "honda fit"}
+        response = client.set_user("foo", properties=foo_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # This call overrides the existing properties for user "foo", setting "car" to
+        # a new "honda odyssey" and create a new property "food" to "seafood".
+        print("Set new properties")
+        foo_properties = {"car": "honda odyssey", "food": "seafood"}
+        response = client.set_user("foo", properties=foo_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # This call removes the specified properties. It ignores the value of the dict.
+        # After this call, the "city" will become an unset field.
+        print("Unset properties")
+        foo_properties = {"city": "x"}
+        response = client.unset_user("foo", properties=foo_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # This call deletes a user
+        print("Delete user")
+        response = client.delete_user("foo")
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # The SDK also support specifying the eventTime. It is useful for importing
+        # events happened in the past.
+        foo_time = datetime(2014, 8, 31, 4, 56, tzinfo=pytz.timezone('US/Pacific'))
+        print("Create user at " + str(foo_time))
+        response = client.set_user("Jarvis", {}, foo_time)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # "item"-helper methods
+
+        # Set item properties implicitly create a item
+        # This call creates a item "bar", and set the properties of "bar".
+        print("Create item bar")
+        bar_properties = {"city": "santa clara", "weight": 6.9}
+        response = client.set_item("bar", properties=bar_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # Similar to user-methods, we can do the same thing with item
+        print("Set new properties")
+        bar_properties = {"weight": 6.2}
+        response = client.set_item("bar", properties=bar_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # This call removes the specified properties. It ignores the value of the dict.
+        # After this call, the "city" will become an unset field.
+        print("Unset properties")
+        bar_properties = {"city": None}
+        response = client.unset_item("bar", properties=bar_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+        # This call deletes a item
+        print("Delete item")
+        response = client.delete_item("bar")
+        print(response)
+        self.assertEqual(response.status, 201)
+
+
+        # "record" action helper functions
+
+        # This call creates a event between a user and an item. In particular, this set
+        # the price of the action
+        print("Record user action")
+        action_properties = {"price": 10.0}
+        response = client.record_user_action_on_item("buy", "foo", "bar", action_properties)
+        print(response)
+        self.assertEqual(response.status, 201)
+
+
+    def test_eventclient_channel(self):
+        subprocess.call(['pio', 'app', 'channel-new', app_name, channel])
+
+        client = EventClient(access_key=access_key, url="http://127.0.0.1:7070",
+                             channel=channel)
+
+        # Check status
+        print("Check status")
+        print(client.get_status())
+        self.assertEqual(client.get_status(), {'status': 'alive'})
+
+        # First event
+        first_event_properties = {
+            "prop1" : 1,
+            "prop2" : "value2",
+            "prop3" : [1, 2, 3],
+            "prop4" : True,
+            "prop5" : ["a", "b", "c"],
+            "prop6" : 4.56 ,
+            }
+        first_event_time = datetime(
+            2004, 12, 13, 21, 39, 45, 618000, pytz.timezone('US/Mountain'))
+        first_event_response = client.create_event(
+            event="my_event",
+            entity_type="user",
+            entity_id="uid",
+            properties=first_event_properties,
+            event_time=first_event_time,
+            )
+        print("First Event response")
+        print(first_event_response)
+        self.assertEqual(first_event_response.status, 201)
+
+        # Second event
+        second_event_properties = {
+            "someProperty" : "value1",
+            "anotherProperty" : "value2",
+            }
+        second_event_response = client.create_event(
+            event="my_event",
+            entity_type="user",
+            entity_id="uid",
+            target_entity_type="item",
+            target_entity_id="iid",
+            properties=second_event_properties,
+            event_time=datetime(2014, 12, 13, 21, 38, 45, 618000, pytz.utc))
+        print("Second Event response")
+        print(second_event_response)
+        self.assertEqual(second_event_response.status, 201)
+
+
+        # Get the first event from Event Server
+        first_event_id = first_event_response.json_body["eventId"]
+        print("Get Event")
+        event = client.get_event(first_event_id)
+        print(event)
+        self.assertEqual(event.get('eventId'), first_event_id)
+
+        # Delete the first event from Event Server
+        print("Delete Event")
+        delete_response = client.delete_event(first_event_id)
+        print(delete_response)
+        self.assertEqual(delete_response.decode('utf-8'), '{"message":"Found"}')
+
+        # Delete the first event from Event Server again should yield exception.
+        print("Delete Event Again")
+        try:
+            delete_response = client.delete_event(first_event_id)
+            self.fail()
+        except NotFoundError as ex:
+            print("The expected error: {0}".format(ex))
+
+
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tests/fileexport_test.py
----------------------------------------------------------------------
diff --git a/tests/fileexport_test.py b/tests/fileexport_test.py
new file mode 100644
index 0000000..0fad97e
--- /dev/null
+++ b/tests/fileexport_test.py
@@ -0,0 +1,74 @@
+import pytz
+import re
+import subprocess
+import unittest
+
+from datetime import datetime
+import predictionio
+from predictionio import EventClient
+
+app_name ='FileExporterApp'
+access_key = 'FILE_EXPORT_TEST'
+filename = 'export_events.json'
+
+class FileExporterTest(unittest.TestCase):
+
+    def setUp(self):
+        subprocess.call(['pio', 'app', 'new', '--access-key', access_key, app_name])
+
+    def tearDown(self):
+        subprocess.call(['pio', 'app', 'delete', '-f', app_name])
+
+    def test_export(self):
+        app_info = subprocess.check_output(['pio', 'app', 'show', app_name])
+        app_id = re.search('App ID: ([0-9]+)', app_info.decode('utf-8')).group(1)
+        print(app_id)
+
+        exporter = predictionio.FileExporter(file_name=filename)
+
+        first_event_properties = {
+            "prop1" : 1,
+            "prop2" : "value2",
+            "prop3" : [1, 2, 3],
+            "prop4" : True,
+            "prop5" : ["a", "b", "c"],
+            "prop6" : 4.56 ,
+            }
+        first_event_time = datetime(
+            2004, 12, 13, 21, 39, 45, 618000, pytz.timezone('US/Mountain'))
+        exporter.create_event(
+            event="my_event",
+            entity_type="user",
+            entity_id="uid",
+            properties=first_event_properties,
+            event_time=first_event_time,
+            )
+
+        # Second event
+        second_event_properties = {
+            "someProperty" : "value1",
+            "anotherProperty" : "value2",
+            }
+        exporter.create_event(
+            event="my_event",
+            entity_type="user",
+            entity_id="uid",
+            target_entity_type="item",
+            target_entity_id="iid",
+            properties=second_event_properties,
+            event_time=datetime(2014, 12, 13, 21, 38, 45, 618000, pytz.utc))
+
+        exporter.close()
+
+        subprocess.call(['pio', 'import', '--appid', app_id, '--input ', filename])
+
+        # TODO
+        # client = EventClient(access_key=access_key, url="http://127.0.0.1:7070")
+        #
+        # print("Get Event")
+        # event = client.get_event(event_id)
+        # print(event)
+        # self.assertEqual(event.get('eventId'), event_id)
+
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8e35e33d/tox.ini
----------------------------------------------------------------------
diff --git a/tox.ini b/tox.ini
index 87b57e9..6f5cd20 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,13 +1,12 @@
 [tox]
-envlist = py27,py34
+envlist = py27,py34,py35,py36
 
 [testenv]
 deps = flake8
-       pandas
+passenv = HOME TRAVIS*
+commands = python -m unittest discover --pattern=*.py tests
 
 [flake8]
 ignore = E111
 
-
 commands = flake8 --ignore=E501 --filename=*.py --exclude=doc,setup.py,*/tests/*
-           python -m unittest discover --pattern=*.py tests


[21/24] incubator-predictionio-sdk-python git commit: Update project info

Posted by sh...@apache.org.
Update project info

Closes #23


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/a71d14eb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/a71d14eb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/a71d14eb

Branch: refs/heads/master
Commit: a71d14eb656da38599c71553e31645ec6c9d5f7b
Parents: 579ab32
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Mon Sep 18 09:42:22 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Mon Sep 18 09:42:22 2017 +0900

----------------------------------------------------------------------
 LICENSE.txt | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 setup.py    |  10 +--
 2 files changed, 204 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/a71d14eb/LICENSE.txt
----------------------------------------------------------------------
diff --git a/LICENSE.txt b/LICENSE.txt
index 11c8530..d645695 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,13 +1,202 @@
-Copyright 2013 TappingStone Inc.
 
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
 
-    http://www.apache.org/licenses/LICENSE-2.0
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/a71d14eb/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index eeafe17..f34003f 100644
--- a/setup.py
+++ b/setup.py
@@ -3,9 +3,9 @@ try:
 except ImportError:
     from distutils.core import setup
 
-__author__ = "The PredictionIO Team"
-__email__ = "help@tappingstone.com"
-__copyright__ = "Copyright 2014, TappingStone, Inc."
+__author__ = "Apache PredictionIO"
+__email__ = "user@predictionio.incubator.apache.org"
+__copyright__ = "Copyright 2017 The Apache Software Foundation"
 __license__ = "Apache License, Version 2.0"
 
 setup(
@@ -14,7 +14,7 @@ setup(
     author=__author__,
     author_email=__email__,
     packages=['predictionio'],
-    url='http://prediction.io',
+    url='http://predictionio.incubator.apache.org/',
     license='LICENSE.txt',
     description='PredictionIO Python SDK',
     classifiers=[
@@ -44,7 +44,7 @@ setup(
                        - without worrying about scalability
 
                        Detailed documentation is available on our
-                       `documentation site <http://docs.prediction.io>`_.
+                       `documentation site <http://predictionio.incubator.apache.org/>`_.
 
                        This module provides convenient access of the
                        PredictionIO API to Python programmers so that they


[17/24] incubator-predictionio-sdk-python git commit: add test case and remove unused imports

Posted by sh...@apache.org.
add test case and remove unused imports


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/88a11a84
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/88a11a84
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/88a11a84

Branch: refs/heads/master
Commit: 88a11a84eac281c06b9a29fa90323ff4c706401e
Parents: a151e0c
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Sun Sep 10 23:16:45 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Sun Sep 10 23:16:45 2017 +0900

----------------------------------------------------------------------
 predictionio/__init__.py  | 2 --
 tests/eventclient_test.py | 8 ++++++++
 2 files changed, 8 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/88a11a84/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index d70c85c..c067689 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -28,14 +28,12 @@ except ImportError:
   from urllib.parse import quote
 
 import json
-import urllib
 
 from datetime import datetime
 import pytz
 
 from predictionio.connection import Connection
 from predictionio.connection import AsyncRequest
-from predictionio.connection import AsyncResponse
 from predictionio.connection import PredictionIOAPIError
 
 

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/88a11a84/tests/eventclient_test.py
----------------------------------------------------------------------
diff --git a/tests/eventclient_test.py b/tests/eventclient_test.py
index 900c48b..ac8a72d 100644
--- a/tests/eventclient_test.py
+++ b/tests/eventclient_test.py
@@ -5,6 +5,7 @@ import unittest
 from datetime import datetime
 from predictionio import EventClient
 from predictionio import NotFoundError
+from predictionio import InvalidArgumentError
 
 app_name ='EventClientApp'
 access_key = 'EVENT_CLIENT_TEST'
@@ -246,6 +247,13 @@ class EventClientTest(unittest.TestCase):
         except NotFoundError as ex:
             print("The expected error: {0}".format(ex))
 
+    def test_invalidurl(self):
+        try:
+            EventClient(access_key=access_key, url="invalid")
+            self.fail()
+        except InvalidArgumentError as ex:
+            print("The expected error: {0}".format(ex))
+
 
 if __name__ == "__main__":
     unittest.main()


[24/24] incubator-predictionio-sdk-python git commit: Merge remote-tracking branch 'apache/release/0.9.9'

Posted by sh...@apache.org.
Merge remote-tracking branch 'apache/release/0.9.9'


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/903b2f6e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/903b2f6e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/903b2f6e

Branch: refs/heads/master
Commit: 903b2f6e76cb3fbfc05c99e971c2bfa08e3bdc40
Parents: 41d0c11 4d8c843
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Wed Oct 25 22:49:39 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Wed Oct 25 22:49:39 2017 +0900

----------------------------------------------------------------------
 .DS_Store                                       |  Bin 6148 -> 0 bytes
 .gitignore                                      |    5 +
 .travis.yml                                     |   34 +
 LICENSE.txt                                     |  209 ++-
 README.txt                                      |  122 +-
 docs/source/conf.py                             |  110 +-
 examples/demo-movielens/appdata.py              |  316 ++---
 examples/demo-movielens/batch_import.py         |  246 ++--
 examples/event_sample.py                        |   48 +-
 examples/import_yahoo.py                        |  261 ++--
 examples/itemrank_quick_query.py                |   18 +-
 examples/itemrank_quick_start.py                |   69 +-
 examples/obsolete/__init__.py                   |    0
 examples/obsolete/itemrec/__init__.py           |    0
 examples/obsolete/itemrec/movies/.gitignore     |    3 -
 examples/obsolete/itemrec/movies/README.md      |   15 -
 examples/obsolete/itemrec/movies/__init__.py    |    0
 examples/obsolete/itemrec/movies/app_config.py  |    2 -
 examples/obsolete/itemrec/movies/appdata.py     |  148 ---
 .../obsolete/itemrec/movies/batch_import.py     |   65 -
 .../obsolete/itemrec/movies/movie_rec_app.py    |  152 ---
 predictionio/__init__.py                        |  115 +-
 predictionio/connection.py                      |  537 ++++----
 predictionio/obsolete.py                        | 1205 ------------------
 setup.py                                        |   42 +-
 tests/after_script.travis.sh                    |    5 +
 tests/before_script.travis.sh                   |   27 +
 tests/conversion_test.py                        |   23 -
 tests/engineclient_test.py                      |   48 +
 tests/eventclient_test.py                       |  259 ++++
 tests/fileexport_test.py                        |   74 ++
 tests/import_testdata.py                        |   52 -
 tests/import_testdata_id_mismatch.py            |   52 -
 tests/import_testdata_special_char.py           |   52 -
 tests/predictionio_itemrec_test.py              |  300 -----
 tests/predictionio_itemrec_test_special_char.py |  291 -----
 tests/predictionio_itemsim_test.py              |  160 ---
 tests/predictionio_test.py                      |  246 ----
 tox.ini                                         |   12 +
 39 files changed, 1638 insertions(+), 3685 deletions(-)
----------------------------------------------------------------------



[23/24] incubator-predictionio-sdk-python git commit: update to 0.9.9 in __init__.py and remove incubator

Posted by sh...@apache.org.
update to 0.9.9 in __init__.py and remove incubator


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/4d8c843e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/4d8c843e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/4d8c843e

Branch: refs/heads/master
Commit: 4d8c843e3f7d940c8df01b2295d086857391ae40
Parents: 72a5092
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Fri Oct 20 22:12:44 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Fri Oct 20 22:12:44 2017 +0900

----------------------------------------------------------------------
 README.txt               | 2 +-
 predictionio/__init__.py | 2 +-
 setup.py                 | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/4d8c843e/README.txt
----------------------------------------------------------------------
diff --git a/README.txt b/README.txt
index 4740ff5..9a7da1d 100644
--- a/README.txt
+++ b/README.txt
@@ -48,7 +48,7 @@ To view the generated documentation, go to docs/build/html/index.html.
 SUPPORT
 =======
 
-http://predictionio.incubator.apache.org/support/
+http://predictionio.apache.org/support/
 
 
 Issue Tracker

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/4d8c843e/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 3ef8d96..a20f4cc 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -4,7 +4,7 @@ Python applications with PredictionIO REST API services.
 """
 
 
-__version__ = "0.9.8"
+__version__ = "0.9.9"
 
 # import packages
 import re

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/4d8c843e/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index fd735a0..968a9e5 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@ except ImportError:
     from distutils.core import setup
 
 __author__ = "Apache PredictionIO"
-__email__ = "user@predictionio.incubator.apache.org"
+__email__ = "user@predictionio.apache.org"
 __copyright__ = "Copyright 2017 The Apache Software Foundation"
 __license__ = "Apache License, Version 2.0"
 
@@ -14,7 +14,7 @@ setup(
     author=__author__,
     author_email=__email__,
     packages=['predictionio'],
-    url='http://predictionio.incubator.apache.org/',
+    url='http://predictionio.apache.org/',
     license='LICENSE.txt',
     description='PredictionIO Python SDK',
     classifiers=[
@@ -44,7 +44,7 @@ setup(
                        - without worrying about scalability
 
                        Detailed documentation is available on our
-                       `documentation site <http://predictionio.incubator.apache.org/>`_.
+                       `documentation site <http://predictionio.apache.org/>`_.
 
                        This module provides convenient access of the
                        PredictionIO API to Python programmers so that they


[06/24] incubator-predictionio-sdk-python git commit: Get events from Event Server.

Posted by sh...@apache.org.
Get events from Event Server.

    :param startTime: time in ISO8601 format. Return events with eventTime >= startTime.
    :param untilTime: time in ISO8601 format. Return events with eventTime < untilTime.
    :param entityId: String. The entityId. Return events for this entityId only.
    :param limit: Integer. The number of record events returned. Default is 20. -1 to get all.
    :param reversed: Boolean. Must be used with both entityType and entityId specified,
      returns events in reversed chronological order. Default is false.


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/8bdf59f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/8bdf59f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/8bdf59f7

Branch: refs/heads/master
Commit: 8bdf59f7c4bcddffbe2b155e5c05d6c855647bf5
Parents: c8dda1a
Author: Nguyen Viet Anh <vi...@gmail.com>
Authored: Mon Jul 27 16:26:33 2015 +0700
Committer: Nguyen Viet Anh <vi...@gmail.com>
Committed: Mon Jul 27 16:26:33 2015 +0700

----------------------------------------------------------------------
 predictionio/__init__.py | 52 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/8bdf59f7/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 8f40a4f..01b7cc2 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -286,6 +286,58 @@ class EventClient(BaseClient):
     """Synchronouly get an event from Event Server."""
     return self.aget_event(event_id).get_response()
 
+  def aget_events(self, startTime=None, untilTime=None, entityType=None, entityId=None, limit=None, reversed=False):
+    """Asynchronouly get events from Event Server.
+
+    :param startTime: time in ISO8601 format. Return events with eventTime >= startTime.
+    :param untilTime: time in ISO8601 format. Return events with eventTime < untilTime.
+    :param entityId: String. The entityId. Return events for this entityId only.
+    :param limit: Integer. The number of record events returned. Default is 20. -1 to get all.
+    :param reversed: Boolean. Must be used with both entityType and entityId specified,
+      returns events in reversed chronological order. Default is false.
+
+    :returns:
+      AsyncRequest object.
+    """
+    qparam = {
+        "accessKey" : self.access_key,
+        "reversed": reversed
+      }
+
+    if startTime is not None:
+      qparam["startTime"] = startTime
+
+    if untilTime is not None:
+      qparam["untilTime"] = untilTime
+
+    if entityType is not None:
+      qparam["entityType"] = entityType
+
+    if entityId is not None:
+      qparam["entityId"] = entityId
+
+    if limit is not None:
+      qparam["limit"] = limit
+
+    if self.channel is not None:
+      qparam["channel"] = self.channel
+    path = "/events.json"
+    request = AsyncRequest("GET", path, **qparam)
+    request.set_rfunc(self._aget_resp)
+    self._connection.make_request(request)
+    return request
+
+  def get_events(self, startTime=None, untilTime=None, entityType=None, entityId=None, limit=None, reversed=False):
+    """Synchronouly get event from Event Server."""
+    return self.aget_events(
+      startTime=startTime,
+      untilTime=untilTime,
+      entityType=entityType,
+      entityId=entityId,
+      limit=limit,
+      reversed=reversed
+    ).get_response()
+
   def adelete_event(self, event_id):
     """Asynchronouly delete an event from Event Server.
 


[02/24] incubator-predictionio-sdk-python git commit: Fixed indentation Deleted obsolete examples Moved obsolete test suite to 'test-obsolete' (port as we go) Added tox test bootstrapping Ignored pycharm, test output Removed obsolete (<0.8) support PEP8/

Posted by sh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/predictionio/obsolete.py
----------------------------------------------------------------------
diff --git a/predictionio/obsolete.py b/predictionio/obsolete.py
deleted file mode 100644
index dc19a09..0000000
--- a/predictionio/obsolete.py
+++ /dev/null
@@ -1,1205 +0,0 @@
-# import packages
-import re
-try:
-  import httplib
-except ImportError:
-  # pylint: disable=F0401
-  # http is a Python3 module, replacing httplib
-  from http import client as httplib
-import json
-import urllib
-import warnings
-
-from predictionio.connection import Connection
-from predictionio.connection import AsyncRequest
-from predictionio.connection import PredictionIOAPIError
-
-"""Error exception defined for this API
-
-Should be handled by the user
-"""
-
-
-class ServerStatusError(PredictionIOAPIError):
-
-  "Error happened when tried to get status of the API server"
-  pass
-
-
-class UserNotCreatedError(PredictionIOAPIError):
-
-  "Error happened when tried to create user"
-  pass
-
-
-class UserNotFoundError(PredictionIOAPIError):
-
-  "Error happened when tried to get user"
-  pass
-
-
-class UserNotDeletedError(PredictionIOAPIError):
-
-  "Error happened when tried to delete user"
-  pass
-
-
-class ItemNotCreatedError(PredictionIOAPIError):
-
-  "Error happened when tried to create item"
-  pass
-
-
-class ItemNotFoundError(PredictionIOAPIError):
-
-  "Error happened when tried to get item"
-  pass
-
-
-class ItemNotDeletedError(PredictionIOAPIError):
-
-  "Error happened when tried to delete item"
-  pass
-
-
-class U2IActionNotCreatedError(PredictionIOAPIError):
-
-  "Error happened when tried to create user-to-item action"
-  pass
-
-
-class ItemRecNotFoundError(PredictionIOAPIError):
-
-  "Error happened when tried to get item recommendation"
-  pass
-
-
-class ItemSimNotFoundError(PredictionIOAPIError):
-
-  "Error happened when tried to get similar items"
-  pass
-
-class ItemRankNotFoundError(PredictionIOAPIError):
-
-  "Error happened when treid to rank item"
-  pass
-
-class InvalidArgumentError(PredictionIOAPIError):
-
-  "Arguments are not valid"
-  pass
-
-# map to API
-LIKE_API = "like"
-DISLIKE_API = "dislike"
-VIEW_API = "view"
-CONVERSION_API = "conversion"
-RATE_API = "rate"
-
-
-class Client(object):
-
-  """PredictionIO client object.
-
-  This is an object representing a PredictionIO's client. This object
-  provides methods for making PredictionIO API requests.
-
-  :param appkey: the App Key provided by PredictionIO.
-  :param threads: number of threads to handle PredictionIO API requests.
-          Must be >= 1.
-  :param apiurl: the PredictionIO API URL path.
-  :param apiversion: the PredictionIO API version. (optional)
-       (eg. "", or "/v1")
-  :param qsize: the max size of the request queue (optional).
-      The asynchronous request becomes blocking once this size has been
-      reached, until the queued requests are handled.
-      Default value is 0, which means infinite queue size.
-  :param timeout: timeout for HTTP connection attempts and requests in
-    seconds (optional).
-    Default value is 5.
-
-  """
-
-  def __init__(self, appkey, threads=1, apiurl="http://localhost:8000",
-         apiversion="", qsize=0, timeout=5):
-    """Constructor of Client object.
-
-    """
-    warnings.warn("predictionio.Client is deprecated. " + 
-      "Please consider upgrading to our latest version.")
-
-    self.appkey = appkey
-    self.threads = threads
-    self.apiurl = apiurl
-    self.apiversion = apiversion
-    self.qsize = qsize
-    self.timeout = timeout
-
-    # check connection type
-    https_pattern = r'^https://(.*)'
-    http_pattern = r'^http://(.*)'
-    m = re.match(https_pattern, apiurl)
-    self.https = True
-    if m is None:  # not matching https
-      m = re.match(http_pattern, apiurl)
-      self.https = False
-      if m is None:  # not matching http either
-        raise InvalidArgumentError("apiurl is not valid: %s" % apiurl)
-    self.host = m.group(1)
-
-    self._uid = None  # identified uid
-    self._connection = Connection(host=self.host, threads=self.threads,
-                    qsize=self.qsize, https=self.https,
-                    timeout=self.timeout)
-
-  def close(self):
-    """Close this client and the connection.
-
-    Call this method when you want to completely terminate the connection
-    with PredictionIO.
-    It will wait for all pending requests to finish.
-    """
-    self._connection.close()
-
-  def pending_requests(self):
-    """Return the number of pending requests.
-
-    :returns:
-      The number of pending requests of this client.
-    """
-    return self._connection.pending_requests()
-
-  def identify(self, uid):
-    """Identify the uid
-
-    :param uid: user id. type str.
-    """
-    self._uid = uid
-
-  def get_status(self):
-    """Get the status of the PredictionIO API Server
-
-    :returns:
-      status message.
-
-    :raises:
-      ServerStatusError.
-    """
-    path = "/"
-    request = AsyncRequest("GET", path)
-    request.set_rfunc(self._aget_status_resp)
-    self._connection.make_request(request)
-    result = self.aresp(request)
-    return result
-
-  def _aget_status_resp(self, response):
-    """Handle the AsyncResponse of get status request"""
-    if response.error is not None:
-      raise ServerStatusError("Exception happened: %s for request %s" %
-                  (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise ServerStatusError("request: %s status: %s body: %s" %
-                  (response.request, response.status,
-                   response.body))
-
-    # data = json.loads(response.body) # convert json string to dict
-    return response.body
-
-  def acreate_user(self, uid, params={}):
-    """Asynchronously create a user.
-
-    :param uid: user id. type str.
-    :param params: optional attributes. type dictionary.
-        For example,
-        { 'custom': 'value', 'pio_inactive' : True,
-        'pio_latlng': [4.5,67.8] }
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-
-    """
-
-    if "pio_latlng" in params:
-      params["pio_latlng"] = ",".join(map(str, params["pio_latlng"]))
-    if "pio_inactive" in params:
-      params["pio_inactive"] = str(params["pio_inactive"]).lower()
-
-    path = "%s/users.json" % self.apiversion
-    request = AsyncRequest(
-      "POST", path, pio_appkey=self.appkey, pio_uid=uid, **params)
-    request.set_rfunc(self._acreate_user_resp)
-    self._connection.make_request(request)
-
-    return request
-
-  def _acreate_user_resp(self, response):
-    """Private function to handle the AsyncResponse of the acreate_user
-    request.
-
-    :param response: AsyncResponse object.
-
-    :returns:
-      None.
-
-    :raises:
-      UserNotCreatedError.
-
-    """
-    if response.error is not None:
-      raise UserNotCreatedError("Exception happened: %s for request %s" %
-                    (response.error, response.request))
-    elif response.status != httplib.CREATED:
-      raise UserNotCreatedError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-
-    return None
-
-  def aget_user(self, uid):
-    """Asynchronously get user.
-
-    :param uid: user id. type str.
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    enc_uid = urllib.quote(uid, "")  # replace special char with %xx
-    path = "%s/users/%s.json" % (self.apiversion, enc_uid)
-    request = AsyncRequest("GET", path, pio_appkey=self.appkey)
-    request.set_rfunc(self._aget_user_resp)
-    self._connection.make_request(request)
-
-    return request
-
-  def _aget_user_resp(self, response):
-    """Private function to handle the AsyncResponse of the aget_user
-    request .
-
-    :param response: AsyncResponse object.
-
-    :returns:
-      User data in Dictionary format.
-
-    :rasies:
-      UserNotFoundError.
-
-    """
-    if response.error is not None:
-      raise UserNotFoundError("Exception happened: %s for request %s" %
-                  (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise UserNotFoundError("request: %s status: %s body: %s" %
-                  (response.request, response.status,
-                   response.body))
-
-    data = json.loads(response.body)  # convert json string to dict
-    return data
-
-  def adelete_user(self, uid):
-    """Asynchronously delete user.
-
-    :param uid: user id. type str.
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    enc_uid = urllib.quote(uid, "")  # replace special char with %xx
-    path = "%s/users/%s.json" % (self.apiversion, enc_uid)
-    request = AsyncRequest("DELETE", path, pio_appkey=self.appkey)
-    request.set_rfunc(self._adelete_user_resp)
-    self._connection.make_request(request)
-
-    return request
-
-  def _adelete_user_resp(self, response):
-    """Private function to handle the AsyncResponse of the adelete_user
-    request.
-
-    :param response: AsyncResponse object.
-
-    :returns:
-      None.
-
-    :raises:
-      UserNotDeletedError.
-
-    """
-    if response.error is not None:
-      raise UserNotDeletedError("Exception happened: %s for request %s" %
-                    (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise UserNotDeletedError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-    return None
-
-  def acreate_item(self, iid, itypes, params={}):
-    """Asynchronously create item.
-
-    :param iid: item id. type str.
-    :param itypes: item types. Tuple of Str.
-        For example, if this item belongs to item types "t1", "t2",
-        "t3", "t4",then itypes=("t1", "t2", "t3", "t4").
-        NOTE: if this item belongs to only one itype, use tuple of one
-        element, eg. itypes=("t1",)
-    :param params: optional attributes. type dictionary.
-        For example,
-        { 'custom': 'value', 'pio_inactive' : True,
-        'pio_latlng': [4.5,67.8] }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    itypes_str = ",".join(itypes)  # join items with ","
-
-    if "pio_latlng" in params:
-      params["pio_latlng"] = ",".join(map(str, params["pio_latlng"]))
-    if "pio_inactive" in params:
-      params["pio_inactive"] = str(params["pio_inactive"]).lower()
-
-    path = "%s/items.json" % self.apiversion
-    request = AsyncRequest("POST", path, pio_appkey=self.appkey,
-                 pio_iid=iid, pio_itypes=itypes_str, **params)
-    request.set_rfunc(self._acreate_item_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _acreate_item_resp(self, response):
-    """Private function to handle the AsyncResponse of the acreate_item
-    request
-
-    :param response: AsyncResponse object.
-
-    :returns:
-      None
-    :raises:
-      ItemNotCreatedError
-
-    """
-    if response.error is not None:
-      raise ItemNotCreatedError("Exception happened: %s for request %s" %
-                    (response.error, response.request))
-    elif response.status != httplib.CREATED:
-      raise ItemNotCreatedError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-    return None
-
-  def aget_item(self, iid):
-    """Asynchronously get item
-
-    :param iid: item id. type str.
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    enc_iid = urllib.quote(iid, "")
-    path = "%s/items/%s.json" % (self.apiversion, enc_iid)
-    request = AsyncRequest("GET", path, pio_appkey=self.appkey)
-    request.set_rfunc(self._aget_item_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _aget_item_resp(self, response):
-    """Private function to handle the AsyncResponse of the aget_item
-    request
-
-    :param response: AsyncResponse object.
-
-    :returns:
-      item data in dictionary format.
-
-    :raises:
-      ItemNotFoundError.
-
-    """
-    if response.error is not None:
-      raise ItemNotFoundError("Exception happened: %s for request %s" %
-                  (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise ItemNotFoundError("request: %s status: %s body: %s" %
-                  (response.request, response.status,
-                   response.body))
-
-    data = json.loads(response.body)  # convert json string to dict
-    if "pio_itypes" in data:
-      # convert from list to tuple
-      data["pio_itypes"] = tuple(data["pio_itypes"])
-
-    return data
-
-  def adelete_item(self, iid):
-    """Asynchronously delete item
-
-    :param iid: item id. type str.
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    enc_iid = urllib.quote(iid, "")
-    path = "%s/items/%s.json" % (self.apiversion, enc_iid)
-    request = AsyncRequest("DELETE", path, pio_appkey=self.appkey)
-    request.set_rfunc(self._adelete_item_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _adelete_item_resp(self, response):
-    """Private function to handle the AsyncResponse of the adelete_item
-    request
-
-    :param response: AsyncResponse object
-
-    :returns:
-      None
-
-    :raises:
-      ItemNotDeletedError
-    """
-    if response.error is not None:
-      raise ItemNotDeletedError("Exception happened: %s for request %s" %
-                    (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise ItemNotDeletedError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-    return None
-
-  def _aget_user_itemrec_topn(self, engine, uid, n, params={}):
-    """Private function to asynchronously get recommendations for user
-
-    :param engine: name of the prediction engine. type str.
-    :param uid: user id. type str.
-    :param n: number of recommendation. type int.
-    :param params: optional parameters. type dictionary
-        For example, { 'pio_itypes' : ("t1","t2") }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    if "pio_itypes" in params:
-      params["pio_itypes"] = ",".join(params["pio_itypes"])
-    if "pio_latlng" in params:
-      params["pio_latlng"] = ",".join(map(str, params["pio_latlng"]))
-    if "pio_attributes" in params:
-      params["pio_attributes"] = ",".join(params["pio_attributes"])
-
-    path = "%s/engines/itemrec/%s/topn.json" % (self.apiversion, engine)
-    request = AsyncRequest("GET", path, pio_appkey=self.appkey,
-                 pio_uid=uid, pio_n=n, **params)
-    request.set_rfunc(self._aget_user_itemrec_topn_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _aget_user_itemrec_topn_resp(self, response):
-    """Private function to handle the AsyncResponse of the aget_itemrec
-    request
-
-    :param response: AsyncResponse object
-
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemRecNotFoundError.
-    """
-    if response.error is not None:
-      raise ItemRecNotFoundError(
-        "Exception happened: %s for request %s" %
-        (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise ItemRecNotFoundError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-
-    data = json.loads(response.body)  # convert json string to dict
-    return data
-
-  def aget_itemrec_topn(self, engine, n, params={}):
-    """Asynchronously get recommendations for the identified user
-
-    :param engine: name of the prediction engine. type str.
-    :param n: number of recommendation. type int.
-    :param params: optional parameters. type dictionary
-        For example, { 'pio_itypes' : ("t1",) }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    if self._uid is None:
-      raise InvalidArgumentError(
-        "uid is not identified. Please call identify(uid) first.")
-
-    request = self._aget_user_itemrec_topn(engine, self._uid, n, params)
-    return request
-
-  def aget_itemrec(self, uid, n, engine, **params):
-    """Deprecated. Asynchronously get recommendations
-
-    :param uid: user id. type str.
-    :param n: number of recommendation. type int.
-    :param engine: name of the prediction engine. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng="123.4, 56.7"
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    request = self._aget_user_itemrec_topn(engine, uid, n, params)
-    return request
-
-  def _aget_itemsim_topn(self, engine, iid, n, params={}):
-    """Private function to asynchronously get top n similar items of the
-    item
-
-    :param engine: name of the prediction engine. type str.
-    :param iid: item id. type str.
-    :param n: number of similar items. type int.
-    :param params: optional parameters. type dictionary
-        For example, { 'pio_itypes' : ("t1","t2") }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    if "pio_itypes" in params:
-      params["pio_itypes"] = ",".join(params["pio_itypes"])
-    if "pio_latlng" in params:
-      params["pio_latlng"] = ",".join(map(str, params["pio_latlng"]))
-    if "pio_attributes" in params:
-      params["pio_attributes"] = ",".join(params["pio_attributes"])
-
-    path = "%s/engines/itemsim/%s/topn.json" % (self.apiversion, engine)
-    request = AsyncRequest("GET", path, pio_appkey=self.appkey,
-                 pio_iid=iid, pio_n=n, **params)
-    request.set_rfunc(self._aget_itemsim_topn_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _aget_itemsim_topn_resp(self, response):
-    """Private function to handle the AsyncResponse of the aget_itemsim
-    request
-
-    :param response: AsyncResponse object
-
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemSimNotFoundError.
-    """
-    if response.error is not None:
-      raise ItemSimNotFoundError(
-        "Exception happened: %s for request %s" %
-        (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise ItemSimNotFoundError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-
-    data = json.loads(response.body)  # convert json string to dict
-    return data
-
-  def aget_itemsim_topn(self, engine, iid, n, params={}):
-    """Asynchronously get top n similar items of the item
-
-    :param engine: name of the prediction engine. type str.
-    :param iid: item id. type str.
-    :param n: number of similar items. type int.
-    :param params: optional parameters. type dictionary
-        For example, { 'pio_itypes' : ("t1",) }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    request = self._aget_itemsim_topn(engine, iid, n, params)
-    return request
-
-  def _aget_user_itemrank_ranked(self, engine, uid, iids, params={}):
-    """Private function to asynchronously get ranked item for user
-
-    :param engine: name of the prediction engine. type str.
-    :param uid: user id. type str.
-    :param iids: items to be ranked. type list of item ids.
-      For example, ["i0", "i1", "i2"]
-    :param params: optional parameters. type dictionary
-      For example. { 'pio_attributes' : "name" }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    if "pio_attributes" in params:
-      params["pio_attributes"] = ",".join(params["pio_attributes"])
-
-    pio_iids = ",".join(iids)
-
-    path = "%s/engines/itemrank/%s/ranked.json" % \
-      (self.apiversion, engine)
-    request = AsyncRequest("GET", path, pio_appkey=self.appkey,
-                           pio_uid=uid, pio_iids=pio_iids, **params)
-    request.set_rfunc(self._aget_user_itemrank_ranked_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _aget_user_itemrank_ranked_resp(self, response):
-    """Private function to handle the AsyncResponse of the aget_itemreoder
-      request
-
-    :param response: AsyncResponse object
-
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemRankNotFoundError.
-    """
-    if response.error is not None:
-      raise ItemRankNotFoundError(
-        "Exception happened: %s for request %s" %
-        (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise ItemRankNotFoundError("request: %s status: %s body: %s" %
-                                  (response.request, response.status,
-                                   response.body))
-
-    data = json.loads(response.body)  # convert json string to dict
-    return data
-
-  def aget_itemrank_ranked(self, engine, iids, params={}):
-    """Asynchronously get ranked item for user
-
-    :param engine: name of the prediction engine. type str.
-    :param iids: items to be ranked. type list of item ids.
-      For example, ["i0", "i1", "i2"]
-    :param params: optional parameters. type dictionary
-      For example. { 'pio_attributes' : "name" }
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    if self._uid is None:
-      raise InvalidArgumentError(
-        "uid is not identified. Please call identify(uid) first.")
-
-    request = self._aget_user_itemrank_ranked(engine,
-      self._uid, iids, params)
-    return request
-
-  def _auser_action_on_item(self, action, uid, iid, params):
-    """Private function to asynchronously create an user action on an item
-
-    :param action: action type. type str. ("like", "dislike", "conversion",
-                         "rate", "view")
-    :param uid: user id. type str or int.
-    :param iid: item id. type str or int.
-    :param params: optional attributes. type dictionary.
-        For example, { 'pio_rate' : 4, 'pio_latlng' : [1.23,4.56] }
-        NOTE: For "rate" action, pio_rate attribute is required.
-            integer value of 1-5 (1 is least preferred and 5 is most
-            preferred)
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    if "pio_latlng" in params:
-      params["pio_latlng"] = ",".join(map(str, params["pio_latlng"]))
-
-    path = "%s/actions/u2i.json" % (self.apiversion)
-    request = AsyncRequest("POST", path, pio_appkey=self.appkey,
-                 pio_action=action, pio_uid=uid, pio_iid=iid,
-                 **params)
-    request.set_rfunc(self._auser_action_on_item_resp)
-    self._connection.make_request(request)
-    return request
-
-  def _auser_action_on_item_resp(self, response):
-    """Private function to handle the AsyncResponse of the
-    _auser_action_on_item request
-
-    :param response: AsyncResponse object
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    if response.error is not None:
-      raise U2IActionNotCreatedError(
-        "Exception happened: %s for request %s" %
-        (response.error, response.request))
-    elif response.status != httplib.CREATED:
-      raise U2IActionNotCreatedError("request: %s status: %s body: %s" %
-                       (response.request, response.status,
-                      response.body))
-    return None
-
-  def arecord_action_on_item(self, action, iid, params={}):
-    """Asynchronously create action on item
-
-    :param action: action name. type String. For example, "rate", "like",
-             etc
-    :param iid: item id. type str or int.
-    :param params: optional attributes. type dictionary.
-        For example, { 'pio_rate' : 4, 'pio_latlng': [4.5,67.8] }
-        NOTE: For "rate" action, pio_rate attribute is required.
-        integer value of 1-5 (1 is least preferred and 5 is most
-        preferred)
-
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-
-    if self._uid is None:
-      raise InvalidArgumentError(
-        "uid is not identified. Please call identify(uid) first.")
-
-    request = self._auser_action_on_item(action, self._uid, iid, params)
-    return request
-
-  def auser_conversion_item(self, uid, iid, **params):
-    """Deprecated. Asynchronously create an user conversion action on an
-    item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    request = self._auser_action_on_item(CONVERSION_API, uid, iid, params)
-    return request
-
-  def auser_dislike_item(self, uid, iid, **params):
-    """Deprecated. Asynchronously create an user dislike action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    request = self._auser_action_on_item(DISLIKE_API, uid, iid, params)
-    return request
-
-  def auser_like_item(self, uid, iid, **params):
-    """Deprecated. Asynchronously create an user like action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    request = self._auser_action_on_item(LIKE_API, uid, iid, params)
-    return request
-
-  def auser_rate_item(self, uid, iid, rate, **params):
-    """Deprecated. Asynchronously create an user rate action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param rate: rating. integer value of 1-5 (1 is least preferred and 5
-           is most preferred)
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-
-    params['pio_rate'] = rate
-    request = self._auser_action_on_item(RATE_API, uid, iid, params)
-    return request
-
-  def auser_view_item(self, uid, iid, **params):
-    """Deprecated. Asynchronously create an user view action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-    :returns:
-      AsyncRequest object. You should call the aresp() method using this
-      AsyncRequest object as argument to get the final result or status
-      of this asynchronous request.
-    """
-    request = self._auser_action_on_item(VIEW_API, uid, iid, params)
-    return request
-
-  def aresp(self, request):
-    """Get the result of the asynchronous request
-
-    :param request: AsyncRequest object. This object must be returned by
-            the asynchronous request function
-            For example, to get the result of a aget_user()
-            request, call this aresp() with the argument of
-            AsyncRequest object returned by aget_user().
-
-    :returns:
-      The result of this AsyncRequest. The return type is the same as
-      the return type of corresponding blocking request.
-
-      For example,
-
-      Calling aresp() with acreate_user() AsyncRequest returns the same
-      type as create_user(), which is None.
-
-      Calling aresp() with aget_user() AsyncRequest returns the same
-      type as get_user(), which is dictionary data.
-
-    :raises:
-      Exception may be raised if there is error happened. The type of
-      exception is the same as exception type of the correspdoning
-      blocking request.
-
-      For example,
-
-      Calling aresp() with acreate_user() AsyncRequest may raise
-      UserNotCreatedError exception.
-
-      Calling aresp() with aget_user() AsyncRequest may raise
-      UserNotFoundError exception.
-
-    """
-    response = request.get_response()
-    result = request.rfunc(response)
-    return result
-
-  def create_user(self, uid, params={}):
-    """Blocking request to create user
-
-    :param uid: user id. type str.
-    :param params: optional attributes. type dictionary.
-      For example, { 'custom': 'value', 'pio_inactive' : True,
-      'pio_latlng': [4.5,67.8] }
-
-    :returns:
-      None.
-
-    :raises:
-      UserNotCreatedError.
-
-    """
-    request = self.acreate_user(uid, params)
-    result = self.aresp(request)
-    return result
-
-  def get_user(self, uid):
-    """Blocking request to get user
-
-    :param uid: user id. type str or int.
-
-    :returns:
-      User data in Dictionary format.
-
-    :rasies:
-      UserNotFoundError.
-
-    """
-    request = self.aget_user(uid)
-    result = self.aresp(request)
-    return result
-
-  def delete_user(self, uid):
-    """Blocking request to delete the user
-
-    :param uid: user id. type str.
-
-    :returns:
-      None.
-
-    :raises:
-      UserNotDeletedError.
-
-    """
-    request = self.adelete_user(uid)
-    result = self.aresp(request)
-    return result
-
-  def create_item(self, iid, itypes, params={}):
-    """Blocking request to create item
-
-    :param iid: item id. type str.
-    :param itypes: item types. Tuple of Str.
-        For example, if this item belongs to item types "t1", "t2",
-        "t3", "t4", then itypes=("t1", "t2", "t3", "t4").
-        NOTE: if this item belongs to only one itype, use tuple of one
-        element, eg. itypes=("t1",)
-    :param params: optional attributes. type dictionary.
-        For example,
-        { 'custom': 'value', 'pio_inactive' : True,
-        'pio_latlng': [4.5,67.8] }
-
-    :returns:
-      None
-
-    :raises:
-      ItemNotCreatedError
-
-    """
-    request = self.acreate_item(iid, itypes, params)
-    result = self.aresp(request)
-    return result
-
-  def get_item(self, iid):
-    """Blocking request to get item
-
-    :param iid: item id. type str.
-
-    :returns:
-      item data in dictionary format.
-
-    :raises:
-      ItemNotFoundError.
-
-    """
-    request = self.aget_item(iid)
-    result = self.aresp(request)
-    return result
-
-  def delete_item(self, iid):
-    """Blocking request to delete item
-
-    :param iid: item id. type str.
-
-    :returns:
-      None
-
-    :raises:
-      ItemNotDeletedError
-
-    """
-    request = self.adelete_item(iid)
-    result = self.aresp(request)
-    return result
-
-  def get_itemrec_topn(self, engine, n, params={}):
-    """Blocking request to get recommendations for the identified user
-
-    :param engine: name of the prediction engine. type str.
-    :param n: number of recommendation. type int.
-    :param params: optional parameters. type dictionary
-        For example, { 'pio_itypes' : ("t1", "t2") }
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemRecNotFoundError.
-    """
-    request = self.aget_itemrec_topn(engine, n, params)
-    result = self.aresp(request)
-    return result
-
-  def get_itemrec(self, uid, n, engine, **params):
-    """Deprecated. Blocking request to get recommendations
-
-    :param uid: user id. type str or int.
-    :param n: number of recommendation. type int.
-    :param engine: name of the prediction engine. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemRecNotFoundError.
-
-    """
-    request = self.aget_itemrec(uid, n, engine, **params)
-    result = self.aresp(request)
-    return result
-
-  def get_itemsim_topn(self, engine, iid, n, params={}):
-    """Blocking request to get top n similar items of the item
-
-    :param engine: name of the prediction engine. type str.
-    :param iid: item id. type str.
-    :param n: number of similar items. type int.
-    :param params: optional parameters. type dictionary
-        For example, { 'pio_itypes' : ("t1",) }
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemSimNotFoundError.
-    """
-
-    request = self.aget_itemsim_topn(engine, iid, n, params)
-    result = self.aresp(request)
-    return result
-
-  def get_itemrank_ranked(self, engine, iids, params={}):
-    """Blocking request to get ranked item for user
-
-    :param engine: name of the prediction engine. type str.
-    :param iids: items to be ranked. type list of item ids.
-        For example, ["i0", "i1", "i2"]
-    :param params: optional parameters. type dictionary
-        For example. { 'pio_attributes' : "name" }
-    :returns:
-      data in dictionary format.
-
-    :raises:
-      ItemRankNotFoundError.
-    """
-    request = self.aget_itemrank_ranked(engine, iids, params)
-    result = self.aresp(request)
-    return result
-
-  def record_action_on_item(self, action, iid, params={}):
-    """Blocking request to create action on an item
-
-    :param action: action name. type String. For example, "rate", "like",
-             etc
-    :param iid: item id. type str.
-    :param params: optional attributes. type dictionary.
-        For example, { 'pio_rate' : 4, 'pio_latlng' : [1.23,4.56] }
-        NOTE: For "rate" action, pio_rate attribute is required.
-        integer value of 1-5 (1 is least preferred and 5 is most
-        preferred)
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    request = self.arecord_action_on_item(action, iid, params)
-    result = self.aresp(request)
-    return result
-
-  def user_conversion_item(self, uid, iid, **params):
-    """Deprecated. Blocking request to create user conversion action on an
-     item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    request = self.auser_conversion_item(uid, iid, **params)
-    result = self.aresp(request)
-    return result
-
-  def user_dislike_item(self, uid, iid, **params):
-    """Deprecated. Blocking request to create user dislike action on an
-     item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    request = self.auser_dislike_item(uid, iid, **params)
-    result = self.aresp(request)
-    return result
-
-  def user_like_item(self, uid, iid, **params):
-    """Deprecated. Blocking request to create user like action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    request = self.auser_like_item(uid, iid, **params)
-    result = self.aresp(request)
-    return result
-
-  def user_rate_item(self, uid, iid, rate, **params):
-    """Deprecated. Blocking request to create user rate action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param rate: rating. integer value of 1-5 (1 is least preferred and 5
-           is most preferred)
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    request = self.auser_rate_item(uid, iid, rate, **params)
-    result = self.aresp(request)
-    return result
-
-  def user_view_item(self, uid, iid, **params):
-    """Deprecated. Blocking request to create user view action on an item
-
-    :param uid: user id. type str.
-    :param iid: item id. type str.
-    :param params: keyword arguments for optional attributes.
-        For example, pio_latlng=[123.4, 56.7]
-
-    :returns:
-      None
-
-    :raises:
-      U2IActionNotCreatedError
-    """
-    request = self.auser_view_item(uid, iid, **params)
-    result = self.aresp(request)
-    return result
-

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index 24bfc03..f0e1038 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
 try:
-  from setuptools import setup
+    from setuptools import setup
 except ImportError:
-  from distutils.core import setup
+    from distutils.core import setup
 
 __author__ = "The PredictionIO Team"
 __email__ = "help@tappingstone.com"
@@ -10,7 +10,7 @@ __license__ = "Apache License, Version 2.0"
 
 setup(
     name='PredictionIO',
-    version="0.8.3",
+    version="0.8.5",
     author=__author__,
     author_email=__email__,
     packages=['predictionio'],
@@ -18,17 +18,17 @@ setup(
     license='LICENSE.txt',
     description='PredictionIO Python SDK',
     classifiers=[
-      'Programming Language :: Python',
-      'License :: OSI Approved :: Apache Software License',
-      'Operating System :: OS Independent',
-      'Development Status :: 4 - Beta',
-      'Intended Audience :: Developers',
-      'Intended Audience :: Science/Research',
-      'Environment :: Web Environment',
-      'Topic :: Internet :: WWW/HTTP',
-      'Topic :: Scientific/Engineering :: Artificial Intelligence',
-      'Topic :: Scientific/Engineering :: Information Analysis',
-      'Topic :: Software Development :: Libraries :: Python Modules'],
+        'Programming Language :: Python',
+        'License :: OSI Approved :: Apache Software License',
+        'Operating System :: OS Independent',
+        'Development Status :: 4 - Beta',
+        'Intended Audience :: Developers',
+        'Intended Audience :: Science/Research',
+        'Environment :: Web Environment',
+        'Topic :: Internet :: WWW/HTTP',
+        'Topic :: Scientific/Engineering :: Artificial Intelligence',
+        'Topic :: Scientific/Engineering :: Information Analysis',
+        'Topic :: Software Development :: Libraries :: Python Modules'],
     long_description="""PredictionIO Python SDK
 
                        PredictionIO is a prediction server for building smart
@@ -50,5 +50,5 @@ setup(
                        PredictionIO API to Python programmers so that they
                        can focus on their application logic.
                        """,
-    install_requires=["pytz >= 2014.2",],
-    )
+    install_requires=["pytz >= 2014.2", ],
+)

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/conversion_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/conversion_test.py b/tests-obsolete/conversion_test.py
new file mode 100644
index 0000000..b9dca97
--- /dev/null
+++ b/tests-obsolete/conversion_test.py
@@ -0,0 +1,16 @@
+import timeit
+
+if __name__ == "__main__":
+    a = True
+
+    t = timeit.Timer("json.dumps(True)", "import json")
+
+    t_bool2json = t.timeit(1000) / 1000
+    print("bool 2 json")
+    print(t_bool2json)
+
+    t = timeit.Timer("str(True).lower()", "")
+
+    t_bool2string = t.timeit(1000) / 1000
+    print("bool 2 string")
+    print(t_bool2string)

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/import_testdata.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/import_testdata.py b/tests-obsolete/import_testdata.py
new file mode 100644
index 0000000..e5338c0
--- /dev/null
+++ b/tests-obsolete/import_testdata.py
@@ -0,0 +1,46 @@
+"""
+Import simple test data for testing getting itemrec
+"""
+import predictionio
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
+API_URL = "http://localhost:7070"
+
+MIN_VERSION = '0.5.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+if __name__ == "__main__":
+    client = predictionio.Client(APP_KEY, 1, API_URL)
+
+    client.create_user("u0")
+    client.create_user("u1")
+    client.create_user("u2")
+    client.create_user("u3")
+
+    client.create_item("i0", ("t1",), {"custom1": "i0c1"})
+    client.create_item("i1", ("t1", "t2"), {"custom1": "i1c1", "custom2": "i1c2"})
+    client.create_item("i2", ("t1", "t2"), {"custom2": "i2c2"})
+    client.create_item("i3", ("t1",))
+
+    client.identify("u0")
+    client.record_action_on_item("rate", "i0", {"pio_rate": 2})
+    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
+    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
+
+    client.identify("u1")
+    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 1})
+
+    client.identify("u2")
+    client.record_action_on_item("rate", "i1", {"pio_rate": 2})
+    client.record_action_on_item("rate", "i2", {"pio_rate": 1})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 3})
+
+    client.identify("u3")
+    client.record_action_on_item("rate", "i0", {"pio_rate": 5})
+    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 2})
+
+    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/import_testdata_id_mismatch.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/import_testdata_id_mismatch.py b/tests-obsolete/import_testdata_id_mismatch.py
new file mode 100644
index 0000000..104f75c
--- /dev/null
+++ b/tests-obsolete/import_testdata_id_mismatch.py
@@ -0,0 +1,46 @@
+"""
+Import simple test data for testing getting itemrec
+"""
+import predictionio
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
+API_URL = "http://localhost:8000"
+
+MIN_VERSION = '0.5.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+if __name__ == "__main__":
+    client = predictionio.Client(APP_KEY, 1, API_URL)
+
+    client.create_user("u0")
+    client.create_user("u1")
+    client.create_user("u2")
+    client.create_user("u3")
+
+    client.create_item("i0", ("t1",), {"custom1": "i0c1"})
+    client.create_item("i1", ("t1", "t2"), {"custom1": "i1c1", "custom2": "i1c2"})
+    client.create_item("i2", ("t1", "t2"), {"custom2": "i2c2"})
+    client.create_item("i3", ("t1",))
+
+    client.identify("u0x")
+    client.record_action_on_item("rate", "i0", {"pio_rate": 2})
+    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
+    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
+
+    client.identify("u1x")
+    client.record_action_on_item("rate", "i2", {"pio_rate": 4})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 1})
+
+    client.identify("u2x")
+    client.record_action_on_item("rate", "i1", {"pio_rate": 2})
+    client.record_action_on_item("rate", "i2", {"pio_rate": 1})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 3})
+
+    client.identify("u3x")
+    client.record_action_on_item("rate", "i0", {"pio_rate": 5})
+    client.record_action_on_item("rate", "i1", {"pio_rate": 3})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 2})
+
+    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/import_testdata_special_char.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/import_testdata_special_char.py b/tests-obsolete/import_testdata_special_char.py
new file mode 100644
index 0000000..c047b6a
--- /dev/null
+++ b/tests-obsolete/import_testdata_special_char.py
@@ -0,0 +1,46 @@
+"""
+Import simple test data (id with special characters) for testing getting itemrec
+"""
+import predictionio
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
+API_URL = "http://localhost:8000"
+
+MIN_VERSION = '0.5.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+if __name__ == "__main__":
+    client = predictionio.Client(APP_KEY, 1, API_URL)
+
+    client.create_user("u0@u.n")
+    client.create_user("u1@u.n")
+    client.create_user("http://u2.com")
+    client.create_user("u3@u.n")
+
+    client.create_item("http://i0.com", ("t1",), {"custom1": "i0c1"})
+    client.create_item("i1@i1", ("t1", "t2"), {"custom1": "i1c1", "custom2": "i1c2"})
+    client.create_item("i2.org", ("t1", "t2"), {"custom2": "i2c2"})
+    client.create_item("i3", ("t1",))
+
+    client.identify("u0@u.n")
+    client.record_action_on_item("rate", "http://i0.com", {"pio_rate": 2})
+    client.record_action_on_item("rate", "i1@i1", {"pio_rate": 3})
+    client.record_action_on_item("rate", "i2.org", {"pio_rate": 4})
+
+    client.identify("u1@u.n")
+    client.record_action_on_item("rate", "i2.org", {"pio_rate": 4})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 1})
+
+    client.identify("http://u2.com")
+    client.record_action_on_item("rate", "i1@i1", {"pio_rate": 2})
+    client.record_action_on_item("rate", "i2.org", {"pio_rate": 1})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 3})
+
+    client.identify("u3@u.n")
+    client.record_action_on_item("rate", "http://i0.com", {"pio_rate": 5})
+    client.record_action_on_item("rate", "i1@i1", {"pio_rate": 3})
+    client.record_action_on_item("rate", "i3", {"pio_rate": 2})
+
+    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/predictionio_itemrec_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_itemrec_test.py b/tests-obsolete/predictionio_itemrec_test.py
new file mode 100644
index 0000000..3105f0f
--- /dev/null
+++ b/tests-obsolete/predictionio_itemrec_test.py
@@ -0,0 +1,336 @@
+"""
+Test getting itemrec after algo training completes.
+"""
+
+from __future__ import print_function
+
+import unittest
+
+import predictionio
+
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
+API_URL = "http://localhost:8000"  # PredictoinIO Server
+
+DEBUG = True
+
+MIN_VERSION = '0.6.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+
+class TestPredictionIO(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_itemrec_exception_deprecated(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        try:
+            client.get_itemrec("uidwithoutrec", 10, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:  # noqa
+            pass  # expected exception
+        except:
+            raise
+
+        client.close()
+
+    def test_get_itemrec_exception(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        client.identify("uidwithoutrec")
+
+        try:
+            client.get_itemrec_topn("python-itemrec-engine", 10)
+        except predictionio.ItemRecNotFoundError as e:  # noqa
+            pass  # expected exception
+        except:
+            raise
+
+        try:
+            client.get_itemrec_topn("python-itemrec-engine", 10,
+                                    {"pio_itypes": ("t1",), "pio_latlng": [1.34, 5.67], "pio_within": 5.0,
+                                     "pio_unit": "km", "pio_attributes": ["custom1", "custom2"]})
+        except predictionio.ItemRecNotFoundError as e:  # noqa
+            pass  # expected exception
+        except:
+            raise
+
+        client.close()
+
+    def test_get_itemrec_deprecated(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        # request more
+        try:
+            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
+
+        try:
+            itemrec = client.get_itemrec("u1", 10, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": ["i2", "i1", "i0", "i3"]}) or
+                        (itemrec == {"pio_iids": ["i2", "i0", "i1", "i3"]}))
+
+        try:
+            itemrec = client.get_itemrec("u2", 10, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertTrue((itemrec == {"pio_iids": ["i3", "i0", "i1", "i2"]}) or
+                        (itemrec == {"pio_iids": ["i3", "i1", "i0", "i2"]}))
+
+        try:
+            itemrec = client.get_itemrec("u3", 6, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertTrue((itemrec == {"pio_iids": ["i0", "i1", "i2", "i3"]}) or
+                        (itemrec == {"pio_iids": ["i0", "i2", "i1", "i3"]}))
+
+        # request less
+        try:
+            itemrec = client.get_itemrec("u0", 1, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2"]})
+
+        try:
+            itemrec = client.get_itemrec("u0", 2, "python-itemrec-engine")
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3"]})
+
+        # request with optional attributes
+
+        # pio_itypes
+        try:
+            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t1", "t2"))
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
+
+        # subset itypes
+        try:
+            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t2",))
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i1"]})
+
+        # nonexisting itypes
+        try:
+            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("other-itype",))
+        except predictionio.ItemRecNotFoundError as e:
+            pass  # expected no recommendation
+        except:
+            raise
+
+        # pio_attributes
+        try:
+            itemrec = client.get_itemrec("u0", 10, "python-itemrec-engine", pio_itypes=("t1",),
+                                         pio_attributes=["custom1", "custom2"])
+        except predictionio.ItemRecNotFoundError as e:  # noqa
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"], "custom1": [None, None, "i1c1", "i0c1"],
+                                   "custom2": ["i2c2", None, "i1c2", None]})
+
+        client.close()
+
+    def test_get_itemrec(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        # request more
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
+
+        client.identify("u1")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertTrue((itemrec == {"pio_iids": ["i2", "i1", "i0", "i3"]}) or
+                        (itemrec == {"pio_iids": ["i2", "i0", "i1", "i3"]}))
+
+        client.identify("u2")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertTrue((itemrec == {"pio_iids": ["i3", "i0", "i1", "i2"]}) or
+                        (itemrec == {"pio_iids": ["i3", "i1", "i0", "i2"]}))
+
+        client.identify("u3")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 6)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertTrue((itemrec == {"pio_iids": ["i0", "i1", "i2", "i3"]}) or
+                        (itemrec == {"pio_iids": ["i0", "i2", "i1", "i3"]}))
+
+        # request less
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 1)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2"]})
+
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 2)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3"]})
+
+        # request with optional attributes
+
+        # pio_itypes
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t1", "t2")})
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"]})
+
+        # subset itypes
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("t2",)})
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+        if DEBUG:
+            print(itemrec)
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i1"]})
+
+        # nonexisting itypes
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10, {"pio_itypes": ("other-itype",)})
+        except predictionio.ItemRecNotFoundError as e:
+            pass  # expected no recommendation
+        except:
+            raise
+
+        # pio_attributes
+        client.identify("u0")
+        try:
+            itemrec = client.get_itemrec_topn("python-itemrec-engine", 10,
+                                              {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
+        except predictionio.ItemRecNotFoundError as e:  # noqa
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": ["i2", "i3", "i1", "i0"], "custom1": [None, None, "i1c1", "i0c1"],
+                                   "custom2": ["i2c2", None, "i1c2", None]})
+
+        # TODO pio_latlng
+        # TODO pio_within
+        # TODO pio_unit
+
+        client.close()
+
+
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/predictionio_itemrec_test_special_char.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_itemrec_test_special_char.py b/tests-obsolete/predictionio_itemrec_test_special_char.py
new file mode 100644
index 0000000..a622800
--- /dev/null
+++ b/tests-obsolete/predictionio_itemrec_test_special_char.py
@@ -0,0 +1,366 @@
+"""
+Test getting itemrec after algo training completes.
+"""
+import unittest
+
+import predictionio
+
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
+API_URL = "http://localhost:8000"  # PredictoinIO Server
+
+DEBUG = True
+
+MIN_VERSION = '0.6.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+
+class TestPredictionIO(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_itemrec_deprecated(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        uid0 = "u0@u.n"
+        uid1 = "u1@u.n"
+        uid2 = "http://u2.com"
+        uid3 = "u3@u.n"
+
+        iid0 = "http://i0.com"
+        iid1 = "i1@i1"
+        iid2 = "i2.org"
+        iid3 = "i3"
+
+        engine_name = "itemrec"
+
+        # request more
+        try:
+            itemrec = client.get_itemrec(uid0, 10, engine_name)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
+
+        try:
+            itemrec = client.get_itemrec(uid1, 10, engine_name)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": [iid2, iid1, iid0, iid3]}) or
+                        (itemrec == {"pio_iids": [iid2, iid0, iid1, iid3]}))
+
+        try:
+            itemrec = client.get_itemrec(uid2, 10, engine_name)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": [iid3, iid0, iid1, iid2]}) or
+                        (itemrec == {"pio_iids": [iid3, iid1, iid0, iid2]}))
+
+        try:
+            itemrec = client.get_itemrec(uid3, 6, engine_name)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": [iid0, iid1, iid2, iid3]}) or
+                        (itemrec == {"pio_iids": [iid0, iid2, iid1, iid3]}))
+
+        # request less
+        try:
+            itemrec = client.get_itemrec(uid0, 1, engine_name)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2]})
+
+        try:
+            itemrec = client.get_itemrec(uid0, 2, engine_name)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3]})
+
+        # request with optional attributes
+
+        # pio_itypes
+        try:
+            itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t1", "t2"))
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
+
+        # subset itypes
+        try:
+            itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t2",))
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid1]})
+
+        # nonexisting itypes
+        try:
+            client.get_itemrec(uid0, 10, engine_name, pio_itypes=("other-itype",))
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            pass  # expected no recommendation
+        except:
+            raise
+
+        # pio_attributes
+        try:
+            itemrec = client.get_itemrec(uid0, 10, engine_name, pio_itypes=("t1",),
+                                         pio_attributes=["custom1", "custom2"])
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0], "custom1": [None, None, "i1c1", "i0c1"],
+                                   "custom2": ["i2c2", None, "i1c2", None]})
+
+        client.close()
+
+    def test_get_itemrec(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        uid0 = "u0@u.n"
+        uid1 = "u1@u.n"
+        uid2 = "http://u2.com"
+        uid3 = "u3@u.n"
+
+        iid0 = "http://i0.com"
+        iid1 = "i1@i1"
+        iid2 = "i2.org"
+        iid3 = "i3"
+
+        engine_name = "itemrec"
+
+        # request more
+        client.identify(uid0)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 10)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
+
+        client.identify(uid1)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 10)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": [iid2, iid1, iid0, iid3]}) or
+                        (itemrec == {"pio_iids": [iid2, iid0, iid1, iid3]}))
+
+        client.identify(uid2)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 10)
+        except predictionio.ItemRecNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": [iid3, iid0, iid1, iid2]}) or
+                        (itemrec == {"pio_iids": [iid3, iid1, iid0, iid2]}))
+
+        client.identify(uid3)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 6)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertTrue((itemrec == {"pio_iids": [iid0, iid1, iid2, iid3]}) or
+                        (itemrec == {"pio_iids": [iid0, iid2, iid1, iid3]}))
+
+        # request less
+        client.identify(uid0)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 1)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2]})
+
+        client.identify(uid0)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 2)
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3]})
+
+        # request with optional attributes
+
+        # pio_itypes
+        client.identify(uid0)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t1", "t2")})
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0]})
+
+        # subset itypes
+        client.identify(uid0)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("t2",)})
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid1]})
+
+        # nonexisting itypes
+        client.identify(uid0)
+        try:
+            client.get_itemrec_topn(engine_name, 10, {"pio_itypes": ("other-itype",)})
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            pass  # expected no recommendation
+        except:
+            raise
+
+        # pio_attributes
+        client.identify(uid0)
+        try:
+            itemrec = client.get_itemrec_topn(engine_name, 10,
+                                              {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
+        except predictionio.ItemRecNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemrec)
+
+        self.assertEqual(itemrec, {"pio_iids": [iid2, iid3, iid1, iid0], "custom1": [None, None, "i1c1", "i0c1"],
+                                   "custom2": ["i2c2", None, "i1c2", None]})
+
+        # TODO pio_latlng
+        # TODO pio_within
+        # TODO pio_unit
+
+        client.close()
+
+
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/tests-obsolete/predictionio_itemsim_test.py
----------------------------------------------------------------------
diff --git a/tests-obsolete/predictionio_itemsim_test.py b/tests-obsolete/predictionio_itemsim_test.py
new file mode 100644
index 0000000..45fa151
--- /dev/null
+++ b/tests-obsolete/predictionio_itemsim_test.py
@@ -0,0 +1,200 @@
+"""
+Test getting itemsim after algo training completes (pdio-itemsimcf with cosine sim).
+"""
+import unittest
+
+import predictionio
+
+
+APP_KEY = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"  # replace this with your AppKey
+API_URL = "http://localhost:8000"  # PredictoinIO Server
+
+DEBUG = True
+
+MIN_VERSION = '0.6.0'
+if predictionio.__version__ < MIN_VERSION:
+    err = "Require PredictionIO Python SDK version >= %s" % MIN_VERSION
+    raise Exception(err)
+
+
+class TestPredictionIO(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def test_get_itemsim_exception(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        try:
+            client.get_itemsim_topn("python-itemsim-engine", "iidwithoutsim", 10)
+        except predictionio.ItemSimNotFoundError as e:
+            pass  # expected exception
+        except:
+            raise
+
+        try:
+            client.get_itemsim_topn("python-itemsim-engine", "iidwithoutsim", 10,
+                                    {"pio_itypes": ("t1",), "pio_latlng": [1.34, 5.67], "pio_within": 5.0,
+                                     "pio_unit": "km", "pio_attributes": ["custom1", "custom2"]})
+        except predictionio.ItemSimNotFoundError as e:
+            if DEBUG:
+                print(e)
+            pass  # expected exception
+        except:
+            raise
+
+        client.close()
+
+    def test_get_itemsim(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        # request more than what is available
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i0", 10)
+        except predictionio.ItemSimNotFoundError as e:
+            print
+            "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertTrue((itemsim == {"pio_iids": ["i1", "i2", "i3"]}) or
+                        (itemsim == {"pio_iids": ["i1", "i3", "i2"]}))
+
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10)
+        except predictionio.ItemSimNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertTrue((itemsim == {"pio_iids": ["i2", "i3", "i0"]}))
+
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i2", 10)
+        except predictionio.ItemSimNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertTrue((itemsim == {"pio_iids": ["i1", "i3", "i0"]}))
+
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i3", 10)
+        except predictionio.ItemSimNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertTrue((itemsim == {"pio_iids": ["i1", "i2", "i0"]}))
+
+        # request less
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 1)
+        except predictionio.ItemSimNotFoundError as e:
+            print
+            "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertEqual(itemsim, {"pio_iids": ["i2"]})
+
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 2)
+        except predictionio.ItemSimNotFoundError as e:
+            print
+            "ERROR: have you run import_testdata.py and then wait for the algorithm training completion?"
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertEqual(itemsim, {"pio_iids": ["i2", "i3"]})
+
+        # request with optional attributes
+
+        # pio_itypes
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t1", "t2")})
+        except predictionio.ItemSimNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertEqual(itemsim, {"pio_iids": ["i2", "i3", "i0"]})
+
+        # subset itypes
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10, {"pio_itypes": ("t2",)})
+        except predictionio.ItemSimNotFoundError as e:
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertEqual(itemsim, {"pio_iids": ["i2"]})
+
+        # nonexisting itypes
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i0", 10, {"pio_itypes": ("other-itype",)})
+        except predictionio.ItemSimNotFoundError as e:
+            pass  # expected no recommendation
+        except:
+            raise
+
+        # pio_attributes
+        try:
+            itemsim = client.get_itemsim_topn("python-itemsim-engine", "i1", 10,
+                                              {"pio_itypes": ("t1",), "pio_attributes": ["custom1", "custom2"]})
+        except predictionio.ItemSimNotFoundError as e:
+            print(e)
+            print("ERROR: have you run import_testdata.py and then wait for the algorithm training completion?")
+            raise
+        except:
+            raise
+
+        if DEBUG:
+            print(itemsim)
+
+        self.assertEqual(itemsim, {"pio_iids": ["i2", "i3", "i0"], "custom1": [None, None, "i0c1"],
+                                   "custom2": ["i2c2", None, None]})
+
+        # TODO pio_latlng
+        # TODO pio_within
+        # TODO pio_unit
+
+        client.close()
+
+
+if __name__ == "__main__":
+    unittest.main()


[04/24] incubator-predictionio-sdk-python git commit: Fixed indentation Deleted obsolete examples Moved obsolete test suite to 'test-obsolete' (port as we go) Added tox test bootstrapping Ignored pycharm, test output Removed obsolete (<0.8) support PEP8/

Posted by sh...@apache.org.
Fixed indentation
Deleted obsolete examples
Moved obsolete test suite to 'test-obsolete' (port as we go)
Added tox test bootstrapping
Ignored pycharm, test output
Removed obsolete (<0.8) support
PEP8/Flake + py2&3 support
Bumped version


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/bc678328
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/bc678328
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/bc678328

Branch: refs/heads/master
Commit: bc6783282a198ea417e84c1bbc882aa41dd3ffae
Parents: 7b66a7a
Author: Filipe Varela <fc...@gmail.com>
Authored: Tue Jan 13 17:29:45 2015 +0000
Committer: Filipe Varela <fc...@gmail.com>
Committed: Thu Jan 15 12:20:40 2015 +0000

----------------------------------------------------------------------
 .gitignore                                      |    4 +
 docs/source/conf.py                             |  108 +-
 examples/demo-movielens/appdata.py              |  316 ++---
 examples/demo-movielens/batch_import.py         |  246 ++--
 examples/event_sample.py                        |   50 +-
 examples/import_yahoo.py                        |  261 ++--
 examples/itemrank_quick_query.py                |   18 +-
 examples/itemrank_quick_start.py                |   69 +-
 examples/obsolete/__init__.py                   |    0
 examples/obsolete/itemrec/__init__.py           |    0
 examples/obsolete/itemrec/movies/.gitignore     |    3 -
 examples/obsolete/itemrec/movies/README.md      |   15 -
 examples/obsolete/itemrec/movies/__init__.py    |    0
 examples/obsolete/itemrec/movies/app_config.py  |    2 -
 examples/obsolete/itemrec/movies/appdata.py     |  148 ---
 .../obsolete/itemrec/movies/batch_import.py     |   65 -
 .../obsolete/itemrec/movies/movie_rec_app.py    |  152 ---
 predictionio/__init__.py                        |  809 ++++++------
 predictionio/connection.py                      |  584 +++++----
 predictionio/obsolete.py                        | 1205 ------------------
 setup.py                                        |   32 +-
 tests-obsolete/conversion_test.py               |   16 +
 tests-obsolete/import_testdata.py               |   46 +
 tests-obsolete/import_testdata_id_mismatch.py   |   46 +
 tests-obsolete/import_testdata_special_char.py  |   46 +
 tests-obsolete/predictionio_itemrec_test.py     |  336 +++++
 .../predictionio_itemrec_test_special_char.py   |  366 ++++++
 tests-obsolete/predictionio_itemsim_test.py     |  200 +++
 tests-obsolete/predictionio_test.py             |  257 ++++
 tests/.keep                                     |    0
 tests/conversion_test.py                        |   23 -
 tests/import_testdata.py                        |   52 -
 tests/import_testdata_id_mismatch.py            |   52 -
 tests/import_testdata_special_char.py           |   52 -
 tests/predictionio_itemrec_test.py              |  300 -----
 tests/predictionio_itemrec_test_special_char.py |  291 -----
 tests/predictionio_itemsim_test.py              |  160 ---
 tests/predictionio_test.py                      |  246 ----
 tox.ini                                         |    9 +
 39 files changed, 2573 insertions(+), 4012 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 66fa4a6..1822229 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+*.egg-info
+.idea
+.tox
+.coverage
 *.pyc
 .project
 .pydevproject

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/docs/source/conf.py
----------------------------------------------------------------------
diff --git a/docs/source/conf.py b/docs/source/conf.py
index cbcb864..539cf04 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -11,13 +11,13 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os
+import sys
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-#sys.path.append("..")
+# sys.path.insert(0, os.path.abspath('.'))
+# sys.path.append("..")
 # Use path in the SDK. Hence need to override system package path by inserting
 # to position 0.
 sys.path.insert(0, "..")
@@ -25,7 +25,7 @@ sys.path.insert(0, "..")
 # -- General configuration -----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
@@ -38,7 +38,7 @@ templates_path = ['_templates']
 source_suffix = '.rst'
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
 master_doc = 'index'
@@ -58,37 +58,37 @@ release = '0.8.3'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
-#language = None
+# language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 exclude_patterns = []
 
 # The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+# default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
 pygments_style = 'sphinx'
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 
 # -- Options for HTML output ---------------------------------------------------
@@ -100,72 +100,72 @@ html_theme = 'default'
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-#html_static_path = ['_static']
+# html_static_path = ['_static']
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 # If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'PredictionIO-Python-SDKdoc'
@@ -174,42 +174,42 @@ htmlhelp_basename = 'PredictionIO-Python-SDKdoc'
 # -- Options for LaTeX output --------------------------------------------------
 
 latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
+    # The paper size ('letterpaper' or 'a4paper').
+    # 'papersize': 'letterpaper',
 
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
+    # The font size ('10pt', '11pt' or '12pt').
+    # 'pointsize': '10pt',
 
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+    # Additional stuff for the LaTeX preamble.
+    # 'preamble': '',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'PredictionIO-Python-SDK.tex', u'PredictionIO-Python-SDK Documentation',
-   u'TappingStone', 'manual'),
+    ('index', 'PredictionIO-Python-SDK.tex', u'PredictionIO-Python-SDK Documentation',
+     u'TappingStone', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output --------------------------------------------
@@ -222,27 +222,27 @@ man_pages = [
 ]
 
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 # -- Options for Texinfo output ------------------------------------------------
 
 # Grouping the document tree into Texinfo files. List of tuples
 # (source start file, target name, title, author,
-#  dir menu entry, description, category)
+# dir menu entry, description, category)
 texinfo_documents = [
-  ('index', 'PredictionIO-Python-SDK', u'PredictionIO-Python-SDK Documentation',
-   u'TappingStone', 'PredictionIO-Python-SDK', 'One line description of project.',
-   'Miscellaneous'),
+    ('index', 'PredictionIO-Python-SDK', u'PredictionIO-Python-SDK Documentation',
+     u'TappingStone', 'PredictionIO-Python-SDK', 'One line description of project.',
+     'Miscellaneous'),
 ]
 
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 autodoc_member_order = 'bysource'

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/demo-movielens/appdata.py
----------------------------------------------------------------------
diff --git a/examples/demo-movielens/appdata.py b/examples/demo-movielens/appdata.py
index d9637ef..354f31e 100644
--- a/examples/demo-movielens/appdata.py
+++ b/examples/demo-movielens/appdata.py
@@ -1,6 +1,5 @@
-
 import datetime
-from operator import itemgetter, attrgetter
+from operator import attrgetter
 
 # can get sample data here:
 # wget http://www.grouplens.org/system/files/ml-100k.zip
@@ -15,169 +14,170 @@ RATE_ACTIONS_DELIMITER = "\t"
 
 
 class User:
-  def __init__(self, uid):
-    self.uid = uid
-    self.rec = [] # recommendations, list of iid
+    def __init__(self, uid):
+        self.uid = uid
+        self.rec = []  # recommendations, list of iid
+
+    def __str__(self):
+        return "User[uid=%s,rec=%s]" % (self.uid, self.rec)
 
-  def __str__(self):
-    return "User[uid=%s,rec=%s]" % (self.uid, self.rec)
 
 class Item:
-  def __init__(self, iid, name, release_date, genres, year):
-    self.iid = iid
-    self.name = name
-    self.release_date = release_date # datetime.datetime object
-    self.genres = genres
-    self.year = year
+    def __init__(self, iid, name, release_date, genres, year):
+        self.iid = iid
+        self.name = name
+        self.release_date = release_date  # datetime.datetime object
+        self.genres = genres
+        self.year = year
+
+    def __str__(self):
+        return "Item[iid=%s,name=%s,release_date=%s,genres=%s]" % (self.iid, self.name, self.release_date, self.genres)
 
-  def __str__(self):
-    return "Item[iid=%s,name=%s,release_date=%s,genres=%s]" % (self.iid, self.name, self.release_date, self.genres)
 
 class RateAction:
-  def __init__(self, uid, iid, rating, t):
-    self.uid = uid
-    self.iid = iid
-    self.rating = rating
-    self.t = t
+    def __init__(self, uid, iid, rating, t):
+        self.uid = uid
+        self.iid = iid
+        self.rating = rating
+        self.t = t
 
-  def __str__(self):
-    return "RateAction[uid=%s,iid=%s,rating=%s,t=%s]" % (self.uid, self.iid, self.rating, self.t)
+    def __str__(self):
+        return "RateAction[uid=%s,iid=%s,rating=%s,t=%s]" % (self.uid, self.iid, self.rating, self.t)
 
 
 class AppData:
-
-  def __init__(self):
-    self._users = {} # dict of User obj
-    self._items = {} # dict of Item obj
-    self._rate_actions = [] # list of RateAction obj
-
-    self._users_file = "%s/%s" % (APPDATA_DIRNAME, USERS_FILENAME)
-    self._items_file = "%s/%s" % (APPDATA_DIRNAME, ITEMS_FILENAME)
-    self._rate_actions_file = "%s/%s" % (APPDATA_DIRNAME, RATE_ACTIONS_FILENAME)
-    self.__init_users()
-    self.__init_items()
-    self.__init_rate_actions()
-
-  def __init_users(self):
-    """
-    uid|
-    """
-    print "[Info] Initializing users..."
-    f = open(self._users_file, 'r')
-    for line in f:
-      data = line.rstrip('\r\n').split(USERS_FILE_DELIMITER)
-      self.add_user(User(data[0]))
-    f.close()
-    print "[Info] %s users were initialized." % len(self._users)
-
-  def __init_items(self):
-    """
-    movie id | movie title | release date | video release date |
-        IMDb URL | unknown | Action | Adventure | Animation |
-        Children's | Comedy | Crime | Documentary | Drama | Fantasy |
-        Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi |
-        Thriller | War | Western |
-        The last 19 fields are the genres, a 1 indicates the movie
-        is of that genre, a 0 indicates it is not; movies can be in
-        several genres at once.
-
-    """
-    genre_names = [ "unknown", "Action", "Adventure", "Animation",
-      "Children's", "Comedy", "Crime", "Documentary", "Drama", "Fantasy",
-      "Film-Noir", "Horror", "Musical", "Mystery", "Romance", "Sci-Fi",
-      "Thriller", "War", "Western"]
-
-    print "[Info] Initializing items..."
-    f = open(self._items_file, 'r')
-    for line in f:
-      data = line.rstrip('\r\n').split(ITEMS_FILE_DELIMITER)
-      genres_flags = data[5:24]
-
-      genres = () # tuple of genres
-      for g,flag in zip(genre_names, genres_flags):
-        if flag == '1':
-          genres = genres + (g,)
-
-      try:
-        # eg. 01-Jan-1994
-        release_date = datetime.datetime.strptime(data[2], "%d-%b-%Y").replace(microsecond=1)
-        (day, month, year) = data[2].split('-')
-      except:
-        print "[Note] item %s %s doesn't have release date. Skip it." % (data[0], data[1])
-      else:
-        self.add_item(Item(
-          iid=data[0],
-          name=data[1],
-          release_date=release_date,
-          genres=genres,
-          year=year))
-    f.close()
-    print "[Info] %s items were initialized." % len(self._items)
-
-  def __init_rate_actions(self):
-    """
-    uid|iid|rating|timestamp
-    """
-    print "[Info] Initializing rate actions..."
-    f = open(self._rate_actions_file, 'r')
-    for line in f:
-      data = line.rstrip('\r\n').split(RATE_ACTIONS_DELIMITER)
-      t = datetime.datetime.utcfromtimestamp(int(data[3])).replace(microsecond=1)
-      self.add_rate_action(RateAction(data[0], data[1], data[2], t))
-    f.close()
-    print "[Info] %s rate actions were initialized." % len(self._rate_actions)
-
-  def add_user(self, user):
-    self._users[user.uid] = user
-
-  def add_item(self, item):
-    self._items[item.iid] = item
-
-  def add_rate_action(self, action):
-    self._rate_actions.append(action)
-
-  def get_users(self):
-    return self._users
-
-  def get_items(self):
-    return self._items
-
-  def get_rate_actions(self):
-    return self._rate_actions
-
-  def get_user(self, uid):
-    """return single user
-    """
-    if uid in self._users:
-      return self._users[uid]
-    else:
-      return None
-
-  def get_item(self, iid):
-    """return single item
-    """
-    if iid in self._items:
-      return self._items[iid]
-    else:
-      return None
-
-  def get_top_rated_items(self, uid, n):
-    """get top n rated iids by this uid
-    """
-    if uid in self._users:
-      actions = filter(lambda u: u.uid==uid, self._rate_actions)
-      top = sorted(actions, key=attrgetter('rating'), reverse=True)
-      topn_iids = map(lambda a: a.iid, top[:n])
-      return topn_iids
-    else:
-      return None
-
-  def get_top_rate_actions(self, uid, n):
-    """get top n rated actions by this uid
-    """
-    if uid in self._users:
-      actions = filter(lambda u: u.uid==uid, self._rate_actions)
-      top = sorted(actions, key=attrgetter('rating'), reverse=True)
-      return top[:n]
-    else:
-      return None
+    def __init__(self):
+        self._users = {}  # dict of User obj
+        self._items = {}  # dict of Item obj
+        self._rate_actions = []  # list of RateAction obj
+
+        self._users_file = "%s/%s" % (APPDATA_DIRNAME, USERS_FILENAME)
+        self._items_file = "%s/%s" % (APPDATA_DIRNAME, ITEMS_FILENAME)
+        self._rate_actions_file = "%s/%s" % (APPDATA_DIRNAME, RATE_ACTIONS_FILENAME)
+        self.__init_users()
+        self.__init_items()
+        self.__init_rate_actions()
+
+    def __init_users(self):
+        """
+        uid|
+        """
+        print("[Info] Initializing users...")
+        f = open(self._users_file, 'r')
+        for line in f:
+            data = line.rstrip('\r\n').split(USERS_FILE_DELIMITER)
+            self.add_user(User(data[0]))
+        f.close()
+        print("[Info] %s users were initialized." % len(self._users))
+
+    def __init_items(self):
+        """
+        movie id | movie title | release date | video release date |
+            IMDb URL | unknown | Action | Adventure | Animation |
+            Children's | Comedy | Crime | Documentary | Drama | Fantasy |
+            Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi |
+            Thriller | War | Western |
+            The last 19 fields are the genres, a 1 indicates the movie
+            is of that genre, a 0 indicates it is not; movies can be in
+            several genres at once.
+
+        """
+        genre_names = ["unknown", "Action", "Adventure", "Animation",
+                       "Children's", "Comedy", "Crime", "Documentary", "Drama", "Fantasy",
+                       "Film-Noir", "Horror", "Musical", "Mystery", "Romance", "Sci-Fi",
+                       "Thriller", "War", "Western"]
+
+        print("[Info] Initializing items...")
+        f = open(self._items_file, 'r')
+        for line in f:
+            data = line.rstrip('\r\n').split(ITEMS_FILE_DELIMITER)
+            genres_flags = data[5:24]
+
+            genres = ()  # tuple of genres
+            for g, flag in zip(genre_names, genres_flags):
+                if flag == '1':
+                    genres = genres + (g,)
+
+            try:
+                # eg. 01-Jan-1994
+                release_date = datetime.datetime.strptime(data[2], "%d-%b-%Y").replace(microsecond=1)
+                (day, month, year) = data[2].split('-')
+            except:
+                print("[Note] item %s %s doesn't have release date. Skip it." % (data[0], data[1]))
+            else:
+                self.add_item(Item(
+                    iid=data[0],
+                    name=data[1],
+                    release_date=release_date,
+                    genres=genres,
+                    year=year))
+        f.close()
+        print("[Info] %s items were initialized." % len(self._items))
+
+    def __init_rate_actions(self):
+        """
+        uid|iid|rating|timestamp
+        """
+        print("[Info] Initializing rate actions...")
+        f = open(self._rate_actions_file, 'r')
+        for line in f:
+            data = line.rstrip('\r\n').split(RATE_ACTIONS_DELIMITER)
+            t = datetime.datetime.utcfromtimestamp(int(data[3])).replace(microsecond=1)
+            self.add_rate_action(RateAction(data[0], data[1], data[2], t))
+        f.close()
+        print("[Info] %s rate actions were initialized." % len(self._rate_actions))
+
+    def add_user(self, user):
+        self._users[user.uid] = user
+
+    def add_item(self, item):
+        self._items[item.iid] = item
+
+    def add_rate_action(self, action):
+        self._rate_actions.append(action)
+
+    def get_users(self):
+        return self._users
+
+    def get_items(self):
+        return self._items
+
+    def get_rate_actions(self):
+        return self._rate_actions
+
+    def get_user(self, uid):
+        """return single user
+        """
+        if uid in self._users:
+            return self._users[uid]
+        else:
+            return None
+
+    def get_item(self, iid):
+        """return single item
+        """
+        if iid in self._items:
+            return self._items[iid]
+        else:
+            return None
+
+    def get_top_rated_items(self, uid, n):
+        """get top n rated iids by this uid
+        """
+        if uid in self._users:
+            actions = filter(lambda u: u.uid == uid, self._rate_actions)
+            top = sorted(actions, key=attrgetter('rating'), reverse=True)
+            topn_iids = map(lambda a: a.iid, top[:n])
+            return topn_iids
+        else:
+            return None
+
+    def get_top_rate_actions(self, uid, n):
+        """get top n rated actions by this uid
+        """
+        if uid in self._users:
+            actions = filter(lambda u: u.uid == uid, self._rate_actions)
+            top = sorted(actions, key=attrgetter('rating'), reverse=True)
+            return top[:n]
+        else:
+            return None

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/demo-movielens/batch_import.py
----------------------------------------------------------------------
diff --git a/examples/demo-movielens/batch_import.py b/examples/demo-movielens/batch_import.py
index f0fcb7c..af9c4f5 100644
--- a/examples/demo-movielens/batch_import.py
+++ b/examples/demo-movielens/batch_import.py
@@ -1,133 +1,135 @@
+import sys
+import datetime
+
+import pytz
 
 from appdata import AppData
 import predictionio
-import sys
-import pytz
-import datetime
+
 
 def batch_import_task(app_data, client, all_info=False):
-  # event_time is an important properties used by the PredictionIO platform. It
-  # is particularly useful in generating training and testing set, which uses
-  # event_time for splitting. Hence, when we import data, better to make the
-  # event_time as approximate to fact as possible.
-  #
-  # However, in many cases, the data doesn't come with a time. Movie-lens' user
-  # data, for example, only reveals the age, gender, occupation, and zip code of
-  # a user. It doesn't report when the user is "created". Likewise, for items,
-  # it only reports the release date.
-  #
-  # To remedy this problem, we have to make some assumptions to the data. In
-  # this import script, the event_time for user is set to epoch=0, and the
-  # event_time for item is set to the release_date + 00:00:00 UTC.
-
-  print "[Info] Importing users to PredictionIO..."
-  user_create_time = datetime.datetime.fromtimestamp(0, tz=pytz.utc)
-  count = 0
-  set_user_request_list = []
-  for k, v in app_data.get_users().iteritems():
-    count += 1
-    if all_info:
-      print "[Info] Importing %s..." % v
-    else:
-      if (count % 32 == 0):
-        sys.stdout.write('\r[Info] %s' % count)
-        sys.stdout.flush()
-
-    set_user_request_list.append(
-        client.aset_user(uid=v.uid, event_time=user_create_time))
-
-  [r.get_response() for r in set_user_request_list]
-  sys.stdout.write('\r[Info] %s users were imported.\n' % count)
-  sys.stdout.flush()
-
-  print "[Info] Importing items to PredictionIO..."
-  count = 0
-  set_item_request_list = []
-  # event_time is a datetime, hence need to add a time component to the release
-  # date.
-  midnight_utc = datetime.time(0, 0, 0, tzinfo=pytz.utc)
-  epoch = datetime.datetime.fromtimestamp(0, tz=pytz.utc)
-  for k, v in app_data.get_items().iteritems():
-    count += 1
-    if all_info:
-      print "[Info] Importing %s..." % v
-    else:
-      if (count % 32 == 0):
-        sys.stdout.write('\r[Info] %s' % count)
-        sys.stdout.flush()
-
-    itypes = ("movie",) + v.genres
-
-    release_datetime = datetime.datetime.combine(
-        v.release_date,
-        midnight_utc)
-
-    # event_time must be after epoch.
-    event_time = release_datetime if release_datetime > epoch else epoch
-
-    utf8_name = v.name.decode('utf-8', 'ignore')
-    
-    set_item_request = client.aset_item(
-        iid=v.iid,
-        event_time=event_time,
-        properties={ 
-          "itypes": list(itypes),
-          "starttime": release_datetime.isoformat(),
-          "name": utf8_name,
-          "year": v.year } )
-
-    set_item_request_list.append(set_item_request)
-
-  [r.get_response() for r in set_item_request_list]
-  sys.stdout.write('\r[Info] %s items were imported.\n' % count)
-  sys.stdout.flush()
-
-  print "[Info] Importing rate actions to PredictionIO..."
-  count = 0
-  create_event_request_list = []
-  for v in app_data.get_rate_actions():
-    count += 1
-    if all_info:
-      print "[Info] Importing %s..." % v
-    else:
-      if (count % 32 == 0):
-        sys.stdout.write('\r[Info] %s' % count)
-        sys.stdout.flush()
-
-    properties = { "rating" : int(v.rating) }
-    req = client.acreate_event(
-        event="rate",
-        entity_type="user",
-        entity_id=v.uid,
-        target_entity_type="item",
-        target_entity_id=v.iid,
-        properties=properties,
-        event_time=v.t.replace(tzinfo=pytz.utc),
+    # event_time is an important properties used by the PredictionIO platform. It
+    # is particularly useful in generating training and testing set, which uses
+    # event_time for splitting. Hence, when we import data, better to make the
+    # event_time as approximate to fact as possible.
+    #
+    # However, in many cases, the data doesn't come with a time. Movie-lens' user
+    # data, for example, only reveals the age, gender, occupation, and zip code of
+    # a user. It doesn't report when the user is "created". Likewise, for items,
+    # it only reports the release date.
+    #
+    # To remedy this problem, we have to make some assumptions to the data. In
+    # this import script, the event_time for user is set to epoch=0, and the
+    # event_time for item is set to the release_date + 00:00:00 UTC.
+
+    print("[Info] Importing users to PredictionIO...")
+    user_create_time = datetime.datetime.fromtimestamp(0, tz=pytz.utc)
+    count = 0
+    set_user_request_list = []
+    for k, v in app_data.get_users().iteritems():
+        count += 1
+        if all_info:
+            print("[Info] Importing %s..." % v)
+        else:
+            if count % 32 == 0:
+                sys.stdout.write('\r[Info] %s' % count)
+                sys.stdout.flush()
+
+        set_user_request_list.append(
+            client.aset_user(uid=v.uid, event_time=user_create_time))
+
+    [r.get_response() for r in set_user_request_list]
+    sys.stdout.write('\r[Info] %s users were imported.\n' % count)
+    sys.stdout.flush()
+
+    print("[Info] Importing items to PredictionIO...")
+    count = 0
+    set_item_request_list = []
+    # event_time is a datetime, hence need to add a time component to the release
+    # date.
+    midnight_utc = datetime.time(0, 0, 0, tzinfo=pytz.utc)
+    epoch = datetime.datetime.fromtimestamp(0, tz=pytz.utc)
+    for k, v in app_data.get_items().iteritems():
+        count += 1
+        if all_info:
+            print("[Info] Importing %s..." % v)
+        else:
+            if count % 32 == 0:
+                sys.stdout.write('\r[Info] %s' % count)
+                sys.stdout.flush()
+
+        itypes = ("movie",) + v.genres
+
+        release_datetime = datetime.datetime.combine(
+            v.release_date,
+            midnight_utc)
+
+        # event_time must be after epoch.
+        event_time = release_datetime if release_datetime > epoch else epoch
+
+        utf8_name = v.name.decode('utf-8', 'ignore')
+
+        set_item_request = client.aset_item(
+            iid=v.iid,
+            event_time=event_time,
+            properties={
+                "itypes": list(itypes),
+                "starttime": release_datetime.isoformat(),
+                "name": utf8_name,
+                "year": v.year})
+
+        set_item_request_list.append(set_item_request)
+
+    [r.get_response() for r in set_item_request_list]
+    sys.stdout.write('\r[Info] %s items were imported.\n' % count)
+    sys.stdout.flush()
+
+    print("[Info] Importing rate actions to PredictionIO...")
+    count = 0
+    create_event_request_list = []
+    for v in app_data.get_rate_actions():
+        count += 1
+        if all_info:
+            print("[Info] Importing %s..." % v)
+        else:
+            if count % 32 == 0:
+                sys.stdout.write('\r[Info] %s' % count)
+                sys.stdout.flush()
+
+        properties = {"rating": int(v.rating)}
+        req = client.acreate_event(
+            event="rate",
+            entity_type="user",
+            entity_id=v.uid,
+            target_entity_type="item",
+            target_entity_id=v.iid,
+            properties=properties,
+            event_time=v.t.replace(tzinfo=pytz.utc),
         )
 
-    create_event_request_list.append(req)
+        create_event_request_list.append(req)
 
-  [r.get_response() for r in create_event_request_list]
-  sys.stdout.write('\r[Info] %s rate actions were imported.\n' % count)
-  sys.stdout.flush()
+    [r.get_response() for r in create_event_request_list]
+    sys.stdout.write('\r[Info] %s rate actions were imported.\n' % count)
+    sys.stdout.flush()
 
 
 if __name__ == '__main__':
-  if len(sys.argv) < 3:
-    sys.exit("Usage: python -m examples.demo-movielens.batch_import "
-        "<access_key> <url>")
-
-  access_key = sys.argv[1]
-
-  client = predictionio.EventClient(
-      access_key=access_key,
-      url=sys.argv[2],
-      threads=5,
-      qsize=500)
-
-  # Test connection
-  print "Status:", client.get_status()
-  
-  app_data = AppData()
-  batch_import_task(app_data, client)
-  client.close()
+    if len(sys.argv) < 3:
+        sys.exit("Usage: python -m examples.demo-movielens.batch_import "
+                 "<access_key> <url>")
+
+    access_key = sys.argv[1]
+
+    client = predictionio.EventClient(
+        access_key=access_key,
+        url=sys.argv[2],
+        threads=5,
+        qsize=500)
+
+    # Test connection
+    print("Status:", client.get_status())
+
+    app_data = AppData()
+    batch_import_task(app_data, client)
+    client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/event_sample.py
----------------------------------------------------------------------
diff --git a/examples/event_sample.py b/examples/event_sample.py
index 0a7a339..b76bcf7 100644
--- a/examples/event_sample.py
+++ b/examples/event_sample.py
@@ -1,10 +1,12 @@
-from predictionio import EventClient
-from predictionio import NotFoundError
 from datetime import datetime
+
 import pytz
-import sys
 
-access_key = None
+from predictionio import EventClient
+from predictionio import NotFoundError
+
+
+access_key = "gDx1XuMUC9vu1YWWPRZkLRTftoq7m73mlj2MtnZEjncPlZ1JxUS2s7oajwP9xrZQ"
 assert access_key is not None, "Please create an access key with 'pio app new'"
 
 client = EventClient(access_key=access_key, url="http://localhost:7070")
@@ -15,13 +17,13 @@ print(client.get_status())
 
 # First event
 first_event_properties = {
-    "prop1" : 1,
-    "prop2" : "value2",
-    "prop3" : [1, 2, 3],
-    "prop4" : True,
-    "prop5" : ["a", "b", "c"],
-    "prop6" : 4.56 ,
-    }
+    "prop1": 1,
+    "prop2": "value2",
+    "prop3": [1, 2, 3],
+    "prop4": True,
+    "prop5": ["a", "b", "c"],
+    "prop6": 4.56,
+}
 first_event_time = datetime(
     2004, 12, 13, 21, 39, 45, 618000, pytz.timezone('US/Mountain'))
 first_event_response = client.create_event(
@@ -30,16 +32,16 @@ first_event_response = client.create_event(
     entity_id="uid",
     properties=first_event_properties,
     event_time=first_event_time,
-    )
+)
 print("First Event response")
 print(first_event_response)
-print
+print()
 
 # Second event
 second_event_properties = {
-    "someProperty" : "value1",
-    "anotherProperty" : "value2",
-    }
+    "someProperty": "value1",
+    "anotherProperty": "value2",
+}
 second_event_response = client.create_event(
     event="my_event",
     entity_type="user",
@@ -50,7 +52,7 @@ second_event_response = client.create_event(
     event_time=datetime(2014, 12, 13, 21, 38, 45, 618000, pytz.utc))
 print("Second Event response")
 print(second_event_response)
-print
+print()
 
 
 # Get the first event from Event Server
@@ -58,21 +60,21 @@ first_event_id = first_event_response.json_body["eventId"]
 print("Get Event")
 event = client.get_event(first_event_id)
 print(event)
-print
+print()
 
 # Delete the first event from Event Server
 print("Delete Event")
 delete_response = client.delete_event(first_event_id)
 print(delete_response)
-print
+print()
 
 # Delete the first event from Event Server again should yield exception.
 print("Delete Event Again")
 try:
-  delete_response = client.delete_event(first_event_id)
-except NotFoundError, ex:
-  print("The expected error: {0}".format(ex))
-print
+    delete_response = client.delete_event(first_event_id)
+except NotFoundError as ex:
+    print("The expected error: {0}".format(ex))
+print()
 
 # "user"-helper methods
 
@@ -98,7 +100,7 @@ print(client.unset_user("foo", properties=foo_properties))
 print("Delete user")
 print(client.delete_user("foo"))
 
-# The SDK also support specifying the eventTime. It is useful for importing 
+# The SDK also support specifying the eventTime. It is useful for importing
 # events happened in the past.
 foo_time = datetime(2014, 8, 31, 4, 56, tzinfo=pytz.timezone('US/Pacific'))
 print("Create user at " + str(foo_time))

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/import_yahoo.py
----------------------------------------------------------------------
diff --git a/examples/import_yahoo.py b/examples/import_yahoo.py
index 93b367d..584a8c9 100644
--- a/examples/import_yahoo.py
+++ b/examples/import_yahoo.py
@@ -3,13 +3,14 @@ Import historical stock data from yahoo finance.
 """
 
 from datetime import datetime
+import sys
+
+import pytz
+
 from pandas.io import data as pdata
-import argparse
 import numpy
 import predictionio
-import pytz
-import sys
-import time
+
 
 EPOCH = datetime(1970, 1, 1, tzinfo=pytz.utc)
 
@@ -63,151 +64,151 @@ SP500_LIST = [
     "WU", "WY", "WYN", "WYNN", "X", "XEL", "XL", "XLNX", "XOM", "XRAY", "XRX",
     "XYL", "YHOO", "YUM", "ZION", "ZMH", "ZTS"]
 
-ETF_LIST = ["QQQ", "SPY", "XLY", "XLP", "XLE", "XLF", "XLV", 
-    "XLI", "XLB", "XLK", "XLU"]
+ETF_LIST = ["QQQ", "SPY", "XLY", "XLP", "XLE", "XLF", "XLV",
+            "XLI", "XLB", "XLK", "XLU"]
 
 
 def since_epoch(dt):
-  return (dt - EPOCH).total_seconds()
+    return (dt - EPOCH).total_seconds()
 
 
 def import_data(client, access_key, ticker, start_time, end_time, event_time):
-  print "Importing:", ticker, start_time, end_time
-
-  try:
-    df = pdata.DataReader(ticker, 'yahoo', start_time, end_time)
-    print "Extracted:", df.index[0], df.index[-1]
-  except IOError, ex:
-    print ex
-    print "Data not exist. Returning"
-    return
-
-  # assume we only extract US data
-  eastern = pytz.timezone('US/Eastern')
-
-  columns = [
-      ('Open', 'open'),
-      ('High', 'high'),
-      ('Low', 'low'),
-      ('Close', 'close'),
-      ('Volume', 'volume'),
-      ('Adj Close', 'adjclose')]
-
-  yahoo_data = dict()
-  yahoo_data['ticker'] = ticker
-  yahoo_data['t'] = [
-      # hour=16 to indicate market close time
-      since_epoch(eastern.localize(date_.to_pydatetime().replace(hour=16)))
-      for date_ in df.index]
-
-  for column in columns:
-    yahoo_data[column[1]] = map(numpy.asscalar, df[column[0]].values)
-
-  properties = {'yahoo': yahoo_data}
-
-  response = client.create_event(
-      event='$set',
-      entity_type='yahoo',
-      entity_id=ticker,
-      properties=properties,
-      event_time=event_time.replace(tzinfo=pytz.utc))
-      
-  print(response)
+    print("Importing:", ticker, start_time, end_time)
+
+    try:
+        df = pdata.DataReader(ticker, 'yahoo', start_time, end_time)
+        print("Extracted:", df.index[0], df.index[-1])
+    except IOError as ex:
+        print(ex)
+        print("Data not exist. Returning")
+        return
+
+    # assume we only extract US data
+    eastern = pytz.timezone('US/Eastern')
+
+    columns = [
+        ('Open', 'open'),
+        ('High', 'high'),
+        ('Low', 'low'),
+        ('Close', 'close'),
+        ('Volume', 'volume'),
+        ('Adj Close', 'adjclose')]
+
+    yahoo_data = dict()
+    yahoo_data['ticker'] = ticker
+    yahoo_data['t'] = [
+        # hour=16 to indicate market close time
+        since_epoch(eastern.localize(date_.to_pydatetime().replace(hour=16)))
+        for date_ in df.index]
+
+    for column in columns:
+        yahoo_data[column[1]] = map(numpy.asscalar, df[column[0]].values)
+
+    properties = {'yahoo': yahoo_data}
+
+    response = client.create_event(
+        event='$set',
+        entity_type='yahoo',
+        entity_id=ticker,
+        properties=properties,
+        event_time=event_time.replace(tzinfo=pytz.utc))
+
+    print(response)
 
 
 def import_all(access_key):
-  """This method import all SP500 stocks and some SPDR ETFs."""
-  time_slices = [
-      (datetime(1999, 1, 1), datetime(2004, 1, 1), datetime(2004, 1, 2)),
-      (datetime(2003, 12, 1), datetime(2009, 1, 1), datetime(2009, 1, 2)),
-      (datetime(2008, 12, 1), datetime(2014, 9, 1), datetime(2014, 9, 2)),
-      ]
+    """This method import all SP500 stocks and some SPDR ETFs."""
+    time_slices = [
+        (datetime(1999, 1, 1), datetime(2004, 1, 1), datetime(2004, 1, 2)),
+        (datetime(2003, 12, 1), datetime(2009, 1, 1), datetime(2009, 1, 2)),
+        (datetime(2008, 12, 1), datetime(2014, 9, 1), datetime(2014, 9, 2)),
+    ]
 
-  url = 'http://localhost:7070'
-  client = predictionio.EventClient(access_key=access_key, threads=1, url=url)
+    url = 'http://localhost:7070'
+    client = predictionio.EventClient(access_key=access_key, threads=1, url=url)
 
-  tickers = SP500_LIST + ETF_LIST 
+    tickers = SP500_LIST + ETF_LIST
 
-  for ticker in tickers:
-    for time_slice in time_slices:
-      import_data(client, access_key, ticker, 
-          time_slice[0], time_slice[1], time_slice[2])
+    for ticker in tickers:
+        for time_slice in time_slices:
+            import_data(client, access_key, ticker,
+                        time_slice[0], time_slice[1], time_slice[2])
 
 
 def import_data_with_gaps(access_key):
-  """This method import data with time gaps. 
-  
-  Data imported by this method is used by stock engine, it demonsrates how it
-  can handle time series data with gaps.
-  """ 
-
-  # time_slices is discontinuted
-  # startTime, endTime, eventDate
-  time_slices = [
-      (datetime(2013, 12, 1), datetime(2014, 2, 1), datetime(2014, 2, 2)),
-      (datetime(2014, 1, 1), datetime(2014, 1, 20), datetime(2014, 2, 10)),
-      (datetime(2014, 1, 10), datetime(2014, 2, 20), datetime(2014, 2, 28)),
-      (datetime(2014, 2, 10), datetime(2014, 3, 31), datetime(2014, 4, 2)),
-      (datetime(2014, 5, 1), datetime(2014, 6, 15), datetime(2014, 6, 20)),
-      (datetime(2014, 6, 1), datetime(2014, 7, 1), datetime(2014, 7, 15)),
-      ]
-
-  tickers = ['SPY', 'AAPL', 'IBM', 'MSFT']
- 
-  url = 'http://localhost:7070'
-  client = predictionio.EventClient(access_key=access_key, threads=1, url=url)
-
-  for ticker in tickers:
-    for time_slice in time_slices:
-      import_data(client, access_key, ticker, 
-          time_slice[0], time_slice[1], time_slice[2])
-
-  # below are data with holes
-  time_slices = [
-      (datetime(2014, 1, 1), datetime(2014, 1, 20), datetime(2014, 2, 10)),
-      (datetime(2014, 2, 10), datetime(2014, 3, 31), datetime(2014, 4, 2)),
-      (datetime(2014, 6, 1), datetime(2014, 7, 1), datetime(2014, 7, 15)),
-      ]
-
-  tickers = ['AMZN']
-  for ticker in tickers:
-    for time_slice in time_slices:
-      import_data(client, access_key, ticker, 
-          time_slice[0], time_slice[1], time_slice[2])
-
-  time_slices = [
-      (datetime(2014, 1, 10), datetime(2014, 2, 20), datetime(2014, 2, 28)),
-      (datetime(2014, 2, 10), datetime(2014, 3, 31), datetime(2014, 4, 2)),
-      ]
-  tickers = ['FB']
-  for ticker in tickers:
-    for time_slice in time_slices:
-      import_data(client, access_key, ticker, 
-          time_slice[0], time_slice[1], time_slice[2])
+    """This method import data with time gaps.
+
+    Data imported by this method is used by stock engine, it demonsrates how it
+    can handle time series data with gaps.
+    """
+
+    # time_slices is discontinuted
+    # startTime, endTime, eventDate
+    time_slices = [
+        (datetime(2013, 12, 1), datetime(2014, 2, 1), datetime(2014, 2, 2)),
+        (datetime(2014, 1, 1), datetime(2014, 1, 20), datetime(2014, 2, 10)),
+        (datetime(2014, 1, 10), datetime(2014, 2, 20), datetime(2014, 2, 28)),
+        (datetime(2014, 2, 10), datetime(2014, 3, 31), datetime(2014, 4, 2)),
+        (datetime(2014, 5, 1), datetime(2014, 6, 15), datetime(2014, 6, 20)),
+        (datetime(2014, 6, 1), datetime(2014, 7, 1), datetime(2014, 7, 15)),
+    ]
+
+    tickers = ['SPY', 'AAPL', 'IBM', 'MSFT']
+
+    url = 'http://localhost:7070'
+    client = predictionio.EventClient(access_key=access_key, threads=1, url=url)
+
+    for ticker in tickers:
+        for time_slice in time_slices:
+            import_data(client, access_key, ticker,
+                        time_slice[0], time_slice[1], time_slice[2])
+
+    # below are data with holes
+    time_slices = [
+        (datetime(2014, 1, 1), datetime(2014, 1, 20), datetime(2014, 2, 10)),
+        (datetime(2014, 2, 10), datetime(2014, 3, 31), datetime(2014, 4, 2)),
+        (datetime(2014, 6, 1), datetime(2014, 7, 1), datetime(2014, 7, 15)),
+    ]
+
+    tickers = ['AMZN']
+    for ticker in tickers:
+        for time_slice in time_slices:
+            import_data(client, access_key, ticker,
+                        time_slice[0], time_slice[1], time_slice[2])
+
+    time_slices = [
+        (datetime(2014, 1, 10), datetime(2014, 2, 20), datetime(2014, 2, 28)),
+        (datetime(2014, 2, 10), datetime(2014, 3, 31), datetime(2014, 4, 2)),
+    ]
+    tickers = ['FB']
+    for ticker in tickers:
+        for time_slice in time_slices:
+            import_data(client, access_key, ticker,
+                        time_slice[0], time_slice[1], time_slice[2])
 
 
 def import_one(access_key):
-  """Import TSLA.
-  
-  Import data with from 2014-01-01 until 2014-03-01. event_time specifies when
-  this data is extracted. 
-  """
-  start_time = datetime(2014, 1, 1)
-  end_time = datetime(2014, 3, 1)
-  event_time = datetime(2014, 9, 1)
-  ticker = 'TSLA'
- 
-  url = 'http://localhost:7070'
-  client = predictionio.EventClient(access_key=access_key, threads=1, url=url)
-
-  import_data(client, access_key, ticker, start_time, end_time, event_time)
+    """Import TSLA.
+
+    Import data with from 2014-01-01 until 2014-03-01. event_time specifies when
+    this data is extracted.
+    """
+    start_time = datetime(2014, 1, 1)
+    end_time = datetime(2014, 3, 1)
+    event_time = datetime(2014, 9, 1)
+    ticker = 'TSLA'
+
+    url = 'http://localhost:7070'
+    client = predictionio.EventClient(access_key=access_key, threads=1, url=url)
+
+    import_data(client, access_key, ticker, start_time, end_time, event_time)
 
 
 if __name__ == '__main__':
-  if len(sys.argv) < 2:
-    sys.exit("Usage: python -m examples.import_yahoo <access_key>")
+    if len(sys.argv) < 2:
+        sys.exit("Usage: python -m examples.import_yahoo <access_key>")
 
-  access_key = sys.argv[1]
-  import_all(access_key=access_key)
-  #import_data_with_gaps(access_key=access_key)
-  #import_one(access_key=access_key)
+    access_key = sys.argv[1]
+    import_all(access_key=access_key)
+    # import_data_with_gaps(access_key=access_key)
+    # import_one(access_key=access_key)

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/itemrank_quick_query.py
----------------------------------------------------------------------
diff --git a/examples/itemrank_quick_query.py b/examples/itemrank_quick_query.py
index 3c43713..2beb29b 100644
--- a/examples/itemrank_quick_query.py
+++ b/examples/itemrank_quick_query.py
@@ -10,14 +10,14 @@ client = predictionio.EngineClient("http://localhost:8000")
 item_ids = [str(i) for i in range(1, 6)]
 user_ids = [str(x) for x in range(1, 6)] + ["NOT_EXIST_USER"]
 for user_id in user_ids:
-  print "Rank item 1 to 5 for user", user_id
-  try:
-    response = client.send_query({
-      "uid": user_id,
-      "iids": item_ids
-    })
-    print response
-  except predictionio.PredictionIOAPIError as e:
-    print 'Caught exception:', e
+    print("Rank item 1 to 5 for user ", user_id)
+    try:
+        response = client.send_query({
+            "uid": user_id,
+            "iids": item_ids
+        })
+        print(response)
+    except predictionio.PredictionIOAPIError as e:
+        print("Caught exception: ", e)
 
 client.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/itemrank_quick_start.py
----------------------------------------------------------------------
diff --git a/examples/itemrank_quick_start.py b/examples/itemrank_quick_start.py
index 6333ea0..a231373 100644
--- a/examples/itemrank_quick_start.py
+++ b/examples/itemrank_quick_start.py
@@ -2,44 +2,47 @@
 itemrank quickstart import data
 """
 
-import predictionio
-
 import random
 import sys
 
+import predictionio
+
+
 def import_itemrank(access_key):
+    random.seed()
+
+    client = predictionio.EventClient(access_key)
+
+    print(client.get_status())
+
+    # generate 10 users, with user ids 1,2,....,10
+    user_ids = [str(i) for i in range(1, 11)]
+    for user_id in user_ids:
+        print
+        "Set user", user_id
+        client.set_user(user_id)
+
+    # generate 50 items, with item ids 1,2,....,50
+    # assign type id 1 to all of them
+    item_ids = [str(i) for i in range(1, 51)]
+    for item_id in item_ids:
+        print
+        "Set item", item_id
+        client.set_item(item_id, {
+            "itypes": ['1']
+        })
+
+    # each user randomly views 10 items
+    for user_id in user_ids:
+        for viewed_item in random.sample(item_ids, 10):
+            print
+            "User", user_id, "views item", viewed_item
+            client.record_user_action_on_item("view", user_id, viewed_item)
 
-  random.seed()
-  
-  client = predictionio.EventClient(access_key)
-
-  print client.get_status()
-  
-  # generate 10 users, with user ids 1,2,....,10
-  user_ids = [str(i) for i in range(1, 11)]
-  for user_id in user_ids:
-    print "Set user", user_id
-    client.set_user(user_id)
-  
-  # generate 50 items, with item ids 1,2,....,50
-  # assign type id 1 to all of them
-  item_ids = [str(i) for i in range(1, 51)]
-  for item_id in item_ids:
-    print "Set item", item_id
-    client.set_item(item_id, {
-      "itypes" : ['1']
-    })
-  
-  # each user randomly views 10 items
-  for user_id in user_ids:
-    for viewed_item in random.sample(item_ids, 10):
-      print "User", user_id ,"views item", viewed_item
-      client.record_user_action_on_item("view", user_id, viewed_item)
-  
-  client.close()
+    client.close()
 
 
 if __name__ == '__main__':
-  if len(sys.argv) < 2:
-    sys.exit("Usage: python -m examples.itemrank_quick_start <access_key>")
-  import_itemrank(sys.argv[1])
+    if len(sys.argv) < 2:
+        sys.exit("Usage: python -m examples.itemrank_quick_start <access_key>")
+    import_itemrank(sys.argv[1])

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/__init__.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/__init__.py b/examples/obsolete/__init__.py
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/__init__.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/__init__.py b/examples/obsolete/itemrec/__init__.py
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/.gitignore
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/.gitignore b/examples/obsolete/itemrec/movies/.gitignore
deleted file mode 100644
index 7b1ef3e..0000000
--- a/examples/obsolete/itemrec/movies/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-test/
-ml-100k/
-ml-100k.zip

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/README.md
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/README.md b/examples/obsolete/itemrec/movies/README.md
deleted file mode 100644
index 9ef357a..0000000
--- a/examples/obsolete/itemrec/movies/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-PredictionIO Python SDK Example
-===============================
-
-Please execute all commands from repository root.
-
-Step 1. Get sample data and unzip it.
-
-    > wget http://www.grouplens.org/system/files/ml-100k.zip
-    > unzip ml-100k.zip
-
-Step 2. Configurate examples/itemrec/movies/appdata.py
-
-Step 3. Run this app:
-
-    > python -m examples.itemrec.movies.movie_rec_app

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/__init__.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/__init__.py b/examples/obsolete/itemrec/movies/__init__.py
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/app_config.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/app_config.py b/examples/obsolete/itemrec/movies/app_config.py
deleted file mode 100644
index 5efa7a0..0000000
--- a/examples/obsolete/itemrec/movies/app_config.py
+++ /dev/null
@@ -1,2 +0,0 @@
-APP_KEY = 'uJKTKyUAFNZYQQO5yxkdrSo3XIlaf9LXejI63CWE0mtZVEYF89hyVtOwpMKfXXXX'
-API_URL = 'http://localhost:8000'

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/appdata.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/appdata.py b/examples/obsolete/itemrec/movies/appdata.py
deleted file mode 100644
index fb3c7fd..0000000
--- a/examples/obsolete/itemrec/movies/appdata.py
+++ /dev/null
@@ -1,148 +0,0 @@
-
-import datetime
-from operator import itemgetter, attrgetter
-
-# can get sample data here:
-# wget http://www.grouplens.org/system/files/ml-100k.zip
-# app data file config
-APPDATA_DIRNAME = "ml-100k"
-USERS_FILENAME = "u.user"
-USERS_FILE_DELIMITER = "|"
-ITEMS_FILENAME = "u.item"
-ITEMS_FILE_DELIMITER = "|"
-RATE_ACTIONS_FILENAME = "u.data"
-RATE_ACTIONS_DELIMITER = "\t"
-
-
-class User:
-  def __init__(self, uid):
-    self.uid = uid
-    self.rec = [] # recommendations, list of iid
-
-  def __str__(self):
-    return "User[uid=%s,rec=%s]" % (self.uid, self.rec)
-
-class Item:
-  def __init__(self, iid, name):
-    self.iid = iid
-    self.name = name
-
-  def __str__(self):
-    return "Item[iid=%s,name=%s]" % (self.iid, self.name)
-
-class RateAction:
-  def __init__(self, uid, iid, rating, t):
-    self.uid = uid
-    self.iid = iid
-    self.rating = rating
-    self.t = t
-
-  def __str__(self):
-    return "RateAction[uid=%s,iid=%s,rating=%s,t=%s]" % (self.uid, self.iid, self.rating, self.t)
-
-
-class AppData:
-
-  def __init__(self):
-    self._users = {} # dict of User obj
-    self._items = {} # dict of Item obj
-    self._rate_actions = [] # list of RateAction obj
-
-    self._users_file = "%s/%s" % (APPDATA_DIRNAME, USERS_FILENAME)
-    self._items_file = "%s/%s" % (APPDATA_DIRNAME, ITEMS_FILENAME)
-    self._rate_actions_file = "%s/%s" % (APPDATA_DIRNAME, RATE_ACTIONS_FILENAME)
-    self.__init_users()
-    self.__init_items()
-    self.__init_rate_actions()
-
-  def __init_users(self):
-    """
-    uid|
-    """
-    print "[Info] Initializing users..."
-    f = open(self._users_file, 'r')
-    for line in f:
-      data = line.rstrip('\r\n').split(USERS_FILE_DELIMITER)
-      self.add_user(User(data[0]))
-    f.close()
-    print "[Info] %s users were initialized." % len(self._users)
-
-  def __init_items(self):
-    """
-    iid|name
-    """
-    print "[Info] Initializing items..."
-    f = open(self._items_file, 'r')
-    for line in f:
-      data = line.rstrip('\r\n').split(ITEMS_FILE_DELIMITER)
-      self.add_item(Item(data[0], data[1]))
-    f.close()
-    print "[Info] %s items were initialized." % len(self._items)
-
-  def __init_rate_actions(self):
-    """
-    uid|iid|rating|timestamp
-    """
-    print "[Info] Initializing rate actions..."
-    f = open(self._rate_actions_file, 'r')
-    for line in f:
-      data = line.rstrip('\r\n').split(RATE_ACTIONS_DELIMITER)
-      t = datetime.datetime.utcfromtimestamp(int(data[3])).isoformat()
-      self.add_rate_action(RateAction(data[0], data[1], data[2], t))
-    f.close()
-    print "[Info] %s rate actions were initialized." % len(self._rate_actions)
-
-  def add_user(self, user):
-    self._users[user.uid] = user
-
-  def add_item(self, item):
-    self._items[item.iid] = item
-
-  def add_rate_action(self, action):
-    self._rate_actions.append(action)
-
-  def get_users(self):
-    return self._users
-
-  def get_items(self):
-    return self._items
-
-  def get_rate_actions(self):
-    return self._rate_actions
-
-  def get_user(self, uid):
-    """return single user
-    """
-    if uid in self._users:
-      return self._users[uid]
-    else:
-      return None
-
-  def get_item(self, iid):
-    """return single item
-    """
-    if iid in self._items:
-      return self._items[iid]
-    else:
-      return None
-
-  def get_top_rated_items(self, uid, n):
-    """get top n rated iids by this uid
-    """
-    if uid in self._users:
-      actions = filter(lambda u: u.uid==uid, self._rate_actions)
-      top = sorted(actions, key=attrgetter('rating'), reverse=True)
-      topn_iids = map(lambda a: a.iid, top[:n])
-      return topn_iids
-    else:
-      return None
-
-  def get_top_rate_actions(self, uid, n):
-    """get top n rated actions by this uid
-    """
-    if uid in self._users:
-      actions = filter(lambda u: u.uid==uid, self._rate_actions)
-      top = sorted(actions, key=attrgetter('rating'), reverse=True)
-      return top[:n]
-    else:
-      return None

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/batch_import.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/batch_import.py b/examples/obsolete/itemrec/movies/batch_import.py
deleted file mode 100644
index b2e0e63..0000000
--- a/examples/obsolete/itemrec/movies/batch_import.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from appdata import AppData
-import predictionio
-import sys
-
-from app_config import APP_KEY, API_URL
-
-def batch_import_task(app_data, client, all_info=False):
-
-  print "[Info] Importing users to PredictionIO..."
-  count = 0 
-  for k, v in app_data.get_users().iteritems():
-    count += 1
-    if all_info:
-      print "[Info] Importing %s..." % v
-    else:
-      if (count % 32 == 0):
-        sys.stdout.write('\r[Info] %s' % count)
-        sys.stdout.flush()
-
-    client.create_user(v.uid)
-  
-  sys.stdout.write('\r[Info] %s users were imported.\n' % count)
-  sys.stdout.flush()
-
-  print "[Info] Importing items to PredictionIO..."
-  count = 0
-  for k, v in app_data.get_items().iteritems():
-    count += 1
-    if all_info:
-      print "[Info] Importing %s..." % v
-    else:
-      if (count % 32 == 0):
-        sys.stdout.write('\r[Info] %s' % count)
-        sys.stdout.flush()
-
-    client.create_item(v.iid, ("movie",))
-  
-  sys.stdout.write('\r[Info] %s items were imported.\n' % count)
-  sys.stdout.flush()
-
-  print "[Info] Importing rate actions to PredictionIO..."
-  count = 0
-  for v in app_data.get_rate_actions():
-    count += 1
-    if all_info:
-      print "[Info] Importing %s..." % v
-    else:
-      if (count % 32 == 0):
-        sys.stdout.write('\r[Info] %s' % count)
-        sys.stdout.flush()
-
-    client.identify(v.uid)
-    client.record_action_on_item("rate", v.iid, { "pio_rate": v.rating, "pio_t": v.t })
-
-  sys.stdout.write('\r[Info] %s rate actions were imported.\n' % count)
-  sys.stdout.flush()
-
-
-if __name__ == '__main__':
-
-  app_data = AppData()
-  client = predictionio.Client(APP_KEY, 1, API_URL)
-  batch_import_task(app_data, client)
-  client.close()
-

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/examples/obsolete/itemrec/movies/movie_rec_app.py
----------------------------------------------------------------------
diff --git a/examples/obsolete/itemrec/movies/movie_rec_app.py b/examples/obsolete/itemrec/movies/movie_rec_app.py
deleted file mode 100644
index 436af38..0000000
--- a/examples/obsolete/itemrec/movies/movie_rec_app.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# To run this example app
-#
-# Please execute all commands from repository root.
-#
-# Step 1. Get sample data and unzip it.
-# > wget http://www.grouplens.org/system/files/ml-100k.zip
-# > unzip ml-100k.zip
-#
-# Step 2. Configurate examples/itemrec/movies/appdata.py
-#
-# Step 3. Run this app:
-# python -m examples.itemrec.movies.movie_rec_app
-
-from appdata import AppData
-import predictionio
-import sys
-
-from app_config import APP_KEY, API_URL
-
-ENGINE_NAME = 'movie-rec'
-
-class App:
-
-  def __init__(self):
-    self._app_data = AppData()
-    self._client = predictionio.Client(APP_KEY, 1, API_URL)
-
-  def run(self):
-    state = "[Main Menu]"
-
-    prompt = "\n"\
-      "%s\n"\
-      "%s\n"\
-      "Please input selection:\n"\
-      " 0: Quit application.\n"\
-      " 1: Get Recommendations from PredictionIO.\n"\
-      " 2: Display user's data." % (state, '-'*len(state))
-
-    while True:
-      print prompt
-      choice = raw_input().lower()
-      if choice == '0':
-        print "\nGood Bye!\n"
-        break
-      elif choice == '1':
-        self.recommend_task(state)
-      elif choice == '2':
-        self.display_user_task(state)
-      else:
-        print '[Error] \'%s\' is not a valid selection.' % choice
-
-    self._client.close()
-
-  def recommend_task(self, prev_state):
-    state = prev_state + " / [Get Recommendations]"
-    prompt = "\n"\
-      "%s\n"\
-      "%s\n"\
-      "Please enter user id:" % (state, '-'*len(state))
-
-    while True:
-      print prompt
-      choice = raw_input().lower()
-      u = self._app_data.get_user(choice)
-      if u:
-        n = 10
-        print "[Info] Getting top %s item recommendations for user %s..." % (n, u.uid)
-        try:
-          self._client.identify(u.uid)
-          rec = self._client.get_itemrec_topn(ENGINE_NAME, n)
-          u.rec = rec['pio_iids']
-          self.display_items(u.rec)
-        except predictionio.ItemRecNotFoundError:
-          print "[Info] Recommendation not found"
-
-        print "[Info] Go back to previous menu..."
-        break
-      else:
-        print "[Error] invalid user id %s. Go back to previous menu..." % choice
-        break
-
-  def display_user_task(self, prev_state):
-    state = prev_state + " / [Display User]"
-    prompt = "\n"\
-      "%s\n"\
-      "%s\n"\
-      "Please enter user id:" % (state, '-'*len(state))
-
-    while True:
-      print prompt
-      choice = raw_input().lower()
-      u = self._app_data.get_user(choice)
-      if u:
-        print "[Info] User %s:" % u.uid
-        n = 10
-        topn_rate_actions = self._app_data.get_top_rate_actions(u.uid, n)
-        print "\n[Info] Top %s movies rated by this user:" % n
-        self.display_rate_actions(topn_rate_actions)
-
-        print "\n[Info] Movies recommended to this user:"
-        self.display_items(u.rec)
-
-        self.wait_for_ack()
-        print "\n[Info] Go back to previous menu..."
-        break
-      else:
-        print "[Error] invalid user id %s. Go back to previous menu..." % choice
-        break
-  
-  def display_items(self, iids, all_info=False):
-    """print item info for each iid in the list
-    """
-    if iids:
-      for iid in iids:
-        item = self._app_data.get_item(iid)
-        if item:
-          if all_info:
-            print "[Info] %s" % item
-          else:
-            print "[Info] %s" % item.name
-        else:
-          print "[Error] Invalid item id %s" % iid
-    else:
-      print "[Info] Empty."
-
-  def display_rate_actions(self, actions):
-    """print iid and rating
-    """
-    if actions:
-      for a in actions:
-        item = self._app_data.get_item(a.iid)
-        if item:
-          print "[Info] %s, rating = %s" % (item.name, a.rating)
-        else:
-          print "[Error] Invalid item id %s" % a.iid
-    else:
-      print "[Info] Empty."
-
-  def wait_for_ack(self):
-
-    prompt = "\nPress enter to continue..."
-    print prompt
-    choice = raw_input().lower()
-
-
-if __name__ == '__main__':
-
-  print "\nWelcome To PredictionIO Python-SDK Demo App!"
-  print "============================================\n"
-  
-  my_app = App()
-  my_app.run()


[18/24] incubator-predictionio-sdk-python git commit: Update __init__.py (Updated Deprecation Error Message)

Posted by sh...@apache.org.
Update __init__.py (Updated Deprecation Error Message)

Closes #15


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/55109536
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/55109536
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/55109536

Branch: refs/heads/master
Commit: 55109536075352a555ab7f56f7ba4b8e0ea539af
Parents: 88a11a8
Author: thomas-idmt <th...@users.noreply.github.com>
Authored: Sun Sep 10 23:19:12 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Sun Sep 10 23:19:12 2017 +0900

----------------------------------------------------------------------
 predictionio/__init__.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/55109536/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index c067689..3ef8d96 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -183,8 +183,8 @@ class EventClient(BaseClient):
 
     if len(access_key) <= 8:
       raise DeprecationWarning(
-          "It seems like you are specifying an app_id. It is deprecated in "
-          "Prediction.IO 0.8.2. Please use access_key instead. Or, "
+          "The entered access key is very short, it seems like you are specifying an app_id."
+          "This is deprecated in Prediction.IO 0.8.2. Please use (a longer) access_key instead. Or, "
           "you may use an earlier version of this sdk.")
 
     self.access_key = access_key


[08/24] incubator-predictionio-sdk-python git commit: Merge pull request #14 from vietanh85/develop

Posted by sh...@apache.org.
Merge pull request #14 from vietanh85/develop

Get events from Event Server.

Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/849c2d54
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/849c2d54
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/849c2d54

Branch: refs/heads/master
Commit: 849c2d54099b3274a7485d86ea98a652175613c3
Parents: c8dda1a 6c95d7f
Author: EmergentOrder <le...@gmail.com>
Authored: Wed Oct 28 11:29:38 2015 -0300
Committer: EmergentOrder <le...@gmail.com>
Committed: Wed Oct 28 11:29:38 2015 -0300

----------------------------------------------------------------------
 predictionio/__init__.py | 52 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
----------------------------------------------------------------------



[05/24] incubator-predictionio-sdk-python git commit: added missing import for InvalidArgumentError. Fix NameError when url provided to client is malformed.

Posted by sh...@apache.org.
added missing import for InvalidArgumentError. Fix NameError when url provided to client is malformed.


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/a6f841f6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/a6f841f6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/a6f841f6

Branch: refs/heads/master
Commit: a6f841f6c3135189dd647845414c0b49a8c1d00e
Parents: c8dda1a
Author: Almog Cohen <al...@gmail.com>
Authored: Wed Jun 17 13:41:33 2015 +0300
Committer: Almog Cohen <al...@gmail.com>
Committed: Wed Jun 17 13:41:33 2015 +0300

----------------------------------------------------------------------
 predictionio/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/a6f841f6/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 8f40a4f..02bd101 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -8,7 +8,7 @@ Python applications with PredictionIO REST API services.
 __version__ = "0.9.2"
 
 # import deprecated libraries.
-from predictionio.obsolete import Client
+from predictionio.obsolete import Client, InvalidArgumentError
 
 # import packages
 import re


[22/24] incubator-predictionio-sdk-python git commit: Prepare 0.9.9rc1

Posted by sh...@apache.org.
Prepare 0.9.9rc1


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/72a50929
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/72a50929
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/72a50929

Branch: refs/heads/master
Commit: 72a509296d355328bdfaa7a4125ff65496d0d937
Parents: a71d14e
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Thu Oct 19 17:50:19 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Thu Oct 19 17:50:19 2017 +0900

----------------------------------------------------------------------
 setup.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/72a50929/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index f34003f..fd735a0 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@ __license__ = "Apache License, Version 2.0"
 
 setup(
     name='PredictionIO',
-    version="0.9.8",
+    version="0.9.9",
     author=__author__,
     author_email=__email__,
     packages=['predictionio'],


[10/24] incubator-predictionio-sdk-python git commit: Merge PR #11, prep 0.9.6 . Clobbered the PR's predictionio/__init__.py conflicting changes, fixed the rest

Posted by sh...@apache.org.
Merge PR #11, prep 0.9.6 . Clobbered the PR's predictionio/__init__.py conflicting changes, fixed the rest


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/7b6e210d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/7b6e210d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/7b6e210d

Branch: refs/heads/master
Commit: 7b6e210d7ad8147358685f513fab98f58a79039b
Parents: b85d044 bc67832
Author: EmergentOrder <le...@gmail.com>
Authored: Tue Nov 3 13:04:18 2015 -0400
Committer: EmergentOrder <le...@gmail.com>
Committed: Tue Nov 3 13:04:18 2015 -0400

----------------------------------------------------------------------
 .gitignore                                      |    4 +
 docs/source/conf.py                             |  110 +-
 examples/demo-movielens/appdata.py              |  316 ++---
 examples/demo-movielens/batch_import.py         |  246 ++--
 examples/event_sample.py                        |   48 +-
 examples/import_yahoo.py                        |  261 ++--
 examples/itemrank_quick_query.py                |   18 +-
 examples/itemrank_quick_start.py                |   69 +-
 examples/obsolete/__init__.py                   |    0
 examples/obsolete/itemrec/__init__.py           |    0
 examples/obsolete/itemrec/movies/.gitignore     |    3 -
 examples/obsolete/itemrec/movies/README.md      |   15 -
 examples/obsolete/itemrec/movies/__init__.py    |    0
 examples/obsolete/itemrec/movies/app_config.py  |    2 -
 examples/obsolete/itemrec/movies/appdata.py     |  148 ---
 .../obsolete/itemrec/movies/batch_import.py     |   65 -
 .../obsolete/itemrec/movies/movie_rec_app.py    |  152 ---
 predictionio/__init__.py                        |   40 +-
 predictionio/connection.py                      |  537 ++++----
 predictionio/obsolete.py                        | 1205 ------------------
 setup.py                                        |   32 +-
 tests-obsolete/conversion_test.py               |   16 +
 tests-obsolete/import_testdata.py               |   46 +
 tests-obsolete/import_testdata_id_mismatch.py   |   46 +
 tests-obsolete/import_testdata_special_char.py  |   46 +
 tests-obsolete/predictionio_itemrec_test.py     |  336 +++++
 .../predictionio_itemrec_test_special_char.py   |  366 ++++++
 tests-obsolete/predictionio_itemsim_test.py     |  200 +++
 tests-obsolete/predictionio_test.py             |  257 ++++
 tests/.keep                                     |    0
 tests/conversion_test.py                        |   23 -
 tests/import_testdata.py                        |   52 -
 tests/import_testdata_id_mismatch.py            |   52 -
 tests/import_testdata_special_char.py           |   52 -
 tests/predictionio_itemrec_test.py              |  300 -----
 tests/predictionio_itemrec_test_special_char.py |  291 -----
 tests/predictionio_itemsim_test.py              |  160 ---
 tests/predictionio_test.py                      |  246 ----
 tox.ini                                         |    9 +
 39 files changed, 2171 insertions(+), 3598 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/7b6e210d/docs/source/conf.py
----------------------------------------------------------------------
diff --cc docs/source/conf.py
index 0d87655,539cf04..d52d83e
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@@ -52,9 -52,9 +52,9 @@@ copyright = u'2014, TappingStone, Inc.
  # built documents.
  #
  # The short X.Y version.
 -version = '0.8'
 +version = '0.9'
  # The full version, including alpha/beta/rc tags.
- release = '0.9.2'
 -release = '0.8.3'
++release = '0.9.6'
  
  # The language for content autogenerated by Sphinx. Refer to documentation
  # for a list of supported languages.

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/7b6e210d/predictionio/__init__.py
----------------------------------------------------------------------
diff --cc predictionio/__init__.py
index 290c31e,f4eb87a..e5e5387
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@@ -1,14 -1,10 +1,13 @@@
--"""PredictoinIO Python SDK
--
--The PredictoinIO Python SDK provides easy-to-use functions for integrating
++"""PredictionIO Python SDK
++The PredictionIO Python SDK provides easy-to-use functions for integrating
  Python applications with PredictionIO REST API services.
  """
  
 -__version__ = "0.8.5"
 +
- __version__ = "0.9.2"
++__version__ = "0.9.6"
 +
 +# import deprecated libraries.
 +from predictionio.obsolete import Client, InvalidArgumentError
  
  # import packages
  import re
@@@ -62,530 -51,405 +61,497 @@@ def event_time_validation(t)
  
  
  class BaseClient(object):
 -    def __init__(self, url, threads=1, qsize=0, timeout=5):
 -        """Constructor of Client object.
 -
 -        """
 -        self.threads = threads
 -        self.url = url
 -        self.qsize = qsize
 -        self.timeout = timeout
 -
 -        # check connection type
 -        https_pattern = r'^https://(.*)'
 -        http_pattern = r'^http://(.*)'
 -        m = re.match(https_pattern, url)
 -        self.https = True
 -        if m is None:  # not matching https
 -            m = re.match(http_pattern, url)
 -            self.https = False
 -            if m is None:  # not matching http either
 -                raise InvalidArgumentError("url is not valid: %s" % url)  # noqa
 -        self.host = m.group(1)
 -
 -        self._uid = None  # identified uid
 -        self._connection = Connection(host=self.host, threads=self.threads,
 -                                      qsize=self.qsize, https=self.https,
 -                                      timeout=self.timeout)
 -
 -    def close(self):
 -        """Close this client and the connection.
 -
 -        Call this method when you want to completely terminate the connection
 -        with PredictionIO.
 -        It will wait for all pending requests to finish.
 -        """
 -        self._connection.close()
 -
 -    def pending_requests(self):
 -        """Return the number of pending requests.
 -
 -        :returns:
 -          The number of pending requests of this client.
 -        """
 -        return self._connection.pending_requests()
 -
 -    def get_status(self):
 -        """Get the status of the PredictionIO API Server
 -
 -        :returns:
 -          status message.
 -
 -        :raises:
 -          ServerStatusError.
 -        """
 -        path = "/"
 -        request = AsyncRequest("GET", path)
 -        request.set_rfunc(self._aget_resp)
 -        self._connection.make_request(request)
 -        result = request.get_response()
 -        return result
 -
 -    def _acreate_resp(self, response):
 -        if response.error is not None:
 -            raise NotCreatedError("Exception happened: %s for request %s" %
 -                                  (response.error, response.request))
 -        elif response.status != httplib.CREATED:
 -            raise NotCreatedError("request: %s status: %s body: %s" %
 -                                  (response.request, response.status,
 -                                   response.body))
 -
 -        return response
 -
 -    def _aget_resp(self, response):
 -        if response.error is not None:
 -            raise NotFoundError("Exception happened: %s for request %s" %
 -                                (response.error, response.request))
 -        elif response.status != httplib.OK:
 -            raise NotFoundError("request: %s status: %s body: %s" %
 -                                (response.request, response.status,
 -                                 response.body))
 -
 -        return response.json_body
 -
 -    def _adelete_resp(self, response):
 -        if response.error is not None:
 -            raise NotFoundError("Exception happened: %s for request %s" %
 -                                (response.error, response.request))
 -        elif response.status != httplib.OK:
 -            raise NotFoundError("request: %s status: %s body: %s" %
 -                                (response.request, response.status,
 -                                 response.body))
 -
 -        return response.body
 +  def __init__(self, url, threads=1, qsize=0, timeout=5):
 +    """Constructor of Client object.
- 
 +    """
 +    self.threads = threads
 +    self.url = url
 +    self.qsize = qsize
 +    self.timeout = timeout
 +
 +    # check connection type
 +    https_pattern = r'^https://(.*)'
 +    http_pattern = r'^http://(.*)'
 +    m = re.match(https_pattern, url)
 +    self.https = True
 +    if m is None:  # not matching https
 +      m = re.match(http_pattern, url)
 +      self.https = False
 +      if m is None:  # not matching http either
 +        raise InvalidArgumentError("url is not valid: %s" % url)
 +    self.host = m.group(1)
 +
 +    self._uid = None  # identified uid
 +    self._connection = Connection(host=self.host, threads=self.threads,
 +                    qsize=self.qsize, https=self.https,
 +                    timeout=self.timeout)
 +
 +  def close(self):
 +    """Close this client and the connection.
- 
 +    Call this method when you want to completely terminate the connection
 +    with PredictionIO.
 +    It will wait for all pending requests to finish.
 +    """
 +    self._connection.close()
 +
 +  def pending_requests(self):
 +    """Return the number of pending requests.
- 
 +    :returns:
 +      The number of pending requests of this client.
 +    """
 +    return self._connection.pending_requests()
 +
 +  def get_status(self):
 +    """Get the status of the PredictionIO API Server
- 
 +    :returns:
 +      status message.
- 
 +    :raises:
 +      ServerStatusError.
 +    """
 +    path = "/"
 +    request = AsyncRequest("GET", path)
 +    request.set_rfunc(self._aget_resp)
 +    self._connection.make_request(request)
 +    result = request.get_response()
 +    return result
 +
 +  def _acreate_resp(self, response):
 +    if response.error is not None:
 +      raise NotCreatedError("Exception happened: %s for request %s" %
 +                    (response.error, response.request))
 +    elif response.status != httplib.CREATED:
 +      raise NotCreatedError("request: %s status: %s body: %s" %
 +                    (response.request, response.status,
 +                     response.body))
 +
 +    return response
 +
 +  def _aget_resp(self, response):
 +    if response.error is not None:
 +      raise NotFoundError("Exception happened: %s for request %s" %
 +                  (response.error, response.request))
 +    elif response.status != httplib.OK:
 +      raise NotFoundError("request: %s status: %s body: %s" %
 +                  (response.request, response.status,
 +                   response.body))
 +
 +    return response.json_body
 +
 +  def _adelete_resp(self, response):
 +    if response.error is not None:
 +      raise NotFoundError("Exception happened: %s for request %s" %
 +                  (response.error, response.request))
 +    elif response.status != httplib.OK:
 +      raise NotFoundError("request: %s status: %s body: %s" %
 +                  (response.request, response.status,
 +                   response.body))
 +
 +    return response.body
  
  
  class EventClient(BaseClient):
 -    """Client for importing data into PredictionIO Event Server.
 -
 -    Notice that app_id has been deprecated as of 0.8.2. Please use access_token
 -    instead.
 -
 -    :param access_key: the access key for your application.
 -    :param url: the url of PredictionIO Event Server.
 -    :param threads: number of threads to handle PredictionIO API requests.
 -            Must be >= 1.
 -    :param qsize: the max size of the request queue (optional).
 -        The asynchronous request becomes blocking once this size has been
 -        reached, until the queued requests are handled.
 -        Default value is 0, which means infinite queue size.
 -    :param timeout: timeout for HTTP connection attempts and requests in
 -      seconds (optional).
 -      Default value is 5.
 +  """Client for importing data into PredictionIO Event Server.
- 
 +  Notice that app_id has been deprecated as of 0.8.2. Please use access_token
 +  instead.
- 
 +  :param access_key: the access key for your application.
 +  :param url: the url of PredictionIO Event Server.
 +  :param threads: number of threads to handle PredictionIO API requests.
 +          Must be >= 1.
 +  :param qsize: the max size of the request queue (optional).
 +      The asynchronous request becomes blocking once this size has been
 +      reached, until the queued requests are handled.
 +      Default value is 0, which means infinite queue size.
 +  :param timeout: timeout for HTTP connection attempts and requests in
 +    seconds (optional).
 +    Default value is 5.
 +  :param channel: channel name (optional)
 +  """
 +
 +  def __init__(self, access_key,
 +      url="http://localhost:7070",
 +      threads=1, qsize=0, timeout=5, channel=None):
 +    assert type(access_key) is str, ("access_key must be string. "
 +        "Notice that app_id has been deprecated in Prediction.IO 0.8.2. "
 +        "Please use access_key instead.")
 +
 +    super(EventClient, self).__init__(url, threads, qsize, timeout)
 +
 +    if len(access_key) <= 8:
 +      raise DeprecationWarning(
 +          "It seems like you are specifying an app_id. It is deprecated in "
 +          "Prediction.IO 0.8.2. Please use access_key instead. Or, "
 +          "you may use an earlier version of this sdk.")
 +
 +    self.access_key = access_key
 +    self.channel = channel
 +
 +  def acreate_event(self, event, entity_type, entity_id,
 +      target_entity_type=None, target_entity_id=None, properties=None,
 +      event_time=None):
 +    """Asynchronously create an event.
- 
 +    :param event: event name. type str.
 +    :param entity_type: entity type. It is the namespace of the entityId and
 +      analogous to the table name of a relational database. The entityId must be
 +      unique within same entityType. type str.
 +    :param entity_id: entity id. *entity_type-entity_id* becomes the unique
 +      identifier of the entity. For example, you may have entityType named user,
 +      and different entity IDs, say 1 and 2. In this case, user-1 and user-2
 +      uniquely identifies entities. type str
 +    :param target_entity_type: target entity type. type str.
 +    :param target_entity_id: target entity id. type str.
 +    :param properties: a custom dict associated with an event. type dict.
 +    :param event_time: the time of the event. type datetime, must contain
 +      timezone info.
- 
 +    :returns:
 +      AsyncRequest object. You can call the get_response() method using this
 +      object to get the final resuls or status of this asynchronous request.
      """
 +    data = {
 +        "event": event,
 +        "entityType": entity_type,
 +        "entityId": entity_id,
 +        }
 +
 +    if target_entity_type is not None:
 +      data["targetEntityType"] = target_entity_type
 +
 +    if target_entity_id is not None:
 +      data["targetEntityId"] = target_entity_id
 +
 +    if properties is not None:
 +      data["properties"] = properties
  
 -    def __init__(self, access_key,
 -                 url="http://localhost:7070",
 -                 threads=1, qsize=0, timeout=5):
 -        assert type(access_key) is str, ("access_key must be string. "
 -                                         "Notice that app_id has been deprecated in Prediction.IO 0.8.2. "
 -                                         "Please use access_key instead.")
 -
 -        super(EventClient, self).__init__(url, threads, qsize, timeout)
 -
 -        if len(access_key) <= 8:
 -            raise DeprecationWarning(
 -                "It seems like you are specifying an app_id. It is deprecated in "
 -                "Prediction.IO 0.8.2. Please use access_key instead. Or, "
 -                "you may use an earlier version of this sdk.")
 -
 -        self.access_key = access_key
 -
 -    def acreate_event(self, event, entity_type, entity_id,
 -                      target_entity_type=None, target_entity_id=None, properties=None,
 -                      event_time=None):
 -        """Asynchronously create an event.
 -
 -        :param event: event name. type str.
 -        :param entity_type: entity type. It is the namespace of the entityId and
 -          analogous to the table name of a relational database. The entityId must be
 -          unique within same entityType. type str.
 -        :param entity_id: entity id. *entity_type-entity_id* becomes the unique
 -          identifier of the entity. For example, you may have entityType named user,
 -          and different entity IDs, say 1 and 2. In this case, user-1 and user-2
 -          uniquely identifies entities. type str
 -        :param target_entity_type: target entity type. type str.
 -        :param target_entity_id: target entity id. type str.
 -        :param properties: a custom dict associated with an event. type dict.
 -        :param event_time: the time of the event. type datetime, must contain
 -          timezone info.
 -
 -        :returns:
 -          AsyncRequest object. You can call the get_response() method using this
 -          object to get the final resuls or status of this asynchronous request.
 -        """
 -        data = {
 -            "event": event,
 -            "entityType": entity_type,
 -            "entityId": entity_id,
 +    et = event_time_validation(event_time)
 +    # EventServer uses milliseconds, but python datetime class uses micro. Hence
 +    # need to skip the last three digits.
 +    et_str = et.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + et.strftime("%z")
 +    data["eventTime"] = et_str
 +
 +    qparam = {
 +        "accessKey" : self.access_key
          }
  
 -        if target_entity_type is not None:
 -            data["targetEntityType"] = target_entity_type
 -
 -        if target_entity_id is not None:
 -            data["targetEntityId"] = target_entity_id
 -
 -        if properties is not None:
 -            data["properties"] = properties
 -
 -        et = event_time_validation(event_time)
 -        # EventServer uses milliseconds, but python datetime class uses micro. Hence
 -        # need to skip the last three digits.
 -        et_str = et.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + et.strftime("%z")
 -        data["eventTime"] = et_str
 -
 -        path = "/events.json?accessKey=%s" % (self.access_key, )
 -        request = AsyncRequest("POST", path, **data)
 -        request.set_rfunc(self._acreate_resp)
 -        self._connection.make_request(request)
 -        return request
 -
 -    def create_event(self, event, entity_type, entity_id,
 -                     target_entity_type=None, target_entity_id=None, properties=None,
 -                     event_time=None):
 -        """Synchronously (blocking) create an event."""
 -        return self.acreate_event(event, entity_type, entity_id,
 -                                  target_entity_type, target_entity_id, properties,
 -                                  event_time).get_response()
 -
 -    def aget_event(self, event_id):
 -        """Asynchronouly get an event from Event Server.
 -
 -        :param event_id: event id returned by the EventServer when creating the
 -          event.
 -
 -        :returns:
 -          AsyncRequest object.
 -        """
 -        enc_event_id = urllib.quote(event_id, "")  # replace special char with %xx
 -        path = "/events/%s.json" % enc_event_id
 -        request = AsyncRequest("GET", path, accessKey=self.access_key)
 -        request.set_rfunc(self._aget_resp)
 -        self._connection.make_request(request)
 -        return request
 -
 -    def get_event(self, event_id):
 -        """Synchronouly get an event from Event Server."""
 -        return self.aget_event(event_id).get_response()
 -
 -    def adelete_event(self, event_id):
 -        """Asynchronouly delete an event from Event Server.
 -
 -        :param event_id: event id returned by the EventServer when creating the
 -          event.
 -
 -        :returns:
 -          AsyncRequest object.
 -        """
 -        enc_event_id = urllib.quote(event_id, "")  # replace special char with %xx
 -        path = "/events/%s.json" % (enc_event_id, )
 -        request = AsyncRequest("DELETE", path, accessKey=self.access_key)
 -        request.set_rfunc(self._adelete_resp)
 -        self._connection.make_request(request)
 -        return request
 -
 -    def delete_event(self, event_id):
 -        """Synchronouly delete an event from Event Server."""
 -        return self.adelete_event(event_id).get_response()
 -
 -    # Below are helper functions
 -
 -    def aset_user(self, uid, properties={}, event_time=None):
 -        """Set properties of a user.
 -
 -        Wrapper of acreate_event function, setting event to "$set" and entity_type
 -        to "user".
 -        """
 -        return self.acreate_event(
 -            event="$set",
 -            entity_type="user",
 -            entity_id=uid,
 -            properties=properties,
 -            event_time=event_time,
 -        )
 +    if self.channel is not None:
 +      qparam["channel"] = self.channel
 +
 +    path = "/events.json?%s" % (urlencode(qparam), )
 +
 +    request = AsyncRequest("POST", path, **data)
 +    request.set_rfunc(self._acreate_resp)
 +    self._connection.make_request(request)
 +    return request
 +
 +  def create_event(self, event, entity_type, entity_id,
 +      target_entity_type=None, target_entity_id=None, properties=None,
 +      event_time=None):
 +    """Synchronously (blocking) create an event."""
 +    return self.acreate_event(event, entity_type, entity_id,
 +        target_entity_type, target_entity_id, properties,
 +        event_time).get_response()
 +
 +  def aget_event(self, event_id):
 +    """Asynchronouly get an event from Event Server.
- 
 +    :param event_id: event id returned by the EventServer when creating the
 +      event.
- 
 +    :returns:
 +      AsyncRequest object.
 +    """
 +    qparam = {
 +        "accessKey" : self.access_key
 +        }
 +
 +    if self.channel is not None:
 +      qparam["channel"] = self.channel
 +
 +    enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
 +    path = "/events/%s.json" % (enc_event_id, )
 +    request = AsyncRequest("GET", path, **qparam)
 +    request.set_rfunc(self._aget_resp)
 +    self._connection.make_request(request)
 +    return request
 +
 +  def get_event(self, event_id):
 +    """Synchronouly get an event from Event Server."""
 +    return self.aget_event(event_id).get_response()
 +
 +  def aget_events(self, startTime=None, untilTime=None, entityType=None, entityId=None, limit=None, reversed=False):
 +    """Asynchronouly get events from Event Server. (Getting events through the Event Server API is used for debugging and not recommended for production)
- 
 +    :param startTime: time in ISO8601 format. Return events with eventTime >= startTime.
 +    :param untilTime: time in ISO8601 format. Return events with eventTime < untilTime.
 +    :param entityId: String. The entityId. Return events for this entityId only.
 +    :param limit: Integer. The number of record events returned. Default is 20. -1 to get all.
 +    :param reversed: Boolean. Must be used with both entityType and entityId specified,
 +      returns events in reversed chronological order. Default is false.
- 
 +    :returns:
 +      AsyncRequest object.
 +    """
 +    qparam = {
 +        "accessKey" : self.access_key,
 +        "reversed": reversed
 +      }
 +
 +    if startTime is not None:
 +      qparam["startTime"] = startTime
 +
 +    if untilTime is not None:
 +      qparam["untilTime"] = untilTime
 +
 +    if entityType is not None:
 +      qparam["entityType"] = entityType
 +
 +    if entityId is not None:
 +      qparam["entityId"] = entityId
 +
 +    if limit is not None:
 +      qparam["limit"] = limit
 +
 +    if self.channel is not None:
 +      qparam["channel"] = self.channel
 +    path = "/events.json"
 +    request = AsyncRequest("GET", path, **qparam)
 +    request.set_rfunc(self._aget_resp)
 +    self._connection.make_request(request)
 +    return request
 +
 +  def get_events(self, startTime=None, untilTime=None, entityType=None, entityId=None, limit=None, reversed=False):
 +    """Synchronouly get event from Event Server. (Getting events through the Event Server API is used for debugging and not recommended for production)"""
 +    return self.aget_events(
 +      startTime=startTime,
 +      untilTime=untilTime,
 +      entityType=entityType,
 +      entityId=entityId,
 +      limit=limit,
 +      reversed=reversed
 +    ).get_response()
 +
 +  def adelete_event(self, event_id):
 +    """Asynchronouly delete an event from Event Server.
- 
 +    :param event_id: event id returned by the EventServer when creating the
 +      event.
- 
 +    :returns:
 +      AsyncRequest object.
 +    """
 +    qparam = {
 +        "accessKey" : self.access_key
 +        }
 +
 +    if self.channel is not None:
 +      qparam["channel"] = self.channel
 +
 +    enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
 +    path = "/events/%s.json" % (enc_event_id, )
 +    request = AsyncRequest("DELETE", path, **qparam)
 +    request.set_rfunc(self._adelete_resp)
 +    self._connection.make_request(request)
 +    return request
 +
 +  def delete_event(self, event_id):
 +    """Synchronouly delete an event from Event Server."""
 +    return self.adelete_event(event_id).get_response()
  
 -    def set_user(self, uid, properties={}, event_time=None):
 -        """Set properties of a user"""
 -        return self.aset_user(uid, properties, event_time).get_response()
 -
 -    def aunset_user(self, uid, properties, event_time=None):
 -        """Unset properties of an user.
 -
 -        Wrapper of acreate_event function, setting event to "$unset" and entity_type
 -        to "user".
 -        """
 -        # check properties={}, it cannot be empty
 -        return self.acreate_event(
 -            event="$unset",
 -            entity_type="user",
 -            entity_id=uid,
 -            properties=properties,
 -            event_time=event_time,
 +  ## Below are helper functions
 +
 +  def aset_user(self, uid, properties={}, event_time=None):
 +    """Set properties of a user.
- 
 +    Wrapper of acreate_event function, setting event to "$set" and entity_type
 +    to "user".
 +    """
 +    return self.acreate_event(
 +      event="$set",
 +      entity_type="user",
 +      entity_id=uid,
 +      properties=properties,
 +      event_time=event_time,
 +    )
 +
 +  def set_user(self, uid, properties={}, event_time=None):
 +    """Set properties of a user"""
 +    return self.aset_user(uid, properties, event_time).get_response()
 +
 +  def aunset_user(self, uid, properties, event_time=None):
 +    """Unset properties of an user.
- 
 +    Wrapper of acreate_event function, setting event to "$unset" and entity_type
 +    to "user".
 +    """
 +    # check properties={}, it cannot be empty
 +    return self.acreate_event(
 +        event="$unset",
 +        entity_type="user",
 +        entity_id=uid,
 +        properties=properties,
 +        event_time=event_time,
          )
  
 -    def unset_user(self, uid, properties, event_time=None):
 -        """Set properties of a user"""
 -        return self.aunset_user(uid, properties, event_time).get_response()
 -
 -    def adelete_user(self, uid, event_time=None):
 -        """Delete a user.
 -
 -        Wrapper of acreate_event function, setting event to "$delete" and entity_type
 -        to "user".
 -        """
 -        return self.acreate_event(
 -            event="$delete",
 -            entity_type="user",
 -            entity_id=uid,
 -            event_time=event_time)
 -
 -    def delete_user(self, uid, event_time=None):
 -        """Delete a user."""
 -        return self.adelete_user(uid, event_time).get_response()
 -
 -    def aset_item(self, iid, properties={}, event_time=None):
 -        """Set properties of an item.
 -
 -        Wrapper of acreate_event function, setting event to "$set" and entity_type
 -        to "item".
 -        """
 -        return self.acreate_event(
 -            event="$set",
 -            entity_type="item",
 -            entity_id=iid,
 -            properties=properties,
 -            event_time=event_time)
 -
 -    def set_item(self, iid, properties={}, event_time=None):
 -        """Set properties of an item."""
 -        return self.aset_item(iid, properties, event_time).get_response()
 -
 -    def aunset_item(self, iid, properties={}, event_time=None):
 -        """Unset properties of an item.
 -
 -        Wrapper of acreate_event function, setting event to "$unset" and entity_type
 -        to "item".
 -        """
 -        return self.acreate_event(
 -            event="$unset",
 -            entity_type="item",
 -            entity_id=iid,
 -            properties=properties,
 -            event_time=event_time)
 -
 -    def unset_item(self, iid, properties={}, event_time=None):
 -        """Unset properties of an item."""
 -        return self.aunset_item(iid, properties, event_time).get_response()
 -
 -    def adelete_item(self, iid, event_time=None):
 -        """Delete an item.
 -
 -        Wrapper of acreate_event function, setting event to "$delete" and entity_type
 -        to "item".
 -        """
 -        return self.acreate_event(
 -            event="$delete",
 -            entity_type="item",
 -            entity_id=iid,
 -            event_time=event_time)
 -
 -    def delete_item(self, iid, event_time=None):
 -        """Delete an item."""
 -        return self.adelete_item(iid, event_time).get_response()
 -
 -    def arecord_user_action_on_item(self, action, uid, iid, properties={},
 -                                    event_time=None):
 -        """Create a user-to-item action.
 -
 -        Wrapper of acreate_event function, setting entity_type to "user" and
 -        target_entity_type to "item".
 -        """
 -        return self.acreate_event(
 -            event=action,
 -            entity_type="user",
 -            entity_id=uid,
 -            target_entity_type="item",
 -            target_entity_id=iid,
 -            properties=properties,
 -            event_time=event_time)
 -
 -    def record_user_action_on_item(self, action, uid, iid, properties={},
 -                                   event_time=None):
 -        """Create a user-to-item action."""
 -        return self.arecord_user_action_on_item(
 -            action, uid, iid, properties, event_time).get_response()
 +  def unset_user(self, uid, properties, event_time=None):
 +    """Set properties of a user"""
 +    return self.aunset_user(uid, properties, event_time).get_response()
  
 +  def adelete_user(self, uid, event_time=None):
 +    """Delete a user.
- 
 +    Wrapper of acreate_event function, setting event to "$delete" and entity_type
 +    to "user".
 +    """
 +    return self.acreate_event(
 +        event="$delete",
 +        entity_type="user",
 +        entity_id=uid,
 +        event_time=event_time)
 +
 +  def delete_user(self, uid, event_time=None):
 +    """Delete a user."""
 +    return self.adelete_user(uid, event_time).get_response()
 +
 +  def aset_item(self, iid, properties={}, event_time=None):
 +    """Set properties of an item.
- 
 +    Wrapper of acreate_event function, setting event to "$set" and entity_type
 +    to "item".
 +    """
 +    return self.acreate_event(
 +        event="$set",
 +        entity_type="item",
 +        entity_id=iid,
 +        properties=properties,
 +        event_time=event_time)
 +
 +  def set_item(self, iid, properties={}, event_time=None):
 +    """Set properties of an item."""
 +    return self.aset_item(iid, properties, event_time).get_response()
 +
 +  def aunset_item(self, iid, properties={}, event_time=None):
 +    """Unset properties of an item.
- 
 +    Wrapper of acreate_event function, setting event to "$unset" and entity_type
 +    to "item".
 +    """
 +    return self.acreate_event(
 +        event="$unset",
 +        entity_type="item",
 +        entity_id=iid,
 +        properties=properties,
 +        event_time=event_time)
 +
 +  def unset_item(self, iid, properties={}, event_time=None):
 +    """Unset properties of an item."""
 +    return self.aunset_item(iid, properties, event_time).get_response()
 +
 +  def adelete_item(self, iid, event_time=None):
 +    """Delete an item.
- 
 +    Wrapper of acreate_event function, setting event to "$delete" and entity_type
 +    to "item".
 +    """
 +    return self.acreate_event(
 +        event="$delete",
 +        entity_type="item",
 +        entity_id=iid,
 +        event_time=event_time)
 +
 +  def delete_item(self, iid, event_time=None):
 +    """Delete an item."""
 +    return self.adelete_item(iid, event_time).get_response()
 +
 +  def arecord_user_action_on_item(self, action, uid, iid, properties={},
 +      event_time=None):
 +    """Create a user-to-item action.
- 
 +    Wrapper of acreate_event function, setting entity_type to "user" and
 +    target_entity_type to "item".
 +    """
 +    return self.acreate_event(
 +        event=action,
 +        entity_type="user",
 +        entity_id=uid,
 +        target_entity_type="item",
 +        target_entity_id=iid,
 +        properties=properties,
 +        event_time=event_time)
 +
 +  def record_user_action_on_item(self, action, uid, iid, properties={},
 +      event_time=None):
 +    """Create a user-to-item action."""
 +    return self.arecord_user_action_on_item(
 +      action, uid, iid, properties, event_time).get_response()
  
 -class EngineClient(BaseClient):
 -    """Client for extracting prediction results from an PredictionIO Engine
 -    Instance.
 -
 -    :param url: the url of the PredictionIO Engine Instance.
 -    :param threads: number of threads to handle PredictionIO API requests.
 -            Must be >= 1.
 -    :param qsize: the max size of the request queue (optional).
 -        The asynchronous request becomes blocking once this size has been
 -        reached, until the queued requests are handled.
 -        Default value is 0, which means infinite queue size.
 -    :param timeout: timeout for HTTP connection attempts and requests in
 -      seconds (optional).
 -      Default value is 5.
  
 +class EngineClient(BaseClient):
 +  """Client for extracting prediction results from an PredictionIO Engine
 +  Instance.
- 
 +  :param url: the url of the PredictionIO Engine Instance.
 +  :param threads: number of threads to handle PredictionIO API requests.
 +          Must be >= 1.
 +  :param qsize: the max size of the request queue (optional).
 +      The asynchronous request becomes blocking once this size has been
 +      reached, until the queued requests are handled.
 +      Default value is 0, which means infinite queue size.
 +  :param timeout: timeout for HTTP connection attempts and requests in
 +    seconds (optional).
 +    Default value is 5.
- 
 +  """
 +  def __init__(self, url="http://localhost:8000", threads=1,
 +      qsize=0, timeout=5):
 +    super(EngineClient, self).__init__(url, threads, qsize, timeout)
 +
 +  def asend_query(self, data):
 +    """Asynchronously send a request to the engine instance with data as the
 +    query.
- 
 +    :param data: the query: It is coverted to an json object using json.dumps
 +      method. type dict.
- 
 +    :returns:
 +      AsyncRequest object. You can call the get_response() method using this
 +      object to get the final resuls or status of this asynchronous request.
      """
 +    path = "/queries.json"
 +    request = AsyncRequest("POST", path, **data)
 +    request.set_rfunc(self._aget_resp)
 +    self._connection.make_request(request)
 +    return request
 +
 +  def send_query(self, data):
 +    """Synchronously send a request.
- 
 +    :param data: the query: It is coverted to an json object using json.dumps
 +      method. type dict.
- 
 +    :returns: the prediction.
 +    """
 +    return self.asend_query(data).get_response()
 +
 +class FileExporter(object):
 +  """File exporter to write events to JSON file for batch import
- 
 +  :param file_name: the destination file name
 +  """
 +  def __init__(self, file_name):
 +    """Constructor of Exporter.
- 
 +    """
 +    self._file = open(file_name, 'w')
  
 -    def __init__(self, url="http://localhost:8000", threads=1,
 -                 qsize=0, timeout=5):
 -        super(EngineClient, self).__init__(url, threads, qsize, timeout)
 +  def create_event(self, event, entity_type, entity_id,
 +      target_entity_type=None, target_entity_id=None, properties=None,
 +      event_time=None):
 +    """Create an event and write to the file.
- 
 +    (please refer to EventClient's create_event())
- 
 +    """
 +    data = {
 +        "event": event,
 +        "entityType": entity_type,
 +        "entityId": entity_id,
 +        }
  
 -    def asend_query(self, data):
 -        """Asynchronously send a request to the engine instance with data as the
 -        query.
 +    if target_entity_type is not None:
 +      data["targetEntityType"] = target_entity_type
  
 -        :param data: the query: It is coverted to an json object using json.dumps
 -          method. type dict.
 +    if target_entity_id is not None:
 +      data["targetEntityId"] = target_entity_id
  
 -        :returns:
 -          AsyncRequest object. You can call the get_response() method using this
 -          object to get the final resuls or status of this asynchronous request.
 -        """
 -        path = "/queries.json"
 -        request = AsyncRequest("POST", path, **data)
 -        request.set_rfunc(self._aget_resp)
 -        self._connection.make_request(request)
 -        return request
 +    if properties is not None:
 +      data["properties"] = properties
  
 -    def send_query(self, data):
 -        """Synchronously send a request.
 +    et = event_time_validation(event_time)
 +    # EventServer uses milliseconds, but python datetime class uses micro. Hence
 +    # need to skip the last three digits.
 +    et_str = et.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + et.strftime("%z")
 +    data["eventTime"] = et_str
  
 -        :param data: the query: It is coverted to an json object using json.dumps
 -          method. type dict.
 +    j = json.dumps(data)
 +    self._file.write(j+"\n")
  
 -        :returns: the prediction.
 -        """
 -        return self.asend_query(data).get_response()
 +  def close(self):
 +    """Close the FileExporter
- 
 +    Call this method when you finish writing all events to JSON file
 +    """
 +    self._file.close()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/7b6e210d/predictionio/connection.py
----------------------------------------------------------------------
diff --cc predictionio/connection.py
index 04fe7b5,8c231f4..8205bb2
--- a/predictionio/connection.py
+++ b/predictionio/connection.py
@@@ -68,192 -67,190 +67,233 @@@ class ProgramError(PredictionIOAPIError
  
  
  class AsyncRequest(object):
+     """AsyncRequest object
  
-   """AsyncRequest object
+     """
  
-   """
+     def __init__(self, method, path, **params):
+         self.method = method  # "GET" "POST" etc
+         # the sub path eg. POST /v1/users.json  GET /v1/users/1.json
+         self.path = path
+         # dictionary format eg. {"appkey" : 123, "id" : 3}
+         self.params = params
+         # use queue to implement response, store AsyncResponse object
+         self.response_q = Queue.Queue(1)
+         self.qpath = "%s?%s" % (self.path, urlencode(self.params))
+         self._response = None
+         # response function to be called to handle the response
+         self.rfunc = None
  
-   def __init__(self, method, path, **params):
-     self.method = method  # "GET" "POST" etc
-     # the sub path eg. POST /v1/users.json  GET /v1/users/1.json
-     self.path = path
-     # dictionary format eg. {"appkey" : 123, "id" : 3}
-     self.params = params
-     # use queue to implement response, store AsyncResponse object
-     self.response_q = Queue.Queue(1)
-     self.qpath = "%s?%s" % (self.path, urlencode(self.params))
-     self._response = None
-     # response function to be called to handle the response
-     self.rfunc = None
+     def __str__(self):
+         return "%s %s %s %s" % (self.method, self.path, self.params,
+                                 self.qpath)
  
-   def __str__(self):
-     return "%s %s %s %s" % (self.method, self.path, self.params,
-                 self.qpath)
+     def set_rfunc(self, func):
+         self.rfunc = func
  
-   def set_rfunc(self, func):
-     self.rfunc = func
+     def set_response(self, response):
+         """ store the response
  
-   def set_response(self, response):
-     """ store the response
+         NOTE: Must be only called once
+         """
+         self.response_q.put(response)
+ 
+     def get_response(self):
+         """Get the response. Blocking.
+ 
+         :returns: self.rfunc's return type.
+         """
+         if self._response is None:
+             tmp_response = self.response_q.get(True)  # NOTE: blocking
+             if self.rfunc is None:
+                 self._response = tmp_response
+             else:
+                 self._response = self.rfunc(tmp_response)
+ 
+         return self._response
  
-     NOTE: Must be only called once
-     """
-     self.response_q.put(response)
  
-   def get_response(self):
-     """Get the response. Blocking.
+ class AsyncResponse(object):
+     """Store the response of asynchronous request
  
-     :returns: self.rfunc's return type.
+     When get the response, user should check if error is None (which means no
+     Exception happens).
+     If error is None, then should check if the status is expected.
      """
-     if self._response is None:
-       tmp_response = self.response_q.get(True)  # NOTE: blocking
-       if self.rfunc is None:
-         self._response = tmp_response
-       else:
-         self._response = self.rfunc(tmp_response)
  
-     return self._response
+     def __init__(self):
+         #: exception object if any happens
+         self.error = None
+ 
+         self.version = None
+         self.status = None
+         self.reason = None
+         #: Response header. str
+         self.headers = None
+         #: Response body. str
+         self.body = None
+         #: Jsonified response body. Remains None if conversion is unsuccessful.
+         self.json_body = None
+         #: Point back to the AsyncRequest object
+         self.request = None
+ 
+     def __str__(self):
+         return "e:%s v:%s s:%s r:%s h:%s b:%s" % (self.error, self.version,
+                                                   self.status, self.reason,
+                                                   self.headers, self.body)
+ 
+     def set_resp(self, version, status, reason, headers, body):
+         self.version = version
+         self.status = status
+         self.reason = reason
+         self.headers = headers
+         self.body = body
+         # Try to extract the json.
+         try:
+             self.json_body = json.loads(body)
+         except ValueError as ex:  # noqa
+             self.json_body = None
  
+     def set_error(self, error):
+         self.error = error
  
 -    def set_request(self, request):
 -        self.request = request
 -
 +class AsyncResponse(object):
 +  """Store the response of asynchronous request
 +
 +  When get the response, user should check if error is None (which means no
 +  Exception happens).
 +  If error is None, then should check if the status is expected.
 +  """
 +
 +  def __init__(self):
 +    #: exception object if any happens
 +    self.error = None
 +
 +    self.version = None
 +    self.status = None
 +    self.reason = None
 +    #: Response header. str
 +    self.headers = None
 +    #: Response body. str
 +    self.body = None
 +    #: Jsonified response body. Remains None if conversion is unsuccessful.
 +    self.json_body = None
 +    #: Point back to the AsyncRequest object
 +    self.request = None  
 +
 +  def __str__(self):
 +    return "e:%s v:%s s:%s r:%s h:%s b:%s" % (self.error, self.version,
 +                          self.status, self.reason,
 +                          self.headers, self.body)
 +
 +  def set_resp(self, version, status, reason, headers, body):
 +    self.version = version
 +    self.status = status
 +    self.reason = reason
 +    self.headers = headers
 +    self.body = body
 +    # Try to extract the json.
 +    try:
 +      self.json_body = json.loads(body.decode('utf8'))
 +    except ValueError as ex:
 +      self.json_body = None
 +
 +  def set_error(self, error):
 +    self.error = error
 +
 +  def set_request(self, request):
 +    self.request = request
  
- 
  class PredictionIOHttpConnection(object):
+     def __init__(self, host, https=True, timeout=5):
+         if https:  # https connection
+             self._connection = httplib.HTTPSConnection(host, timeout=timeout)
+         else:
+             self._connection = httplib.HTTPConnection(host, timeout=timeout)
  
-   def __init__(self, host, https=True, timeout=5):
-     if https:  # https connection
-       self._connection = httplib.HTTPSConnection(host, timeout=timeout)
-     else:
-       self._connection = httplib.HTTPConnection(host, timeout=timeout)
- 
-   def connect(self):
-     self._connection.connect()
+     def connect(self):
+         self._connection.connect()
  
-   def close(self):
-     self._connection.close()
+     def close(self):
+         self._connection.close()
  
-   def request(self, method, url, body={}, headers={}):
-     """
-     http request wrapper function, with retry capability in case of error.
-     catch error exception and store it in AsyncResponse object
-     return AsyncResponse object
+     def request(self, method, url, body={}, headers={}):
+         """
+         http request wrapper function, with retry capability in case of error.
+         catch error exception and store it in AsyncResponse object
+         return AsyncResponse object
  
-     Args:
-       method: http method, type str
-       url: url path, type str
-       body: http request body content, type dict
-       header: http request header , type dict
-     """
+         Args:
+           method: http method, type str
+           url: url path, type str
+           body: http request body content, type dict
+           header: http request header , type dict
+         """
  
-     response = AsyncResponse()
+         response = AsyncResponse()
  
-     try:
-       # number of retry in case of error (minimum 0 means no retry)
-       retry_limit = MAX_RETRY
-       mod_headers = dict(headers)  # copy the headers
-       mod_headers["Connection"] = "keep-alive"
-       enc_body = None
-       if body:  # if body is not empty
-         #enc_body = urlencode(body)
-         #mod_headers[
-         #  "Content-type"] = "application/x-www-form-urlencoded"
-         enc_body = json.dumps(body)
-         mod_headers[
-           "Content-type"] = "application/json"
-         #mod_headers["Accept"] = "text/plain"
-     except Exception as e:
-       response.set_error(e)
-       return response
- 
-     if DEBUG_LOG:
-       logger.debug("Request m:%s u:%s h:%s b:%s", method, url,
-              mod_headers, enc_body)
-     # retry loop
-     for i in xrange(retry_limit + 1):
-       try:
-         if i != 0:
-           if DEBUG_LOG:
-             logger.debug("retry request %s times" % i)
-         if self._connection.sock is None:
-           self._connection.connect()
-         self._connection.request(method, url, enc_body, mod_headers)
-       except Exception as e:
-         self._connection.close()
-         if i == retry_limit:
-           # new copy of e created everytime??
-           response.set_error(e)
-       else:  # NOTE: this is try's else clause
-         # connect() and request() OK
          try:
-           resp = self._connection.getresponse()
+             # number of retry in case of error (minimum 0 means no retry)
+             retry_limit = MAX_RETRY
+             mod_headers = dict(headers)  # copy the headers
+             mod_headers["Connection"] = "keep-alive"
+             enc_body = None
+             if body:  # if body is not empty
+                 # enc_body = urlencode(body)
+                 # mod_headers[
+                 # "Content-type"] = "application/x-www-form-urlencoded"
+                 enc_body = json.dumps(body)
+                 mod_headers[
+                     "Content-type"] = "application/json"
+                 # mod_headers["Accept"] = "text/plain"
          except Exception as e:
-           self._connection.close()
-           if i == retry_limit:
              response.set_error(e)
-         else:  # NOTE: this is try's else clause
-           # getresponse() OK
-           resp_version = resp.version  # int
-           resp_status = resp.status  # int
-           resp_reason = resp.reason  # str
-           # resp.getheaders() returns list of tuples
-           # converted to dict format
-           resp_headers = dict(resp.getheaders())
-           # NOTE: have to read the response before sending out next
-           # http request
-           resp_body = resp.read()  # str
-           response.set_resp(version=resp_version, status=resp_status,
-                     reason=resp_reason, headers=resp_headers,
-                     body=resp_body)
-           break  # exit retry loop
-     # end of retry loop
-     if DEBUG_LOG:
-       logger.debug("Response %s", response)
-     return response  # AsyncResponse object
+             return response
+ 
+         if DEBUG_LOG:
+             logger.debug("Request m:%s u:%s h:%s b:%s", method, url,
+                          mod_headers, enc_body)
+         # retry loop
+         for i in xrange(retry_limit + 1):
+             try:
+                 if i != 0:
+                     if DEBUG_LOG:
+                         logger.debug("retry request %s times" % i)
+                 if self._connection.sock is None:
+                     self._connection.connect()
+                 self._connection.request(method, url, enc_body, mod_headers)
+             except Exception as e:
+                 self._connection.close()
+                 if i == retry_limit:
+                     # new copy of e created everytime??
+                     response.set_error(e)
+             else:  # NOTE: this is try's else clause
+                 # connect() and request() OK
+                 try:
+                     resp = self._connection.getresponse()
+                 except Exception as e:
+                     self._connection.close()
+                     if i == retry_limit:
+                         response.set_error(e)
+                 else:  # NOTE: this is try's else clause
+                     # getresponse() OK
+                     resp_version = resp.version  # int
+                     resp_status = resp.status  # int
+                     resp_reason = resp.reason  # str
+                     # resp.getheaders() returns list of tuples
+                     # converted to dict format
+                     resp_headers = dict(resp.getheaders())
+                     # NOTE: have to read the response before sending out next
+                     # http request
+                     resp_body = resp.read()  # str
+                     response.set_resp(version=resp_version, status=resp_status,
+                                       reason=resp_reason, headers=resp_headers,
+                                       body=resp_body)
+                     break  # exit retry loop
+         # end of retry loop
+         if DEBUG_LOG:
+             logger.debug("Response %s", response)
+         return response  # AsyncResponse object
  
  
  def connection_worker(host, request_queue, https=True, timeout=5, loop=True):

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/7b6e210d/setup.py
----------------------------------------------------------------------
diff --cc setup.py
index 15163d1,f0e1038..67b12e3
--- a/setup.py
+++ b/setup.py
@@@ -10,7 -10,7 +10,7 @@@ __license__ = "Apache License, Version 
  
  setup(
      name='PredictionIO',
-     version="0.9.2",
 -    version="0.8.5",
++    version="0.9.6",
      author=__author__,
      author_email=__email__,
      packages=['predictionio'],


[20/24] incubator-predictionio-sdk-python git commit: ignore .DS_Store

Posted by sh...@apache.org.
ignore .DS_Store


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/579ab327
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/579ab327
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/579ab327

Branch: refs/heads/master
Commit: 579ab327d3ef8685f7e98bd97c4320e331d4272a
Parents: 4b51a30
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Wed Sep 13 15:15:37 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Wed Sep 13 15:15:37 2017 +0900

----------------------------------------------------------------------
 .DS_Store  | Bin 6148 -> 0 bytes
 .gitignore |   1 +
 2 files changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/579ab327/.DS_Store
----------------------------------------------------------------------
diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index af48d0a..0000000
Binary files a/.DS_Store and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/579ab327/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 1822229..0c3ae58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ MANIFEST
 docs/build/
 tests_env/
 *.zip
+.DS_Store


[03/24] incubator-predictionio-sdk-python git commit: Fixed indentation Deleted obsolete examples Moved obsolete test suite to 'test-obsolete' (port as we go) Added tox test bootstrapping Ignored pycharm, test output Removed obsolete (<0.8) support PEP8/

Posted by sh...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 45a379f..f4eb87a 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -4,21 +4,17 @@ The PredictoinIO Python SDK provides easy-to-use functions for integrating
 Python applications with PredictionIO REST API services.
 """
 
-
-__version__ = "0.8.3"
-
-# import deprecated libraries.
-from predictionio.obsolete import Client
+__version__ = "0.8.5"
 
 # import packages
 import re
+
 try:
-  import httplib
+    import httplib
 except ImportError:
-  # pylint: disable=F0401
-  # http is a Python3 module, replacing httplib
-  from http import client as httplib
-import json
+    # pylint: disable=F0401
+    # http is a Python3 module, replacing httplib
+    from http import client as httplib
 import urllib
 
 from datetime import datetime
@@ -26,433 +22,434 @@ import pytz
 
 from predictionio.connection import Connection
 from predictionio.connection import AsyncRequest
-from predictionio.connection import AsyncResponse
+from predictionio.connection import AsyncResponse  # noqa
 from predictionio.connection import PredictionIOAPIError
 
 
 class NotCreatedError(PredictionIOAPIError):
-  pass
+    pass
 
 
 class NotFoundError(PredictionIOAPIError):
-  pass
+    pass
 
 
 def event_time_validation(t):
-  """ Validate event_time according to EventAPI Specification.
-  """
+    """ Validate event_time according to EventAPI Specification.
+    """
 
-  if t is None:
-    return datetime.now(pytz.utc)
+    if t is None:
+        return datetime.now(pytz.utc)
 
-  if type(t) != datetime:
-    raise AttributeError("event_time must be datetime.datetime")
+    if type(t) != datetime:
+        raise AttributeError("event_time must be datetime.datetime")
 
-  if t.tzinfo is None:
-    raise AttributeError("event_time must have tzinfo")
+    if t.tzinfo is None:
+        raise AttributeError("event_time must have tzinfo")
 
-  return t
+    return t
 
 
 class BaseClient(object):
-  def __init__(self, url, threads=1, qsize=0, timeout=5):
-    """Constructor of Client object.
+    def __init__(self, url, threads=1, qsize=0, timeout=5):
+        """Constructor of Client object.
+
+        """
+        self.threads = threads
+        self.url = url
+        self.qsize = qsize
+        self.timeout = timeout
+
+        # check connection type
+        https_pattern = r'^https://(.*)'
+        http_pattern = r'^http://(.*)'
+        m = re.match(https_pattern, url)
+        self.https = True
+        if m is None:  # not matching https
+            m = re.match(http_pattern, url)
+            self.https = False
+            if m is None:  # not matching http either
+                raise InvalidArgumentError("url is not valid: %s" % url)  # noqa
+        self.host = m.group(1)
+
+        self._uid = None  # identified uid
+        self._connection = Connection(host=self.host, threads=self.threads,
+                                      qsize=self.qsize, https=self.https,
+                                      timeout=self.timeout)
+
+    def close(self):
+        """Close this client and the connection.
+
+        Call this method when you want to completely terminate the connection
+        with PredictionIO.
+        It will wait for all pending requests to finish.
+        """
+        self._connection.close()
+
+    def pending_requests(self):
+        """Return the number of pending requests.
+
+        :returns:
+          The number of pending requests of this client.
+        """
+        return self._connection.pending_requests()
+
+    def get_status(self):
+        """Get the status of the PredictionIO API Server
+
+        :returns:
+          status message.
+
+        :raises:
+          ServerStatusError.
+        """
+        path = "/"
+        request = AsyncRequest("GET", path)
+        request.set_rfunc(self._aget_resp)
+        self._connection.make_request(request)
+        result = request.get_response()
+        return result
+
+    def _acreate_resp(self, response):
+        if response.error is not None:
+            raise NotCreatedError("Exception happened: %s for request %s" %
+                                  (response.error, response.request))
+        elif response.status != httplib.CREATED:
+            raise NotCreatedError("request: %s status: %s body: %s" %
+                                  (response.request, response.status,
+                                   response.body))
+
+        return response
+
+    def _aget_resp(self, response):
+        if response.error is not None:
+            raise NotFoundError("Exception happened: %s for request %s" %
+                                (response.error, response.request))
+        elif response.status != httplib.OK:
+            raise NotFoundError("request: %s status: %s body: %s" %
+                                (response.request, response.status,
+                                 response.body))
+
+        return response.json_body
+
+    def _adelete_resp(self, response):
+        if response.error is not None:
+            raise NotFoundError("Exception happened: %s for request %s" %
+                                (response.error, response.request))
+        elif response.status != httplib.OK:
+            raise NotFoundError("request: %s status: %s body: %s" %
+                                (response.request, response.status,
+                                 response.body))
+
+        return response.body
 
-    """
-    self.threads = threads
-    self.url = url
-    self.qsize = qsize
-    self.timeout = timeout
-
-    # check connection type
-    https_pattern = r'^https://(.*)'
-    http_pattern = r'^http://(.*)'
-    m = re.match(https_pattern, url)
-    self.https = True
-    if m is None:  # not matching https
-      m = re.match(http_pattern, url)
-      self.https = False
-      if m is None:  # not matching http either
-        raise InvalidArgumentError("url is not valid: %s" % url)
-    self.host = m.group(1)
-
-    self._uid = None  # identified uid
-    self._connection = Connection(host=self.host, threads=self.threads,
-                    qsize=self.qsize, https=self.https,
-                    timeout=self.timeout)
-
-  def close(self):
-    """Close this client and the connection.
-
-    Call this method when you want to completely terminate the connection
-    with PredictionIO.
-    It will wait for all pending requests to finish.
-    """
-    self._connection.close()
 
-  def pending_requests(self):
-    """Return the number of pending requests.
-
-    :returns:
-      The number of pending requests of this client.
+class EventClient(BaseClient):
+    """Client for importing data into PredictionIO Event Server.
+
+    Notice that app_id has been deprecated as of 0.8.2. Please use access_token
+    instead.
+
+    :param access_key: the access key for your application.
+    :param url: the url of PredictionIO Event Server.
+    :param threads: number of threads to handle PredictionIO API requests.
+            Must be >= 1.
+    :param qsize: the max size of the request queue (optional).
+        The asynchronous request becomes blocking once this size has been
+        reached, until the queued requests are handled.
+        Default value is 0, which means infinite queue size.
+    :param timeout: timeout for HTTP connection attempts and requests in
+      seconds (optional).
+      Default value is 5.
     """
-    return self._connection.pending_requests()
 
-  def get_status(self):
-    """Get the status of the PredictionIO API Server
+    def __init__(self, access_key,
+                 url="http://localhost:7070",
+                 threads=1, qsize=0, timeout=5):
+        assert type(access_key) is str, ("access_key must be string. "
+                                         "Notice that app_id has been deprecated in Prediction.IO 0.8.2. "
+                                         "Please use access_key instead.")
+
+        super(EventClient, self).__init__(url, threads, qsize, timeout)
+
+        if len(access_key) <= 8:
+            raise DeprecationWarning(
+                "It seems like you are specifying an app_id. It is deprecated in "
+                "Prediction.IO 0.8.2. Please use access_key instead. Or, "
+                "you may use an earlier version of this sdk.")
+
+        self.access_key = access_key
+
+    def acreate_event(self, event, entity_type, entity_id,
+                      target_entity_type=None, target_entity_id=None, properties=None,
+                      event_time=None):
+        """Asynchronously create an event.
+
+        :param event: event name. type str.
+        :param entity_type: entity type. It is the namespace of the entityId and
+          analogous to the table name of a relational database. The entityId must be
+          unique within same entityType. type str.
+        :param entity_id: entity id. *entity_type-entity_id* becomes the unique
+          identifier of the entity. For example, you may have entityType named user,
+          and different entity IDs, say 1 and 2. In this case, user-1 and user-2
+          uniquely identifies entities. type str
+        :param target_entity_type: target entity type. type str.
+        :param target_entity_id: target entity id. type str.
+        :param properties: a custom dict associated with an event. type dict.
+        :param event_time: the time of the event. type datetime, must contain
+          timezone info.
+
+        :returns:
+          AsyncRequest object. You can call the get_response() method using this
+          object to get the final resuls or status of this asynchronous request.
+        """
+        data = {
+            "event": event,
+            "entityType": entity_type,
+            "entityId": entity_id,
+        }
 
-    :returns:
-      status message.
+        if target_entity_type is not None:
+            data["targetEntityType"] = target_entity_type
+
+        if target_entity_id is not None:
+            data["targetEntityId"] = target_entity_id
+
+        if properties is not None:
+            data["properties"] = properties
+
+        et = event_time_validation(event_time)
+        # EventServer uses milliseconds, but python datetime class uses micro. Hence
+        # need to skip the last three digits.
+        et_str = et.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + et.strftime("%z")
+        data["eventTime"] = et_str
+
+        path = "/events.json?accessKey=%s" % (self.access_key, )
+        request = AsyncRequest("POST", path, **data)
+        request.set_rfunc(self._acreate_resp)
+        self._connection.make_request(request)
+        return request
+
+    def create_event(self, event, entity_type, entity_id,
+                     target_entity_type=None, target_entity_id=None, properties=None,
+                     event_time=None):
+        """Synchronously (blocking) create an event."""
+        return self.acreate_event(event, entity_type, entity_id,
+                                  target_entity_type, target_entity_id, properties,
+                                  event_time).get_response()
+
+    def aget_event(self, event_id):
+        """Asynchronouly get an event from Event Server.
+
+        :param event_id: event id returned by the EventServer when creating the
+          event.
+
+        :returns:
+          AsyncRequest object.
+        """
+        enc_event_id = urllib.quote(event_id, "")  # replace special char with %xx
+        path = "/events/%s.json" % enc_event_id
+        request = AsyncRequest("GET", path, accessKey=self.access_key)
+        request.set_rfunc(self._aget_resp)
+        self._connection.make_request(request)
+        return request
+
+    def get_event(self, event_id):
+        """Synchronouly get an event from Event Server."""
+        return self.aget_event(event_id).get_response()
+
+    def adelete_event(self, event_id):
+        """Asynchronouly delete an event from Event Server.
+
+        :param event_id: event id returned by the EventServer when creating the
+          event.
+
+        :returns:
+          AsyncRequest object.
+        """
+        enc_event_id = urllib.quote(event_id, "")  # replace special char with %xx
+        path = "/events/%s.json" % (enc_event_id, )
+        request = AsyncRequest("DELETE", path, accessKey=self.access_key)
+        request.set_rfunc(self._adelete_resp)
+        self._connection.make_request(request)
+        return request
+
+    def delete_event(self, event_id):
+        """Synchronouly delete an event from Event Server."""
+        return self.adelete_event(event_id).get_response()
+
+    # Below are helper functions
+
+    def aset_user(self, uid, properties={}, event_time=None):
+        """Set properties of a user.
+
+        Wrapper of acreate_event function, setting event to "$set" and entity_type
+        to "user".
+        """
+        return self.acreate_event(
+            event="$set",
+            entity_type="user",
+            entity_id=uid,
+            properties=properties,
+            event_time=event_time,
+        )
 
-    :raises:
-      ServerStatusError.
-    """
-    path = "/"
-    request = AsyncRequest("GET", path)
-    request.set_rfunc(self._aget_resp)
-    self._connection.make_request(request)
-    result = request.get_response()
-    return result
-
-  def _acreate_resp(self, response):
-    if response.error is not None:
-      raise NotCreatedError("Exception happened: %s for request %s" %
-                    (response.error, response.request))
-    elif response.status != httplib.CREATED:
-      raise NotCreatedError("request: %s status: %s body: %s" %
-                    (response.request, response.status,
-                     response.body))
-
-    return response
-
-  def _aget_resp(self, response):
-    if response.error is not None:
-      raise NotFoundError("Exception happened: %s for request %s" %
-                  (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise NotFoundError("request: %s status: %s body: %s" %
-                  (response.request, response.status,
-                   response.body))
-
-    return response.json_body
-
-  def _adelete_resp(self, response):
-    if response.error is not None:
-      raise NotFoundError("Exception happened: %s for request %s" %
-                  (response.error, response.request))
-    elif response.status != httplib.OK:
-      raise NotFoundError("request: %s status: %s body: %s" %
-                  (response.request, response.status,
-                   response.body))
-
-    return response.body
+    def set_user(self, uid, properties={}, event_time=None):
+        """Set properties of a user"""
+        return self.aset_user(uid, properties, event_time).get_response()
+
+    def aunset_user(self, uid, properties, event_time=None):
+        """Unset properties of an user.
+
+        Wrapper of acreate_event function, setting event to "$unset" and entity_type
+        to "user".
+        """
+        # check properties={}, it cannot be empty
+        return self.acreate_event(
+            event="$unset",
+            entity_type="user",
+            entity_id=uid,
+            properties=properties,
+            event_time=event_time,
+        )
 
+    def unset_user(self, uid, properties, event_time=None):
+        """Set properties of a user"""
+        return self.aunset_user(uid, properties, event_time).get_response()
+
+    def adelete_user(self, uid, event_time=None):
+        """Delete a user.
+
+        Wrapper of acreate_event function, setting event to "$delete" and entity_type
+        to "user".
+        """
+        return self.acreate_event(
+            event="$delete",
+            entity_type="user",
+            entity_id=uid,
+            event_time=event_time)
+
+    def delete_user(self, uid, event_time=None):
+        """Delete a user."""
+        return self.adelete_user(uid, event_time).get_response()
+
+    def aset_item(self, iid, properties={}, event_time=None):
+        """Set properties of an item.
+
+        Wrapper of acreate_event function, setting event to "$set" and entity_type
+        to "item".
+        """
+        return self.acreate_event(
+            event="$set",
+            entity_type="item",
+            entity_id=iid,
+            properties=properties,
+            event_time=event_time)
+
+    def set_item(self, iid, properties={}, event_time=None):
+        """Set properties of an item."""
+        return self.aset_item(iid, properties, event_time).get_response()
+
+    def aunset_item(self, iid, properties={}, event_time=None):
+        """Unset properties of an item.
+
+        Wrapper of acreate_event function, setting event to "$unset" and entity_type
+        to "item".
+        """
+        return self.acreate_event(
+            event="$unset",
+            entity_type="item",
+            entity_id=iid,
+            properties=properties,
+            event_time=event_time)
+
+    def unset_item(self, iid, properties={}, event_time=None):
+        """Unset properties of an item."""
+        return self.aunset_item(iid, properties, event_time).get_response()
+
+    def adelete_item(self, iid, event_time=None):
+        """Delete an item.
+
+        Wrapper of acreate_event function, setting event to "$delete" and entity_type
+        to "item".
+        """
+        return self.acreate_event(
+            event="$delete",
+            entity_type="item",
+            entity_id=iid,
+            event_time=event_time)
+
+    def delete_item(self, iid, event_time=None):
+        """Delete an item."""
+        return self.adelete_item(iid, event_time).get_response()
+
+    def arecord_user_action_on_item(self, action, uid, iid, properties={},
+                                    event_time=None):
+        """Create a user-to-item action.
+
+        Wrapper of acreate_event function, setting entity_type to "user" and
+        target_entity_type to "item".
+        """
+        return self.acreate_event(
+            event=action,
+            entity_type="user",
+            entity_id=uid,
+            target_entity_type="item",
+            target_entity_id=iid,
+            properties=properties,
+            event_time=event_time)
+
+    def record_user_action_on_item(self, action, uid, iid, properties={},
+                                   event_time=None):
+        """Create a user-to-item action."""
+        return self.arecord_user_action_on_item(
+            action, uid, iid, properties, event_time).get_response()
 
-class EventClient(BaseClient):
-  """Client for importing data into PredictionIO Event Server.
-
-  Notice that app_id has been deprecated as of 0.8.2. Please use access_token
-  instead.
-
-  :param access_key: the access key for your application.
-  :param url: the url of PredictionIO Event Server.
-  :param threads: number of threads to handle PredictionIO API requests.
-          Must be >= 1.
-  :param qsize: the max size of the request queue (optional).
-      The asynchronous request becomes blocking once this size has been
-      reached, until the queued requests are handled.
-      Default value is 0, which means infinite queue size.
-  :param timeout: timeout for HTTP connection attempts and requests in
-    seconds (optional).
-    Default value is 5.
-  """
-
-  def __init__(self, access_key, 
-      url="http://localhost:7070",
-      threads=1, qsize=0, timeout=5):
-    assert type(access_key) is str, ("access_key must be string. "
-        "Notice that app_id has been deprecated in Prediction.IO 0.8.2. "
-        "Please use access_key instead.")
-
-    super(EventClient, self).__init__(url, threads, qsize, timeout)
-
-    if len(access_key) <= 8:
-      raise DeprecationWarning(
-          "It seems like you are specifying an app_id. It is deprecated in "
-          "Prediction.IO 0.8.2. Please use access_key instead. Or, "
-          "you may use an earlier version of this sdk.")
-
-    self.access_key = access_key
-
-  def acreate_event(self, event, entity_type, entity_id,
-      target_entity_type=None, target_entity_id=None, properties=None,
-      event_time=None):
-    """Asynchronously create an event.
-
-    :param event: event name. type str.
-    :param entity_type: entity type. It is the namespace of the entityId and
-      analogous to the table name of a relational database. The entityId must be
-      unique within same entityType. type str.
-    :param entity_id: entity id. *entity_type-entity_id* becomes the unique
-      identifier of the entity. For example, you may have entityType named user,
-      and different entity IDs, say 1 and 2. In this case, user-1 and user-2
-      uniquely identifies entities. type str
-    :param target_entity_type: target entity type. type str.
-    :param target_entity_id: target entity id. type str.
-    :param properties: a custom dict associated with an event. type dict.
-    :param event_time: the time of the event. type datetime, must contain
-      timezone info. 
-
-    :returns:
-      AsyncRequest object. You can call the get_response() method using this
-      object to get the final resuls or status of this asynchronous request.
-    """
-    data = {
-        "event": event,
-        "entityType": entity_type,
-        "entityId": entity_id,
-        }
 
-    if target_entity_type is not None:
-      data["targetEntityType"] = target_entity_type
-
-    if target_entity_id is not None:
-      data["targetEntityId"] = target_entity_id
-
-    if properties is not None:
-      data["properties"] = properties
-
-    et = event_time_validation(event_time)
-    # EventServer uses milliseconds, but python datetime class uses micro. Hence
-    # need to skip the last three digits.
-    et_str = et.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + et.strftime("%z")
-    data["eventTime"] = et_str
-    
-    path = "/events.json?accessKey=%s" % (self.access_key, )
-    request = AsyncRequest("POST", path, **data)
-    request.set_rfunc(self._acreate_resp)
-    self._connection.make_request(request)
-    return request
-
-  def create_event(self, event, entity_type, entity_id,
-      target_entity_type=None, target_entity_id=None, properties=None,
-      event_time=None):
-    """Synchronously (blocking) create an event."""
-    return self.acreate_event(event, entity_type, entity_id,
-        target_entity_type, target_entity_id, properties, 
-        event_time).get_response()
-
-  def aget_event(self, event_id):
-    """Asynchronouly get an event from Event Server.
-
-    :param event_id: event id returned by the EventServer when creating the
-      event.
-
-    :returns:
-      AsyncRequest object. 
+class EngineClient(BaseClient):
+    """Client for extracting prediction results from an PredictionIO Engine
+    Instance.
+
+    :param url: the url of the PredictionIO Engine Instance.
+    :param threads: number of threads to handle PredictionIO API requests.
+            Must be >= 1.
+    :param qsize: the max size of the request queue (optional).
+        The asynchronous request becomes blocking once this size has been
+        reached, until the queued requests are handled.
+        Default value is 0, which means infinite queue size.
+    :param timeout: timeout for HTTP connection attempts and requests in
+      seconds (optional).
+      Default value is 5.
+
     """
-    enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
-    path = "/events/%s.json" % enc_event_id
-    request = AsyncRequest("GET", path, accessKey=self.access_key)
-    request.set_rfunc(self._aget_resp)
-    self._connection.make_request(request)
-    return request
 
-  def get_event(self, event_id):
-    """Synchronouly get an event from Event Server."""
-    return self.aget_event(event_id).get_response()
+    def __init__(self, url="http://localhost:8000", threads=1,
+                 qsize=0, timeout=5):
+        super(EngineClient, self).__init__(url, threads, qsize, timeout)
 
-  def adelete_event(self, event_id):
-    """Asynchronouly delete an event from Event Server.
+    def asend_query(self, data):
+        """Asynchronously send a request to the engine instance with data as the
+        query.
 
-    :param event_id: event id returned by the EventServer when creating the
-      event.
+        :param data: the query: It is coverted to an json object using json.dumps
+          method. type dict.
 
-    :returns:
-      AsyncRequest object. 
-    """
-    enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
-    path = "/events/%s.json" % (enc_event_id, )
-    request = AsyncRequest("DELETE", path, accessKey=self.access_key)
-    request.set_rfunc(self._adelete_resp)
-    self._connection.make_request(request)
-    return request
-
-  def delete_event(self, event_id):
-    """Synchronouly delete an event from Event Server."""
-    return self.adelete_event(event_id).get_response()
-
-  ## Below are helper functions
-
-  def aset_user(self, uid, properties={}, event_time=None):
-    """Set properties of a user.
-   
-    Wrapper of acreate_event function, setting event to "$set" and entity_type
-    to "user".
-    """
-    return self.acreate_event(
-      event="$set",
-      entity_type="user",
-      entity_id=uid,
-      properties=properties,
-      event_time=event_time,
-    )
-
-  def set_user(self, uid, properties={}, event_time=None):
-    """Set properties of a user"""
-    return self.aset_user(uid, properties, event_time).get_response()
-
-  def aunset_user(self, uid, properties, event_time=None):
-    """Unset properties of an user.
-   
-    Wrapper of acreate_event function, setting event to "$unset" and entity_type
-    to "user".
-    """
-    # check properties={}, it cannot be empty
-    return self.acreate_event(
-        event="$unset",
-        entity_type="user",
-        entity_id=uid,
-        properties=properties,
-        event_time=event_time,
-        )
+        :returns:
+          AsyncRequest object. You can call the get_response() method using this
+          object to get the final resuls or status of this asynchronous request.
+        """
+        path = "/queries.json"
+        request = AsyncRequest("POST", path, **data)
+        request.set_rfunc(self._aget_resp)
+        self._connection.make_request(request)
+        return request
 
-  def unset_user(self, uid, properties, event_time=None):
-    """Set properties of a user"""
-    return self.aunset_user(uid, properties, event_time).get_response()
-
-  def adelete_user(self, uid, event_time=None):
-    """Delete a user.
-   
-    Wrapper of acreate_event function, setting event to "$delete" and entity_type
-    to "user".
-    """
-    return self.acreate_event(
-        event="$delete",
-        entity_type="user",
-        entity_id=uid,
-        event_time=event_time)
-
-  def delete_user(self, uid, event_time=None):
-    """Delete a user."""
-    return self.adelete_user(uid, event_time).get_response()
-
-  def aset_item(self, iid, properties={}, event_time=None):
-    """Set properties of an item.
-   
-    Wrapper of acreate_event function, setting event to "$set" and entity_type
-    to "item".
-    """
-    return self.acreate_event(
-        event="$set",
-        entity_type="item",
-        entity_id=iid,
-        properties=properties,
-        event_time=event_time)
-
-  def set_item(self, iid, properties={}, event_time=None):
-    """Set properties of an item."""
-    return self.aset_item(iid, properties, event_time).get_response()
-
-  def aunset_item(self, iid, properties={}, event_time=None):
-    """Unset properties of an item.
-   
-    Wrapper of acreate_event function, setting event to "$unset" and entity_type
-    to "item".
-    """
-    return self.acreate_event(
-        event="$unset",
-        entity_type="item",
-        entity_id=iid,
-        properties=properties,
-        event_time=event_time)
-
-  def unset_item(self, iid, properties={}, event_time=None):
-    """Unset properties of an item."""
-    return self.aunset_item(iid, properties, event_time).get_response()
-
-  def adelete_item(self, iid, event_time=None):
-    """Delete an item.
-   
-    Wrapper of acreate_event function, setting event to "$delete" and entity_type
-    to "item".
-    """
-    return self.acreate_event(
-        event="$delete",
-        entity_type="item",
-        entity_id=iid,
-        event_time=event_time)
-
-  def delete_item(self, iid, event_time=None):
-    """Delete an item."""
-    return self.adelete_item(iid, event_time).get_response()
-
-  def arecord_user_action_on_item(self, action, uid, iid, properties={},
-      event_time=None):
-    """Create a user-to-item action.
-
-    Wrapper of acreate_event function, setting entity_type to "user" and
-    target_entity_type to "item".
-    """
-    return self.acreate_event(
-        event=action,
-        entity_type="user",
-        entity_id=uid,
-        target_entity_type="item",
-        target_entity_id=iid,
-        properties=properties,
-        event_time=event_time)
-
-  def record_user_action_on_item(self, action, uid, iid, properties={},
-      event_time=None):
-    """Create a user-to-item action."""
-    return self.arecord_user_action_on_item(
-      action, uid, iid, properties, event_time).get_response()
+    def send_query(self, data):
+        """Synchronously send a request.
 
+        :param data: the query: It is coverted to an json object using json.dumps
+          method. type dict.
 
-class EngineClient(BaseClient):
-  """Client for extracting prediction results from an PredictionIO Engine
-  Instance.
-  
-  :param url: the url of the PredictionIO Engine Instance.
-  :param threads: number of threads to handle PredictionIO API requests.
-          Must be >= 1.
-  :param qsize: the max size of the request queue (optional).
-      The asynchronous request becomes blocking once this size has been
-      reached, until the queued requests are handled.
-      Default value is 0, which means infinite queue size.
-  :param timeout: timeout for HTTP connection attempts and requests in
-    seconds (optional).
-    Default value is 5.
-  
-  """
-  def __init__(self, url="http://localhost:8000", threads=1,
-      qsize=0, timeout=5):
-    super(EngineClient, self).__init__(url, threads, qsize, timeout)
-
-  def asend_query(self, data):
-    """Asynchronously send a request to the engine instance with data as the
-    query.
-
-    :param data: the query: It is coverted to an json object using json.dumps
-      method. type dict. 
-
-    :returns:
-      AsyncRequest object. You can call the get_response() method using this
-      object to get the final resuls or status of this asynchronous request.
-    """
-    path = "/queries.json"
-    request = AsyncRequest("POST", path, **data)
-    request.set_rfunc(self._aget_resp)
-    self._connection.make_request(request)
-    return request
-
-  def send_query(self, data):
-    """Synchronously send a request.
-    
-    :param data: the query: It is coverted to an json object using json.dumps
-      method. type dict. 
-
-    :returns: the prediction.
-    """
-    return self.asend_query(data).get_response()
+        :returns: the prediction.
+        """
+        return self.asend_query(data).get_response()

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/bc678328/predictionio/connection.py
----------------------------------------------------------------------
diff --git a/predictionio/connection.py b/predictionio/connection.py
index 2c79d64..8c231f4 100644
--- a/predictionio/connection.py
+++ b/predictionio/connection.py
@@ -1,23 +1,22 @@
-
 try:
-  import Queue
+    import Queue
 except ImportError:
-  # pylint: disable=F0401
-  # http is a Python3 module, replacing httplib. Ditto.
-  import queue as Queue
+    # pylint: disable=F0401
+    # http is a Python3 module, replacing httplib. Ditto.
+    import queue as Queue
 import threading
 
 try:
-  import httplib
+    import httplib
 except ImportError:
-  # pylint: disable=F0401
-  from http import client as httplib
+    # pylint: disable=F0401
+    from http import client as httplib
 
 try:
-  from urllib import urlencode
+    from urllib import urlencode
 except ImportError:
-  # pylint: disable=F0401,E0611
-  from urllib.parse import urlencode
+    # pylint: disable=F0401,E0611
+    from urllib.parse import urlencode
 
 import datetime
 import json
@@ -25,9 +24,9 @@ import logging
 
 # use generators for python2 and python3
 try:
-  xrange
+    xrange
 except NameError:
-  xrange = range
+    xrange = range
 
 # some constants
 MAX_RETRY = 1  # 0 means no retry
@@ -39,332 +38,329 @@ DEBUG_LOG = False
 
 
 def enable_log(filename=None):
-  global logger
-  global DEBUG_LOG
-  timestamp = datetime.datetime.today()
-  if not filename:
-    logfile = "./log/predictionio_%s.log" % timestamp.strftime(
-      "%Y-%m-%d_%H:%M:%S.%f")
-  else:
-    logfile = filename
-  logging.basicConfig(filename=logfile,
-            filemode='w',
-            level=logging.DEBUG,
-            format='[%(levelname)s] %(name)s (%(threadName)s) %(message)s')
-  logger = logging.getLogger(__name__)
-  DEBUG_LOG = True
+    global logger
+    global DEBUG_LOG
+    timestamp = datetime.datetime.today()
+    if not filename:
+        logfile = "./log/predictionio_%s.log" % timestamp.strftime(
+            "%Y-%m-%d_%H:%M:%S.%f")
+    else:
+        logfile = filename
+    logging.basicConfig(filename=logfile,
+                        filemode='w',
+                        level=logging.DEBUG,
+                        format='[%(levelname)s] %(name)s (%(threadName)s) %(message)s')
+    logger = logging.getLogger(__name__)
+    DEBUG_LOG = True
 
 
 class PredictionIOAPIError(Exception):
-  pass
+    pass
 
 
 class NotSupportMethodError(PredictionIOAPIError):
-  pass
+    pass
 
 
 class ProgramError(PredictionIOAPIError):
-  pass
+    pass
 
 
 class AsyncRequest(object):
+    """AsyncRequest object
 
-  """AsyncRequest object
+    """
 
-  """
+    def __init__(self, method, path, **params):
+        self.method = method  # "GET" "POST" etc
+        # the sub path eg. POST /v1/users.json  GET /v1/users/1.json
+        self.path = path
+        # dictionary format eg. {"appkey" : 123, "id" : 3}
+        self.params = params
+        # use queue to implement response, store AsyncResponse object
+        self.response_q = Queue.Queue(1)
+        self.qpath = "%s?%s" % (self.path, urlencode(self.params))
+        self._response = None
+        # response function to be called to handle the response
+        self.rfunc = None
 
-  def __init__(self, method, path, **params):
-    self.method = method  # "GET" "POST" etc
-    # the sub path eg. POST /v1/users.json  GET /v1/users/1.json
-    self.path = path
-    # dictionary format eg. {"appkey" : 123, "id" : 3}
-    self.params = params
-    # use queue to implement response, store AsyncResponse object
-    self.response_q = Queue.Queue(1)
-    self.qpath = "%s?%s" % (self.path, urlencode(self.params))
-    self._response = None
-    # response function to be called to handle the response
-    self.rfunc = None
+    def __str__(self):
+        return "%s %s %s %s" % (self.method, self.path, self.params,
+                                self.qpath)
 
-  def __str__(self):
-    return "%s %s %s %s" % (self.method, self.path, self.params,
-                self.qpath)
+    def set_rfunc(self, func):
+        self.rfunc = func
 
-  def set_rfunc(self, func):
-    self.rfunc = func
+    def set_response(self, response):
+        """ store the response
 
-  def set_response(self, response):
-    """ store the response
+        NOTE: Must be only called once
+        """
+        self.response_q.put(response)
 
-    NOTE: Must be only called once
-    """
-    self.response_q.put(response)
+    def get_response(self):
+        """Get the response. Blocking.
 
-  def get_response(self):
-    """Get the response. Blocking.
+        :returns: self.rfunc's return type.
+        """
+        if self._response is None:
+            tmp_response = self.response_q.get(True)  # NOTE: blocking
+            if self.rfunc is None:
+                self._response = tmp_response
+            else:
+                self._response = self.rfunc(tmp_response)
+
+        return self._response
+
+
+class AsyncResponse(object):
+    """Store the response of asynchronous request
 
-    :returns: self.rfunc's return type.
+    When get the response, user should check if error is None (which means no
+    Exception happens).
+    If error is None, then should check if the status is expected.
     """
-    if self._response is None:
-      tmp_response = self.response_q.get(True)  # NOTE: blocking
-      if self.rfunc is None:
-        self._response = tmp_response
-      else:
-        self._response = self.rfunc(tmp_response)
 
-    return self._response
+    def __init__(self):
+        #: exception object if any happens
+        self.error = None
+
+        self.version = None
+        self.status = None
+        self.reason = None
+        #: Response header. str
+        self.headers = None
+        #: Response body. str
+        self.body = None
+        #: Jsonified response body. Remains None if conversion is unsuccessful.
+        self.json_body = None
+        #: Point back to the AsyncRequest object
+        self.request = None
+
+    def __str__(self):
+        return "e:%s v:%s s:%s r:%s h:%s b:%s" % (self.error, self.version,
+                                                  self.status, self.reason,
+                                                  self.headers, self.body)
+
+    def set_resp(self, version, status, reason, headers, body):
+        self.version = version
+        self.status = status
+        self.reason = reason
+        self.headers = headers
+        self.body = body
+        # Try to extract the json.
+        try:
+            self.json_body = json.loads(body)
+        except ValueError as ex:  # noqa
+            self.json_body = None
 
+    def set_error(self, error):
+        self.error = error
 
-class AsyncResponse(object):
-  """Store the response of asynchronous request
-
-  When get the response, user should check if error is None (which means no
-  Exception happens).
-  If error is None, then should check if the status is expected.
-  """
-
-  def __init__(self):
-    #: exception object if any happens
-    self.error = None
-
-    self.version = None
-    self.status = None
-    self.reason = None
-    #: Response header. str
-    self.headers = None
-    #: Response body. str
-    self.body = None
-    #: Jsonified response body. Remains None if conversion is unsuccessful.
-    self.json_body = None
-    #: Point back to the AsyncRequest object
-    self.request = None  
-
-  def __str__(self):
-    return "e:%s v:%s s:%s r:%s h:%s b:%s" % (self.error, self.version,
-                          self.status, self.reason,
-                          self.headers, self.body)
-
-  def set_resp(self, version, status, reason, headers, body):
-    self.version = version
-    self.status = status
-    self.reason = reason
-    self.headers = headers
-    self.body = body
-    # Try to extract the json.
-    try:
-      self.json_body = json.loads(body)
-    except ValueError as ex:
-      self.json_body = None
-
-  def set_error(self, error):
-    self.error = error
-
-  def set_request(self, request):
-    self.request = request
+    def set_request(self, request):
+        self.request = request
 
 
 class PredictionIOHttpConnection(object):
+    def __init__(self, host, https=True, timeout=5):
+        if https:  # https connection
+            self._connection = httplib.HTTPSConnection(host, timeout=timeout)
+        else:
+            self._connection = httplib.HTTPConnection(host, timeout=timeout)
 
-  def __init__(self, host, https=True, timeout=5):
-    if https:  # https connection
-      self._connection = httplib.HTTPSConnection(host, timeout=timeout)
-    else:
-      self._connection = httplib.HTTPConnection(host, timeout=timeout)
+    def connect(self):
+        self._connection.connect()
 
-  def connect(self):
-    self._connection.connect()
+    def close(self):
+        self._connection.close()
 
-  def close(self):
-    self._connection.close()
+    def request(self, method, url, body={}, headers={}):
+        """
+        http request wrapper function, with retry capability in case of error.
+        catch error exception and store it in AsyncResponse object
+        return AsyncResponse object
 
-  def request(self, method, url, body={}, headers={}):
-    """
-    http request wrapper function, with retry capability in case of error.
-    catch error exception and store it in AsyncResponse object
-    return AsyncResponse object
+        Args:
+          method: http method, type str
+          url: url path, type str
+          body: http request body content, type dict
+          header: http request header , type dict
+        """
 
-    Args:
-      method: http method, type str
-      url: url path, type str
-      body: http request body content, type dict
-      header: http request header , type dict
-    """
+        response = AsyncResponse()
 
-    response = AsyncResponse()
-
-    try:
-      # number of retry in case of error (minimum 0 means no retry)
-      retry_limit = MAX_RETRY
-      mod_headers = dict(headers)  # copy the headers
-      mod_headers["Connection"] = "keep-alive"
-      enc_body = None
-      if body:  # if body is not empty
-        #enc_body = urlencode(body)
-        #mod_headers[
-        #  "Content-type"] = "application/x-www-form-urlencoded"
-        enc_body = json.dumps(body)
-        mod_headers[
-          "Content-type"] = "application/json"
-        #mod_headers["Accept"] = "text/plain"
-    except Exception as e:
-      response.set_error(e)
-      return response
-
-    if DEBUG_LOG:
-      logger.debug("Request m:%s u:%s h:%s b:%s", method, url,
-             mod_headers, enc_body)
-    # retry loop
-    for i in xrange(retry_limit + 1):
-      try:
-        if i != 0:
-          if DEBUG_LOG:
-            logger.debug("retry request %s times" % i)
-        if self._connection.sock is None:
-          self._connection.connect()
-        self._connection.request(method, url, enc_body, mod_headers)
-      except Exception as e:
-        self._connection.close()
-        if i == retry_limit:
-          # new copy of e created everytime??
-          response.set_error(e)
-      else:  # NOTE: this is try's else clause
-        # connect() and request() OK
         try:
-          resp = self._connection.getresponse()
+            # number of retry in case of error (minimum 0 means no retry)
+            retry_limit = MAX_RETRY
+            mod_headers = dict(headers)  # copy the headers
+            mod_headers["Connection"] = "keep-alive"
+            enc_body = None
+            if body:  # if body is not empty
+                # enc_body = urlencode(body)
+                # mod_headers[
+                # "Content-type"] = "application/x-www-form-urlencoded"
+                enc_body = json.dumps(body)
+                mod_headers[
+                    "Content-type"] = "application/json"
+                # mod_headers["Accept"] = "text/plain"
         except Exception as e:
-          self._connection.close()
-          if i == retry_limit:
             response.set_error(e)
-        else:  # NOTE: this is try's else clause
-          # getresponse() OK
-          resp_version = resp.version  # int
-          resp_status = resp.status  # int
-          resp_reason = resp.reason  # str
-          # resp.getheaders() returns list of tuples
-          # converted to dict format
-          resp_headers = dict(resp.getheaders())
-          # NOTE: have to read the response before sending out next
-          # http request
-          resp_body = resp.read()  # str
-          response.set_resp(version=resp_version, status=resp_status,
-                    reason=resp_reason, headers=resp_headers,
-                    body=resp_body)
-          break  # exit retry loop
-    # end of retry loop
-    if DEBUG_LOG:
-      logger.debug("Response %s", response)
-    return response  # AsyncResponse object
+            return response
+
+        if DEBUG_LOG:
+            logger.debug("Request m:%s u:%s h:%s b:%s", method, url,
+                         mod_headers, enc_body)
+        # retry loop
+        for i in xrange(retry_limit + 1):
+            try:
+                if i != 0:
+                    if DEBUG_LOG:
+                        logger.debug("retry request %s times" % i)
+                if self._connection.sock is None:
+                    self._connection.connect()
+                self._connection.request(method, url, enc_body, mod_headers)
+            except Exception as e:
+                self._connection.close()
+                if i == retry_limit:
+                    # new copy of e created everytime??
+                    response.set_error(e)
+            else:  # NOTE: this is try's else clause
+                # connect() and request() OK
+                try:
+                    resp = self._connection.getresponse()
+                except Exception as e:
+                    self._connection.close()
+                    if i == retry_limit:
+                        response.set_error(e)
+                else:  # NOTE: this is try's else clause
+                    # getresponse() OK
+                    resp_version = resp.version  # int
+                    resp_status = resp.status  # int
+                    resp_reason = resp.reason  # str
+                    # resp.getheaders() returns list of tuples
+                    # converted to dict format
+                    resp_headers = dict(resp.getheaders())
+                    # NOTE: have to read the response before sending out next
+                    # http request
+                    resp_body = resp.read()  # str
+                    response.set_resp(version=resp_version, status=resp_status,
+                                      reason=resp_reason, headers=resp_headers,
+                                      body=resp_body)
+                    break  # exit retry loop
+        # end of retry loop
+        if DEBUG_LOG:
+            logger.debug("Response %s", response)
+        return response  # AsyncResponse object
 
 
 def connection_worker(host, request_queue, https=True, timeout=5, loop=True):
-  """worker function which establishes connection and wait for request jobs
-  from the request_queue
-
-  Args:
-    request_queue: the request queue storing the AsyncRequest object
-      valid requests:
-        GET
-        POST
-        DELETE
-        KILL
-    https: HTTPS (True) or HTTP (False)
-    timeout: timeout for HTTP connection attempts and requests in seconds
-    loop: This worker function stays in a loop waiting for request
-      For testing purpose only. should always be set to True.
-  """
-
-  connect = PredictionIOHttpConnection(host, https, timeout)
-
-  # loop waiting for job form request queue
-  killed = not loop
-
-  while True:
-    # print "thread %s waiting for request" % thread.get_ident()
-    request = request_queue.get(True)  # NOTE: blocking get
-    # print "get request %s" % request
-    method = request.method
-    if method == "GET":
-      path = request.qpath
-      d = connect.request("GET", path)
-    elif method == "POST":
-      path = request.path
-      body = request.params
-      d = connect.request("POST", path, body)
-    elif method == "DELETE":
-      path = request.qpath
-      d = connect.request("DELETE", path)
-    elif method == "KILL":
-      # tell the thread to kill the connection
-      killed = True
-      d = AsyncResponse()
-    else:
-      d = AsyncResponse()
-      d.set_error(NotSupportMethodError(
-        "Don't Support the method %s" % method))
+    """worker function which establishes connection and wait for request jobs
+    from the request_queue
 
-    d.set_request(request)
-    request.set_response(d)
-    request_queue.task_done()
-    if killed:
-      break
+    Args:
+      request_queue: the request queue storing the AsyncRequest object
+        valid requests:
+          GET
+          POST
+          DELETE
+          KILL
+      https: HTTPS (True) or HTTP (False)
+      timeout: timeout for HTTP connection attempts and requests in seconds
+      loop: This worker function stays in a loop waiting for request
+        For testing purpose only. should always be set to True.
+    """
 
-  # end of while loop
-  connect.close()
+    connect = PredictionIOHttpConnection(host, https, timeout)
+
+    # loop waiting for job form request queue
+    killed = not loop
+
+    while True:
+        # print "thread %s waiting for request" % thread.get_ident()
+        request = request_queue.get(True)  # NOTE: blocking get
+        # print "get request %s" % request
+        method = request.method
+        if method == "GET":
+            path = request.qpath
+            d = connect.request("GET", path)
+        elif method == "POST":
+            path = request.path
+            body = request.params
+            d = connect.request("POST", path, body)
+        elif method == "DELETE":
+            path = request.qpath
+            d = connect.request("DELETE", path)
+        elif method == "KILL":
+            # tell the thread to kill the connection
+            killed = True
+            d = AsyncResponse()
+        else:
+            d = AsyncResponse()
+            d.set_error(NotSupportMethodError(
+                "Don't Support the method %s" % method))
+
+        d.set_request(request)
+        request.set_response(d)
+        request_queue.task_done()
+        if killed:
+            break
+
+    # end of while loop
+    connect.close()
 
 
 class Connection(object):
+    """abstract object for connection with server
 
-  """abstract object for connection with server
-
-  spawn multiple connection_worker threads to handle jobs in the queue q
-  """
-
-  def __init__(self, host, threads=1, qsize=0, https=True, timeout=5):
-    """constructor
-
-    Args:
-      host: host of the server.
-      threads: type int, number of threads to be spawn
-      qsize: size of the queue q
-      https: indicate it is httpS (True) or http connection (False)
-      timeout: timeout for HTTP connection attempts and requests in
-        seconds
-    """
-    self.host = host
-    self.https = https
-    self.q = Queue.Queue(qsize)  # if qsize=0, means infinite
-    self.threads = threads
-    self.timeout = timeout
-    # start thread based on threads number
-    self.tid = {}  # dictionary of thread object
-
-    for i in xrange(threads):
-      tname = "PredictionIOThread-%s" % i  # thread name
-      self.tid[i] = threading.Thread(
-        target=connection_worker, name=tname,
-        kwargs={'host': self.host, 'request_queue': self.q,
-            'https': self.https, 'timeout': self.timeout})
-      self.tid[i].setDaemon(True)
-      self.tid[i].start()
-
-  def make_request(self, request):
-    """put the request into the q
-    """
-    self.q.put(request)
-
-  def pending_requests(self):
-    """number of pending requests in the queue
+    spawn multiple connection_worker threads to handle jobs in the queue q
     """
-    return self.q.qsize()
-
-  def close(self):
-    """close this Connection. Call this when main program exits
-    """
-    # set kill message to q
-    for i in xrange(self.threads):
-      self.make_request(AsyncRequest("KILL", ""))
-
-    self.q.join()  # wait for q empty
 
-    for i in xrange(self.threads):  # wait for all thread finish
-      self.tid[i].join()
+    def __init__(self, host, threads=1, qsize=0, https=True, timeout=5):
+        """constructor
+
+        Args:
+          host: host of the server.
+          threads: type int, number of threads to be spawn
+          qsize: size of the queue q
+          https: indicate it is httpS (True) or http connection (False)
+          timeout: timeout for HTTP connection attempts and requests in
+            seconds
+        """
+        self.host = host
+        self.https = https
+        self.q = Queue.Queue(qsize)  # if qsize=0, means infinite
+        self.threads = threads
+        self.timeout = timeout
+        # start thread based on threads number
+        self.tid = {}  # dictionary of thread object
+
+        for i in xrange(threads):
+            tname = "PredictionIOThread-%s" % i  # thread name
+            self.tid[i] = threading.Thread(
+                target=connection_worker, name=tname,
+                kwargs={'host': self.host, 'request_queue': self.q,
+                        'https': self.https, 'timeout': self.timeout})
+            self.tid[i].setDaemon(True)
+            self.tid[i].start()
+
+    def make_request(self, request):
+        """put the request into the q
+        """
+        self.q.put(request)
+
+    def pending_requests(self):
+        """number of pending requests in the queue
+        """
+        return self.q.qsize()
+
+    def close(self):
+        """close this Connection. Call this when main program exits
+        """
+        # set kill message to q
+        for i in xrange(self.threads):
+            self.make_request(AsyncRequest("KILL", ""))
+
+        self.q.join()  # wait for q empty
+
+        for i in xrange(self.threads):  # wait for all thread finish
+            self.tid[i].join()


[19/24] incubator-predictionio-sdk-python git commit: Closes #21

Posted by sh...@apache.org.
Closes #21


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/4b51a300
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/4b51a300
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/4b51a300

Branch: refs/heads/master
Commit: 4b51a300e95c123de67742f7679d55f8045e07d7
Parents: 5510953
Author: Shinsuke Sugaya <sh...@apache.org>
Authored: Sun Sep 10 23:20:52 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Sun Sep 10 23:20:52 2017 +0900

----------------------------------------------------------------------

----------------------------------------------------------------------



[09/24] incubator-predictionio-sdk-python git commit: Merge pull request #13 from AlmogCohen/develop

Posted by sh...@apache.org.
Merge pull request #13 from AlmogCohen/develop

Added missing import for InvalidArgumentError

Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/b85d044f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/b85d044f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/b85d044f

Branch: refs/heads/master
Commit: b85d044f83bb4f811232d97db4bb7626222cac83
Parents: 849c2d5 a6f841f
Author: EmergentOrder <le...@gmail.com>
Authored: Wed Oct 28 11:31:42 2015 -0300
Committer: EmergentOrder <le...@gmail.com>
Committed: Wed Oct 28 11:31:42 2015 -0300

----------------------------------------------------------------------
 predictionio/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/b85d044f/predictionio/__init__.py
----------------------------------------------------------------------


[14/24] incubator-predictionio-sdk-python git commit: fix version numbers

Posted by sh...@apache.org.
fix version numbers


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/cd72584e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/cd72584e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/cd72584e

Branch: refs/heads/master
Commit: cd72584e3617109eb9f77fe9e7489dd3cc2c9d6b
Parents: 73adea9
Author: EmergentOrder <le...@gmail.com>
Authored: Tue Nov 3 14:13:23 2015 -0400
Committer: EmergentOrder <le...@gmail.com>
Committed: Tue Nov 3 14:13:23 2015 -0400

----------------------------------------------------------------------
 docs/source/conf.py      | 2 +-
 predictionio/__init__.py | 2 +-
 setup.py                 | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/cd72584e/docs/source/conf.py
----------------------------------------------------------------------
diff --git a/docs/source/conf.py b/docs/source/conf.py
index d52d83e..5139b89 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -54,7 +54,7 @@ copyright = u'2014, TappingStone, Inc.'
 # The short X.Y version.
 version = '0.9'
 # The full version, including alpha/beta/rc tags.
-release = '0.9.6'
+release = '0.9.8'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/cd72584e/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 699b2db..b429b4e 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -4,7 +4,7 @@ Python applications with PredictionIO REST API services.
 """
 
 
-__version__ = "0.9.6"
+__version__ = "0.9.8"
 
 # import packages
 import re

http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/cd72584e/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index 67b12e3..eeafe17 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@ __license__ = "Apache License, Version 2.0"
 
 setup(
     name='PredictionIO',
-    version="0.9.6",
+    version="0.9.8",
     author=__author__,
     author_email=__email__,
     packages=['predictionio'],


[07/24] incubator-predictionio-sdk-python git commit: adding comment: (getting events through the Event Server API is used for debugging and not recommended for production)

Posted by sh...@apache.org.
adding comment: (getting events through the Event Server API is used for debugging and not recommended for production)


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/6c95d7f5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/6c95d7f5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/6c95d7f5

Branch: refs/heads/master
Commit: 6c95d7f5d8e060c339b617cd9de342740a21de43
Parents: 8bdf59f
Author: Nguyen Viet Anh <vi...@gmail.com>
Authored: Sat Aug 1 09:53:42 2015 +0700
Committer: Nguyen Viet Anh <vi...@gmail.com>
Committed: Sat Aug 1 09:53:42 2015 +0700

----------------------------------------------------------------------
 predictionio/__init__.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/6c95d7f5/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 01b7cc2..f4db10c 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -287,7 +287,7 @@ class EventClient(BaseClient):
     return self.aget_event(event_id).get_response()
 
   def aget_events(self, startTime=None, untilTime=None, entityType=None, entityId=None, limit=None, reversed=False):
-    """Asynchronouly get events from Event Server.
+    """Asynchronouly get events from Event Server. (Getting events through the Event Server API is used for debugging and not recommended for production)
 
     :param startTime: time in ISO8601 format. Return events with eventTime >= startTime.
     :param untilTime: time in ISO8601 format. Return events with eventTime < untilTime.
@@ -328,7 +328,7 @@ class EventClient(BaseClient):
     return request
 
   def get_events(self, startTime=None, untilTime=None, entityType=None, entityId=None, limit=None, reversed=False):
-    """Synchronouly get event from Event Server."""
+    """Synchronouly get event from Event Server. (Getting events through the Event Server API is used for debugging and not recommended for production)"""
     return self.aget_events(
       startTime=startTime,
       untilTime=untilTime,


[12/24] incubator-predictionio-sdk-python git commit: exclude indentation error

Posted by sh...@apache.org.
exclude indentation error


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/e63bf7f6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/e63bf7f6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/e63bf7f6

Branch: refs/heads/master
Commit: e63bf7f697c50b9ec23496fc8dc39fe556f97cef
Parents: 77ef0dd
Author: EmergentOrder <le...@gmail.com>
Authored: Tue Nov 3 13:56:00 2015 -0400
Committer: EmergentOrder <le...@gmail.com>
Committed: Tue Nov 3 13:56:00 2015 -0400

----------------------------------------------------------------------
 tox.ini | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/e63bf7f6/tox.ini
----------------------------------------------------------------------
diff --git a/tox.ini b/tox.ini
index 23d96e4..87b57e9 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,5 +5,9 @@ envlist = py27,py34
 deps = flake8
        pandas
 
+[flake8]
+ignore = E111
+
+
 commands = flake8 --ignore=E501 --filename=*.py --exclude=doc,setup.py,*/tests/*
            python -m unittest discover --pattern=*.py tests


[16/24] incubator-predictionio-sdk-python git commit: fix InvalidArgumentError is not defined

Posted by sh...@apache.org.
fix InvalidArgumentError is not defined

Closes #19


Project: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/commit/a151e0cd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/tree/a151e0cd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/diff/a151e0cd

Branch: refs/heads/master
Commit: a151e0cdfc9f84334cb29c6bb429a829606f5c4b
Parents: 8e35e33
Author: goodspeed <ca...@gmail.com>
Authored: Sun Sep 10 23:12:50 2017 +0900
Committer: Shinsuke Sugaya <sh...@apache.org>
Committed: Sun Sep 10 23:12:50 2017 +0900

----------------------------------------------------------------------
 predictionio/__init__.py | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-predictionio-sdk-python/blob/a151e0cd/predictionio/__init__.py
----------------------------------------------------------------------
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 01ac045..d70c85c 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -47,6 +47,10 @@ class NotFoundError(PredictionIOAPIError):
   pass
 
 
+class InvalidArgumentError(PredictionIOAPIError):
+    pass
+
+
 def event_time_validation(t):
   """ Validate event_time according to EventAPI Specification.
   """