Repository: oppia/oppia

Issue:
Make sure that data passed to platform storage service are always bytes
Make sure that data passed to platform storage service, more precisely to `commit` method, are always only `bytes` and not `str`. 


Discussion:

Resolving patch:
diff --git a/core/domain/fs_services.py b/core/domain/fs_services.py
--- a/core/domain/fs_services.py
+++ b/core/domain/fs_services.py
@@ -23,7 +23,7 @@
 from core.domain import image_services
 from core.platform import models
 
-from typing import Dict, List, Optional, Union
+from typing import Dict, List, Optional
 
 MYPY = False
 if MYPY: # pragma: no cover
@@ -183,7 +183,7 @@ def get(self, filepath: str) -> bytes:
     def commit(
         self,
         filepath: str,
-        raw_bytes: Union[bytes, str],
+        raw_bytes: bytes,
         mimetype: Optional[str] = None
     ) -> None:
         """Commit raw_bytes to the relevant file in the entity's assets folder.
@@ -191,7 +191,7 @@ def commit(
         Args:
             filepath: str. The path to the relevant file within the entity's
                 assets folder.
-            raw_bytes: Union[bytes, str]. The content to be stored in the file.
+            raw_bytes: bytes. The content to be stored in the file.
             mimetype: Optional[str]. The content-type of the cloud file.
         """
         # Note that textual data needs to be converted to bytes so that it can
@@ -199,8 +199,6 @@ def commit(
         # required for binary data (i.e. when mimetype is set to
         # 'application/octet-stream').
 
-        if isinstance(raw_bytes, str):
-            raw_bytes = raw_bytes.encode('utf-8')
         self._check_filepath(filepath)
         storage_services.commit(
             self._bucket_name,


Test patch:
diff --git a/core/domain/fs_services_test.py b/core/domain/fs_services_test.py
--- a/core/domain/fs_services_test.py
+++ b/core/domain/fs_services_test.py
@@ -41,7 +41,7 @@ def setUp(self) -> None:
             feconf.ENTITY_TYPE_EXPLORATION, 'eid')
 
     def test_get_and_save(self) -> None:
-        self.fs.commit('abc.png', 'file_contents')
+        self.fs.commit('abc.png', b'file_contents')
         self.assertEqual(self.fs.get('abc.png'), b'file_contents')
 
     def test_validate_entity_parameters(self) -> None:
@@ -68,7 +68,7 @@ def test_validate_entity_parameters(self) -> None:
 
     def test_delete(self) -> None:
         self.assertFalse(self.fs.isfile('abc.png'))
-        self.fs.commit('abc.png', 'file_contents')
+        self.fs.commit('abc.png', b'file_contents')
         self.assertTrue(self.fs.isfile('abc.png'))
 
         self.fs.delete('abc.png')
@@ -87,10 +87,10 @@ def test_delete(self) -> None:
     def test_listdir(self) -> None:
         self.assertItemsEqual(self.fs.listdir(''), [])  # type: ignore[no-untyped-call]
 
-        self.fs.commit('abc.png', 'file_contents')
-        self.fs.commit('abcd.png', 'file_contents_2')
-        self.fs.commit('abc/abcd.png', 'file_contents_3')
-        self.fs.commit('bcd/bcde.png', 'file_contents_4')
+        self.fs.commit('abc.png', b'file_contents')
+        self.fs.commit('abcd.png', b'file_contents_2')
+        self.fs.commit('abc/abcd.png', b'file_contents_3')
+        self.fs.commit('bcd/bcde.png', b'file_contents_4')
 
         file_names = ['abc.png', 'abc/abcd.png', 'abcd.png', 'bcd/bcde.png']
 
@@ -117,7 +117,7 @@ def test_listdir(self) -> None:
         self.assertEqual(new_fs.listdir('assets'), [])
 
     def test_copy(self) -> None:
-        self.fs.commit('abc2.png', 'file_contents')
+        self.fs.commit('abc2.png', b'file_contents')
         self.assertEqual(self.fs.listdir(''), ['abc2.png'])
         destination_fs = fs_services.GcsFileSystem(
             feconf.ENTITY_TYPE_QUESTION, 'question_id1')
@@ -147,7 +147,7 @@ def test_invalid_filepaths_are_caught(self) -> None:
             with self.assertRaisesRegex(IOError, 'Invalid filepath'):  # type: ignore[no-untyped-call]
                 fs.get(filepath)
             with self.assertRaisesRegex(IOError, 'Invalid filepath'):  # type: ignore[no-untyped-call]
-                fs.commit(filepath, 'raw_file')
+                fs.commit(filepath, b'raw_file')
             with self.assertRaisesRegex(IOError, 'Invalid filepath'):  # type: ignore[no-untyped-call]
                 fs.delete(filepath)
             with self.assertRaisesRegex(IOError, 'Invalid filepath'):  # type: ignore[no-untyped-call]