Repository: contentful/contentful.py

Issue:
Optional linked assets cannot be represented
`Asset.__repr__()` utilises `Asset.url()` which depends on `file` instance attribute.

If the asset is optional and not set, the object cannot be represented: `'contentful.asset.Asset object' has no attribute 'file'`.

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1be23e4..d70c0ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,8 @@
 # CHANGELOG
 
 ## Unreleased
+### Fixed
+* Assets with empty or missing files no longer error when trying to get it serialized to string. [#48](https://github.com/contentful/contentful.py/issues/48)
 
 ## v1.12.1
 ### Fixed
diff --git a/contentful/asset.py b/contentful/asset.py
index 90d9ffe..284590b 100644
--- a/contentful/asset.py
+++ b/contentful/asset.py
@@ -30,6 +30,9 @@ class Asset(FieldsResource):
             "//images.contentful.com/spaces/foobar/...?w=120&h=160"
         """
 
+        if not hasattr(self, 'file') or not self.file:
+            return ""
+
         url = self.file['url']
         args = ['{0}={1}'.format(k, v) for k, v in kwargs.items()]
 


Test patch:
diff --git a/tests/asset_test.py b/tests/asset_test.py
index 426b2e2..f0c5635 100644
--- a/tests/asset_test.py
+++ b/tests/asset_test.py
@@ -38,3 +38,50 @@ class AssetTest(TestCase):
         self.assertEqual(asset.url(), '//images.contentful.com/...')
         self.assertEqual(asset.url(w=123), '//images.contentful.com/...?w=123')
         self.assertEqual(str(asset), "<Asset id='foo' url='//images.contentful.com/...'>")
+
+    def test_asset_with_no_file_can_be_serialized_correctly(self):
+        asset = Asset({
+            'sys': {
+                'type': 'Asset',
+                'id': 'foo',
+                'createdAt': '2016-12-01T11:39:20.257859',
+                'updatedAt': '2016-12-01T11:39:20.257859',
+                'space': {
+                    'sys': {
+                        'type': 'Link',
+                        'linkType': 'Space',
+                        'id': 'foo'
+                    }
+                }
+            },
+            'fields': {
+                'title': 'Awesome Pic',
+                'description': 'A picture of something'
+            }
+        })
+
+        self.assertEqual(str(asset), "<Asset id='foo' url=''>")
+
+    def test_asset_with_empty_file_can_be_serialized_correctly(self):
+        asset = Asset({
+            'sys': {
+                'type': 'Asset',
+                'id': 'foo',
+                'createdAt': '2016-12-01T11:39:20.257859',
+                'updatedAt': '2016-12-01T11:39:20.257859',
+                'space': {
+                    'sys': {
+                        'type': 'Link',
+                        'linkType': 'Space',
+                        'id': 'foo'
+                    }
+                }
+            },
+            'fields': {
+                'title': 'Awesome Pic',
+                'description': 'A picture of something',
+                'file': {}
+            }
+        })
+
+        self.assertEqual(str(asset), "<Asset id='foo' url=''>")