Repository: Shopify/shopify_python_api

Issue:
Support for independently creating/modifying product images.
Please correct me if I'm wrong, but at the moment the only way to create/update product images through the Python API is directly through a POST/PUT call to the product endpoint.

As per the [Shopify API documentation on product images](http://docs.shopify.com/api/product_image), we should be able to make POST and PUT calls directly to `/admin/products/#{id}/images.json` and `PUT /admin/products/#{id}/images/#{id}.json`. However, this doesn't seem to work currently with the API as the prefix for the `Image` class isn't properly being built. Thus, something like this...

```python
image = shopify.Image()
image.src = "http://example.com/example.png"
image.product_id = 123456789
image.save()
```

... tries to POST to `/admin/products//images.json` which returns a 406.

Looking at the source, I think a fix would be to implement the `prefix()` class method, similar to what's been done with the `Variant` class. Just wanted to run this by folks who might be more familiar with this to see if that might be a valid solution.

Discussion:

Patch:
diff --git a/shopify/resources/image.py b/shopify/resources/image.py
index c5f9fd2..a0e82ef 100644
--- a/shopify/resources/image.py
+++ b/shopify/resources/image.py
@@ -8,6 +8,14 @@ import re
 class Image(ShopifyResource):
     _prefix_source = "/admin/products/$product_id/"
 
+    @classmethod
+    def _prefix(cls, options={}):
+        product_id = options.get("product_id")
+        if product_id:
+            return "/admin/products/%s" % (product_id)
+        else:
+            return "/admin"
+
     def __getattr__(self, name):
         if name in ["pico", "icon", "thumb", "small", "compact", "medium", "large", "grande", "original"]:
             return re.sub(r"/(.*)\.(\w{2,4})", r"/\1_%s.\2" % (name), self.src)
@@ -24,3 +32,8 @@ class Image(ShopifyResource):
             return []
         query_params = { 'metafield[owner_id]': self.id, 'metafield[owner_resource]': 'product_image' }
         return Metafield.find(from_ = '/admin/metafields.json?%s' % urllib.parse.urlencode(query_params))
+
+    def save(self):
+        if 'product_id' not in self._prefix_options:
+            self._prefix_options['product_id'] = self.product_id
+        return super(ShopifyResource, self).save()


Test patch:
diff --git a/test/image_test.py b/test/image_test.py
index 935f53b..1234898 100644
--- a/test/image_test.py
+++ b/test/image_test.py
@@ -13,6 +13,17 @@ class ImageTest(TestCase):
         self.assertEqual('http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1389388540', image.src)
         self.assertEqual(850703190, image.id)
 
+    def test_create_image_then_add_parent_id(self):
+        self.fake("products/632910392/images", method='POST', body=self.load_fixture('image'), headers={'Content-type': 'application/json'})
+        image = shopify.Image()
+        image.position = 1
+        image.product_id = 632910392
+        image.attachment = "R0lGODlhbgCMAPf/APbr48VySrxTO7IgKt2qmKQdJeK8lsFjROG5p/nz7Zg3MNmnd7Q1MLNVS9GId71hSJMZIuzTu4UtKbeEeakhKMl8U8WYjfr18YQaIbAf=="
+        image.save()
+
+        self.assertEqual('http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1389388540', image.src)
+        self.assertEqual(850703190, image.id)
+
     def test_get_images(self):
         self.fake("products/632910392/images", method='GET', body=self.load_fixture('images'))
         image = shopify.Image.find(product_id=632910392)