SDKPYTHON-8 #comment add get_itemsim_topn and version check in test script
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 5d4fcf4..9855198 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -49,9 +49,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '0.5'
+version = '0.6'
 # The full version, including alpha/beta/rc tags.
-release = '0.5.0'
+release = '0.6.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 2f68cf2..608a1fb 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -9,7 +9,7 @@
 __copyright__ = "Copyright 2013, TappingStone, Inc."
 __license__ = "Apache License, Version 2.0"
 
-__version__ = "0.5.0"
+__version__ = "0.6.0-SNAPSHOT"
 
 
 # import packages
@@ -63,6 +63,10 @@
     "Error happened when tried to get item recommendation"
     pass
 
+class ItemSimNotFoundError(PredictionIOAPIError):
+    "Error happened when tried to get similar items"
+    pass
+
 class InvalidArgumentError(PredictionIOAPIError):
     "Arguments are not valid"
     pass
@@ -485,6 +489,69 @@
         request = self._aget_user_itemrec_topn(uid, n, engine, 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"])
+
+        enc_iid = urllib.quote(iid,"") # replace special char with %xx
+        path = "%s/engines/itemsim/%s/topn.json" % (self.apiversion, engine)
+        request = AsyncRequest("GET", path, pio_appkey=self.appkey, pio_iid=enc_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 _auser_action_on_item(self, action, uid, iid, params):
         """Private function to asynchronously create an user action on an item
 
@@ -795,6 +862,25 @@
         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 record_action_on_item(self, action, iid, params={}):
         """Blocking request to create action on an item
 
diff --git a/tests/import_testdata.py b/tests/import_testdata.py
index 40263e9..add526f 100644
--- a/tests/import_testdata.py
+++ b/tests/import_testdata.py
@@ -3,9 +3,14 @@
 """
 import predictionio
 
-APP_KEY = "zHCx9Xv9sZ9Q21LMINKcrgZNgGJ3oReZA9Zvf0MsyJYDv6FwgHEeEI0XTEY5aEsu"
+APP_KEY = "y2Fk4BACEGYeJnqBF4zL9TmrIBdF9va3gyFaLsnM7PVyUNf0G00zC8vCnyBx5hdA"
 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)
 
diff --git a/tests/predictionio_itemrec_test.py b/tests/predictionio_itemrec_test.py
index 7d39ee5..873cc73 100644
--- a/tests/predictionio_itemrec_test.py
+++ b/tests/predictionio_itemrec_test.py
@@ -14,6 +14,11 @@
 
 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
diff --git a/tests/predictionio_itemsim_test.py b/tests/predictionio_itemsim_test.py
new file mode 100644
index 0000000..3c27886
--- /dev/null
+++ b/tests/predictionio_itemsim_test.py
@@ -0,0 +1,145 @@
+"""
+Test getting itemsim after algo training completes (pdio-itemsimcf with cosine sim).
+"""
+import predictionio
+import unittest
+import threading
+import time
+
+import httplib
+import urllib
+
+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(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()
diff --git a/tests/predictionio_test.py b/tests/predictionio_test.py
index 41e2ecd..fe919cc 100644
--- a/tests/predictionio_test.py
+++ b/tests/predictionio_test.py
@@ -9,10 +9,14 @@
 import httplib
 import urllib
 
-
-APP_KEY = "zHCx9Xv9sZ9Q21LMINKcrgZNgGJ3oReZA9Zvf0MsyJYDv6FwgHEeEI0XTEY5aEsu" # replace this with your AppKey
+APP_KEY = "y2Fk4BACEGYeJnqBF4zL9TmrIBdF9va3gyFaLsnM7PVyUNf0G00zC8vCnyBx5hdA" # 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)
+    
 class TestPredictionIO(unittest.TestCase):
 
     def setUp(self):
@@ -204,6 +208,25 @@
 
         client.close()
 
+    def test_get_itemsim_topn(self):
+        client = predictionio.Client(APP_KEY, 1, API_URL)
+
+        try:
+            itemsim = client.get_itemsim_topn("test-python-engine", "i1unknwon", 10)
+        except predictionio.ItemSimNotFoundError as e:
+            pass # expected exception
+        except:
+            raise
+
+        try:
+            itemsim = client.get_itemsim_topn("test-python-engine", "i1unknwon", 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()
+
 """
 to run individual test:
 $ python -m unittest predictionio_test.TestPredictionIO.test_user