← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jtv/maas/make-file-upload into lp:maas

 

Jeroen T. Vermeulen has proposed merging lp:~jtv/maas/make-file-upload into lp:maas.

Commit message:
Factory method: make_file_upload, to create a file-like object that's just a little bit more file-like than BytesIO.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jtv/maas/make-file-upload/+merge/135886

This is another bit I just pulled from the larger branch I'm working on, to whittle it down to a convenient reviewing size.  This helper turned out to be of use in existing code as well.  It creates a BytesIO, but with a "name" attribute, and in the usual factory style, it makes up the name and/or content as desired.

I'm not entirely sure if the name is right.  But I toyed with alternatives like "make_fake_file" but found nothing that is quite as distinct from the already present "make_file."  Also, its current form holds a concrete and useful promise: that the result is something you can feed to a POST using the Django test client, and which it will then interpret as a file upload.


Jeroen
-- 
https://code.launchpad.net/~jtv/maas/make-file-upload/+merge/135886
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jtv/maas/make-file-upload into lp:maas.
=== modified file 'src/maasserver/testing/factory.py'
--- src/maasserver/testing/factory.py	2012-11-23 11:13:39 +0000
+++ src/maasserver/testing/factory.py	2012-11-23 12:29:24 +0000
@@ -60,6 +60,30 @@
 
 class Factory(maastesting.factory.Factory):
 
+    def make_file_upload(self, name=None, content=None):
+        """Create a file-like object for upload in http POST or PUT.
+
+        To upload a file using the Django test client, just include a
+        parameter that maps not to a string, but to a file upload as
+        produced by this method.
+
+        :param name: Name of the file to be uploaded.  If omitted, one will
+            be made up.
+        :type name: `unicode`
+        :param content: Contents for the uploaded file.  If omitted, some
+            contents will be made up.
+        :type content: `bytes`
+        :return: A file-like object, with the requested `content` and `name`.
+        """
+        if content is None:
+            content = self.getRandomString().encode('ascii')
+        if name is None:
+            name = self.make_name('file')
+        assert isinstance(content, bytes)
+        upload = BytesIO(content)
+        upload.name = name
+        return upload
+
     def getRandomEnum(self, enum, but_not=None):
         """Pick a random item from an enumeration class.
 
@@ -302,12 +326,8 @@
         return admin
 
     def make_file_storage(self, filename=None, content=None):
-        if filename is None:
-            filename = self.getRandomString(100)
-        if content is None:
-            content = self.getRandomString(1024).encode('ascii')
-
-        return FileStorage.objects.save_file(filename, BytesIO(content))
+        fake_file = self.make_file_upload(filename, content)
+        return FileStorage.objects.save_file(fake_file.name, fake_file)
 
     def make_oauth_header(self, **kwargs):
         """Fake an OAuth authorization header.

=== modified file 'src/metadataserver/tests/test_api.py'
--- src/metadataserver/tests/test_api.py	2012-11-14 14:34:06 +0000
+++ src/metadataserver/tests/test_api.py	2012-11-23 12:29:24 +0000
@@ -14,7 +14,6 @@
 
 from collections import namedtuple
 import httplib
-from io import BytesIO
 import json
 
 from django.conf import settings
@@ -153,9 +152,10 @@
             'status': 'OK',
         }
         params.update(kwargs)
-        for name, content in files.items():
-            params[name] = BytesIO(content)
-            params[name].name = name
+        params.update({
+            name: factory.make_file_upload(name, content)
+            for name, content in files.items()
+        })
         url = reverse('metadata-version', args=[version])
         return client.post(url, params)