Ejemplo n.º 1
0
 def setUp(self):
     self.transient_root = tempfile.mkdtemp()
     self.persistent_root = tempfile.mkdtemp()
     self.transient_url = '/transient/'
     self.persistent_url = '/media/'
     self.file_manager = FileManager(self.transient_root,
                                     self.persistent_root,
                                     self.transient_url,
                                     self.persistent_url)
     self.env = AppEnvironment.create(file_manager=self.file_manager)
Ejemplo n.º 2
0
 def setUp(self):
     self.transient_root = tempfile.mkdtemp()
     self.persistent_root = tempfile.mkdtemp()
     self.transient_url = '/transient/'
     self.persistent_url = '/media/'
     self.file_manager = FileManager(self.transient_root,
                                     self.persistent_root,
                                     self.transient_url,
                                     self.persistent_url)
     Session = filesessionmaker(orm.sessionmaker(), self.file_manager)
     engine = create_engine('sqlite://')
     Base.metadata.create_all(engine)
     self.db = Session(bind=engine)
Ejemplo n.º 3
0
    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.ro_file_manager = ReadonlyFileManager(self.persistent_root,
                                                   self.persistent_url)
Ejemplo n.º 4
0
Archivo: app.py Proyecto: vlaght/ikcms
 def front_file_manager(self):
     return FileManager(
         transient_root=None,
         persistent_root=self.cfg.MEDIA_ROOT_FRONT,
         transient_url=None,
         persistent_url=self.cfg.MEDIA_URL,
     )
Ejemplo n.º 5
0
Archivo: app.py Proyecto: vlaght/ikcms
 def admin_file_manager(self):
     return FileManager(
         self.cfg.FORM_TEMP,
         self.cfg.MEDIA_ROOT_ADMIN,
         self.cfg.FORM_TEMP_URL,
         self.cfg.MEDIA_URL,
     )
Ejemplo n.º 6
0
 def make():
     file_manager = FileManager(self.transient_root,
                                self.persistent_root,
                                self.transient_url, self.persistent_url)
     filesessionmaker(orm.sessionmaker(),
                      self.file_manager,
                      file_managers={
                          ObjWithFile.file: file_manager,
                      })
Ejemplo n.º 7
0
 def setUp(self):
     self.transient_root = tempfile.mkdtemp()
     self.persistent_root = tempfile.mkdtemp()
     self.transient_url = "/transient/"
     self.persistent_url = "/media/"
     self.file_manager = FileManager(
         self.transient_root, self.persistent_root, self.transient_url, self.persistent_url
     )
     self.env = AppEnvironment.create(file_manager=self.file_manager)
Ejemplo n.º 8
0
    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.metadata_transient_root = tempfile.mkdtemp()
        self.metadata_persistent_root = tempfile.mkdtemp()
        self.metadata_transient_url = '/metadata/transient/'
        self.metadata_persistent_url = '/metadata/media/'

        self.metadata_file_manager = FileManager(self.metadata_transient_root,
                                                 self.metadata_persistent_root,
                                                 self.metadata_transient_url,
                                                 self.metadata_persistent_url)

        self.model_transient_root = tempfile.mkdtemp()
        self.model_persistent_root = tempfile.mkdtemp()
        self.model_transient_url = '/model/transient/'
        self.model_persistent_url = '/model/media/'

        self.model_file_manager = FileManager(self.model_transient_root,
                                              self.model_persistent_root,
                                              self.model_transient_url,
                                              self.model_persistent_url)

        Session = filesessionmaker(orm.sessionmaker(),
                                   self.file_manager,
                                   file_managers={
                                       MetadataLevelObj.metadata:
                                       self.metadata_file_manager,
                                       ModelLevelObj: self.model_file_manager,
                                   })

        engine = create_engine('sqlite://')
        Base.metadata.create_all(engine)
        CustomBase.metadata.create_all(engine)
        self.db = Session(bind=engine)
Ejemplo n.º 9
0
 def setUp(self):
     self.transient_root = tempfile.mkdtemp()
     self.persistent_root = tempfile.mkdtemp()
     self.transient_url = '/transient/'
     self.persistent_url = '/media/'
     self.file_manager = FileManager(self.transient_root,
                                     self.persistent_root,
                                     self.transient_url,
                                     self.persistent_url)
     Session = filesessionmaker(orm.sessionmaker(), self.file_manager)
     engine = create_engine('sqlite://')
     Base.metadata.create_all(engine)
     self.db = Session(bind=engine)
Ejemplo n.º 10
0
    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.ro_file_manager = ReadonlyFileManager(self.persistent_root,
                                                   self.persistent_url)
Ejemplo n.º 11
0
    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.metadata_transient_root = tempfile.mkdtemp()
        self.metadata_persistent_root = tempfile.mkdtemp()
        self.metadata_transient_url = '/metadata/transient/'
        self.metadata_persistent_url = '/metadata/media/'

        self.metadata_file_manager = FileManager(self.metadata_transient_root,
                                                 self.metadata_persistent_root,
                                                 self.metadata_transient_url,
                                                 self.metadata_persistent_url)

        self.model_transient_root = tempfile.mkdtemp()
        self.model_persistent_root = tempfile.mkdtemp()
        self.model_transient_url = '/model/transient/'
        self.model_persistent_url = '/model/media/'

        self.model_file_manager = FileManager(self.model_transient_root,
                                              self.model_persistent_root,
                                              self.model_transient_url,
                                              self.model_persistent_url)


        Session = filesessionmaker(orm.sessionmaker(), self.file_manager,
            file_managers={
                MetadataLevelObj.metadata: self.metadata_file_manager,
                ModelLevelObj: self.model_file_manager,
            })

        engine = create_engine('sqlite://')
        Base.metadata.create_all(engine)
        CustomBase.metadata.create_all(engine)
        self.db = Session(bind=engine)
Ejemplo n.º 12
0
class SqlaFilesTests(unittest.TestCase):

    Model = ObjWithFile

    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.metadata_transient_root = tempfile.mkdtemp()
        self.metadata_persistent_root = tempfile.mkdtemp()
        self.metadata_transient_url = '/metadata/transient/'
        self.metadata_persistent_url = '/metadata/media/'

        self.metadata_file_manager = FileManager(self.metadata_transient_root,
                                                 self.metadata_persistent_root,
                                                 self.metadata_transient_url,
                                                 self.metadata_persistent_url)

        self.model_transient_root = tempfile.mkdtemp()
        self.model_persistent_root = tempfile.mkdtemp()
        self.model_transient_url = '/model/transient/'
        self.model_persistent_url = '/model/media/'

        self.model_file_manager = FileManager(self.model_transient_root,
                                              self.model_persistent_root,
                                              self.model_transient_url,
                                              self.model_persistent_url)


        Session = filesessionmaker(orm.sessionmaker(), self.file_manager,
            file_managers={
                MetadataLevelObj.metadata: self.metadata_file_manager,
                ModelLevelObj: self.model_file_manager,
            })

        engine = create_engine('sqlite://')
        Base.metadata.create_all(engine)
        CustomBase.metadata.create_all(engine)
        self.db = Session(bind=engine)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)
        shutil.rmtree(self.metadata_transient_root)
        shutil.rmtree(self.metadata_persistent_root)
        shutil.rmtree(self.model_transient_root)
        shutil.rmtree(self.model_persistent_root)

    def test_session(self):
        self.assertTrue(hasattr(self.db, 'file_manager'))
        self.assertIsInstance(self.db.file_manager, FileManager)

    def test_find_file_manager(self):
        self.assertTrue(hasattr(self.db, 'find_file_manager'))

        self.assertEqual(self.db.find_file_manager(self.Model.file),
                         self.file_manager)

        self.assertEqual(self.db.find_file_manager(ModelLevelObj.file),
                         self.model_file_manager)

        self.assertEqual(self.db.find_file_manager(MetadataLevelObj.file),
                         self.metadata_file_manager)

    def test_create(self):
        obj = self.Model()

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.add(obj)
        self.db.commit()
        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test')

    def test_create_metadata_obj(self):
        metadata_obj = MetadataLevelObj()
        metadata_filemanager = self.db.find_file_manager(metadata_obj)
        metadata_file = metadata_filemanager.new_transient()
        with open(metadata_file.path, 'wb') as fp:
            fp.write(b'test')
        metadata_obj.file = metadata_file

        self.assertTrue(metadata_obj.file.path.startswith(self.metadata_transient_root))

        self.db.add(metadata_obj)
        self.db.commit()

        self.assertTrue(metadata_obj.file.path.startswith(self.metadata_persistent_root))

    def test_create_model_obj(self):
        model_obj = ModelLevelObj()
        model_filemanager = self.db.find_file_manager(model_obj)
        model_file = model_filemanager.new_transient()
        with open(model_file.path, 'wb') as fp:
            fp.write(b'test')
        model_obj.file = model_file

        self.assertTrue(model_obj.file.path.startswith(self.model_transient_root))

        self.db.add(model_obj)
        self.db.commit()

        self.assertTrue(model_obj.file.path.startswith(self.model_persistent_root))

    def test_update_none2file(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.commit()

        # cleanup self.Model.file._states.items() to get the result
        # from scratch, not from cache
        obj_id = obj.id
        obj = None
        gc.collect()
        obj = self.db.query(self.Model).get(obj_id)

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test')
        self.assertEqual(obj.file.size, 4)
        self.assertEqual(obj.file_size, 4)

    def test_update_file2none(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        self.db.commit()

        pf = obj.file

        obj.file = None
        self.assertIsNone(obj.file_name)
        self.assertTrue(os.path.exists(pf.path))
        self.assertEqual(obj.file_size, 4)
        self.db.commit()

        self.assertFalse(os.path.exists(pf.path))
        self.assertEqual(obj.file_size, None)

    def test_update_file2file(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')
        self.db.add(obj)
        self.db.commit()
        pf1 = obj.file

        self.assertEqual(obj.file_size, 5)

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test22')
        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.commit()

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertFalse(os.path.exists(pf1.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test22')
        self.assertEqual(obj.file_size, 6)

    def test_update_file2self(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')
        self.db.add(obj)
        self.db.commit()
        pf1 = obj.file

        obj.file = self.file_manager.get_persistent(obj.file.name)
        self.db.commit()

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertTrue(os.path.exists(obj.file.path))
        self.assertEqual(pf1.path, obj.file.path)

        # XXX for test coverage
        #     have no idea what extra check can be performed
        obj.file = obj.file
        self.assertTrue(os.path.exists(obj.file.path))
        self.assertEqual(pf1.path, obj.file.path)

    @unittest.expectedFailure
    def test_update_file2file_not_random(self):
        obj = self.Model()

        obj.file_by_id = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')
        self.db.add(obj)
        self.db.commit()
        self.assertEqual(obj.file_by_id_name,
                         self.Model.file_by_id.name_template.format(item=obj))
        pf1 = obj.file_by_id

        obj.file_by_id = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test2')
        self.assertIsInstance(obj.file_by_id, TransientFile)
        self.assertIsNotNone(obj.file_by_id_name)
        self.db.commit()

        self.assertIsInstance(obj.file_by_id, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertFalse(os.path.exists(pf1.path))
        self.assertTrue(os.path.isfile(obj.file_by_id.path))
        self.assertEqual(open(obj.file_by_id.path).read(), 'test2')

    @unittest.expectedFailure
    def test_update_random_collision(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')

        persistent = self.file_manager.get_persistent(obj.file_name)
        dirname = os.path.dirname(persistent.path)
        if not os.path.isdir(dirname):
            os.makedirs(dirname)
        with open(persistent.path, 'wb') as fp:
            fp.write(b'taken')

        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.commit()
        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test')
        self.assertNotEqual(persistent.path, obj.file.path)
        self.assertEqual(open(persistent.path).read(), 'taken')

    def test_update_none2persistent(self):
        f = self.file_manager.get_persistent('persistent.txt')
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')

        obj = self.Model()
        obj.file = f
        self.db.add(obj)
        self.db.commit()

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertTrue(os.path.exists(obj.file.path))
        self.assertEqual(obj.file.name, 'persistent.txt')

    def test_delete(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        self.db.commit()
        pf = obj.file
        self.db.delete(obj)
        self.db.commit()
        self.assertFalse(os.path.exists(pf.path))

    def test_set_invalid(self):
        obj = self.Model()
        self.assertRaises(ValueError, lambda: setattr(obj, 'file', 'test'))

    def test_cached_lost(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.commit()

        os.unlink(obj.file.path)

        self.assertEqual(obj.file.size, 4)
        self.assertEqual(obj.file_size, 4)

        del obj.file.size
        self.assertEqual(obj.file.size, None)

    def test_file2none_lost(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        self.db.commit()

        os.unlink(obj.file.path)
        obj.file = None
        self.db.commit()

        self.assertEqual(obj.file_size, None)

    def test_file_manager_for_field(self):
        def make():
            file_manager = FileManager(self.transient_root,
                                       self.persistent_root,
                                       self.transient_url,
                                       self.persistent_url)
            filesessionmaker(orm.sessionmaker(), self.file_manager,
                file_managers={
                    ObjWithFile.file: file_manager,
                })

        self.assertRaises(NotImplementedError, make)

    def test_detached_object(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.commit()
        # cleanup self.Model.file._states.items() to get the result
        # from scratch, not from cache
        obj_id = obj.id
        obj = None
        gc.collect()
        obj = self.db.query(self.Model).get(obj_id)

        with mock.patch.object(iktomi.db.sqla.files,
                               'object_session', return_value=None):
            with self.assertRaises(RuntimeError) as exc:
                obj.file
            self.assertEqual('Object is detached', str(exc.exception))

    def test_absent_file_manager(self):
        obj = self.Model()
        del self.db.file_manager
        self.db.add(obj)
        self.db.commit()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.commit()
        # cleanup self.Model.file._states.items() to get the result
        # from scratch, not from cache
        obj_id = obj.id
        obj = None
        gc.collect()
        obj = self.db.query(self.Model).get(obj_id)

        with self.assertRaises(RuntimeError) as exc:
            obj.file
        self.assertEqual("Session doesn't support file management", str(exc.exception))
Ejemplo n.º 13
0
class SqlaImagesTests(unittest.TestCase):
    def setUp(self):
        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'
        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)
        Session = filesessionmaker(orm.sessionmaker(), self.file_manager)
        engine = create_engine('sqlite://')
        Base.metadata.create_all(engine)
        self.db = Session(bind=engine)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)

    def test_create(self):
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient('.gif')
        _create_image(f.path)

        def return_image(image, filter):
            # asserting that filter was called
            self.assertEqual(filter, ImageFilter.BLUR)
            return image

        with mock.patch('PIL.Image.Image.filter',
                        side_effect=return_image,
                        autospec=True):
            self.db.add(obj)
            self.db.commit()

            self.assertIsInstance(obj.image, PersistentFile)
            self.assertIsInstance(obj.thumb, PersistentFile)
            self.assertIsInstance(obj.thumb_filter, PersistentFile)
            self.assertIsInstance(obj.thumb_optimize, PersistentFile)

            img = Image.open(obj.image.path)
            self.assertEqual(img.size, (200, 200))
            self.assertEqual(obj.image.width, img.width)
            self.assertEqual(obj.image.height, img.height)

            thumb = Image.open(obj.thumb.path)
            self.assertEqual(thumb.size, (100, 100))
            self.assertEqual(obj.thumb.height, thumb.height)
            self.assertEqual(obj.thumb.width, thumb.width)
            pixels = thumb.load()
            self.assertEqual(pixels[50, 50], (186, 186, 186))

            self.assertLessEqual(
                os.stat(obj.thumb_optimize.path).st_size,
                os.stat(obj.thumb.path).st_size)

    def test_no_original_image(self):
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient()
        _create_image(f.path, format='PNG')

        warn = []
        with mock.patch('os.path.isfile', return_value=False):
            with mock.patch(
                    'logging.Logger.warn',
                    side_effect=lambda m, *args: warn.append(m % args)):
                self.db.add(obj)
                self.db.commit()

        self.assertEqual(len(warn), 3)
        self.assertEqual(warn[0], warn[1])
        self.assertEqual(warn[1], warn[2])
        self.assertIn("Original file is absent", warn[0])
        self.assertIn(obj.image.path, warn[0])

    def test_no_ext(self):
        # test for extraction image extension from image instead of file path
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient()
        _create_image(f.path, format='PNG')
        self.db.add(obj)
        self.db.commit()
        self.assertIsInstance(obj.image, PersistentFile)
        self.assertTrue(obj.image.path.endswith('.png'))

    def test_no_size(self):
        obj = ObjWithImage()
        obj.icon = f = self.file_manager.new_transient('.gif')
        _create_image(f.path, 200, 300)
        self.db.add(obj)
        self.db.commit()

        self.assertIsNone(obj.image)
        self.assertIsNone(obj.thumb)
        self.assertIsInstance(obj.icon, PersistentFile)

        img = Image.open(obj.icon.path)
        self.assertEqual(img.size, (200, 300))

    def test_no_img(self):
        obj = ObjWithImage()
        self.db.add(obj)
        self.db.commit()

        self.assertEqual(obj.image, None)
        self.assertEqual(obj.thumb, None)
        self.assertEqual(obj.icon, None)

    def test_update(self):
        obj = ObjWithImage()
        self.db.add(obj)
        self.db.commit()

        obj.image = f = self.file_manager.new_transient('.gif')
        _create_image(f.path)
        self.db.commit()

        self.assertIsInstance(obj.image, PersistentFile)
        self.assertIsInstance(obj.thumb, PersistentFile)

        img = Image.open(obj.image.path)
        self.assertEqual(img.size, (200, 200))

        thumb = Image.open(obj.thumb.path)
        self.assertEqual(thumb.size, (100, 100))

    def test_invalid(self):
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient('.gif')
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        with self.assertRaises(IOError):
            self.db.commit()

    def test_fill_without_size(self):
        with self.assertRaises(AssertionError):

            class Test(Base):

                id = Column(Integer, primary_key=True)
                image_name = Column(VARBINARY(250))
                image = ImageProperty(image_name,
                                      name_template='image/{random}')

                thumb_name = Column(VARBINARY(250))
                thumb = ImageProperty(thumb_name,
                                      name_template='thumb/{random}',
                                      fill_from='image')
Ejemplo n.º 14
0
class SqlaFilesTests(unittest.TestCase):

    Model = ObjWithFile

    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.metadata_transient_root = tempfile.mkdtemp()
        self.metadata_persistent_root = tempfile.mkdtemp()
        self.metadata_transient_url = '/metadata/transient/'
        self.metadata_persistent_url = '/metadata/media/'

        self.metadata_file_manager = FileManager(self.metadata_transient_root,
                                                 self.metadata_persistent_root,
                                                 self.metadata_transient_url,
                                                 self.metadata_persistent_url)

        self.model_transient_root = tempfile.mkdtemp()
        self.model_persistent_root = tempfile.mkdtemp()
        self.model_transient_url = '/model/transient/'
        self.model_persistent_url = '/model/media/'

        self.model_file_manager = FileManager(self.model_transient_root,
                                              self.model_persistent_root,
                                              self.model_transient_url,
                                              self.model_persistent_url)

        Session = filesessionmaker(orm.sessionmaker(),
                                   self.file_manager,
                                   file_managers={
                                       MetadataLevelObj.metadata:
                                       self.metadata_file_manager,
                                       ModelLevelObj: self.model_file_manager,
                                   })

        engine = create_engine('sqlite://')
        Base.metadata.create_all(engine)
        CustomBase.metadata.create_all(engine)
        self.db = Session(bind=engine)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)
        shutil.rmtree(self.metadata_transient_root)
        shutil.rmtree(self.metadata_persistent_root)
        shutil.rmtree(self.model_transient_root)
        shutil.rmtree(self.model_persistent_root)

    def test_session(self):
        self.assertTrue(hasattr(self.db, 'file_manager'))
        self.assertIsInstance(self.db.file_manager, FileManager)

    def test_find_file_manager(self):
        self.assertTrue(hasattr(self.db, 'find_file_manager'))

        self.assertEqual(self.db.find_file_manager(self.Model.file),
                         self.file_manager)

        self.assertEqual(self.db.find_file_manager(ModelLevelObj.file),
                         self.model_file_manager)

        self.assertEqual(self.db.find_file_manager(MetadataLevelObj.file),
                         self.metadata_file_manager)

    def test_create(self):
        obj = self.Model()

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.add(obj)
        self.db.commit()
        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test')

    def test_create_metadata_obj(self):
        metadata_obj = MetadataLevelObj()
        metadata_filemanager = self.db.find_file_manager(metadata_obj)
        metadata_file = metadata_filemanager.new_transient()
        with open(metadata_file.path, 'wb') as fp:
            fp.write(b'test')
        metadata_obj.file = metadata_file

        self.assertTrue(
            metadata_obj.file.path.startswith(self.metadata_transient_root))

        self.db.add(metadata_obj)
        self.db.commit()

        self.assertTrue(
            metadata_obj.file.path.startswith(self.metadata_persistent_root))

    def test_create_model_obj(self):
        model_obj = ModelLevelObj()
        model_filemanager = self.db.find_file_manager(model_obj)
        model_file = model_filemanager.new_transient()
        with open(model_file.path, 'wb') as fp:
            fp.write(b'test')
        model_obj.file = model_file

        self.assertTrue(
            model_obj.file.path.startswith(self.model_transient_root))

        self.db.add(model_obj)
        self.db.commit()

        self.assertTrue(
            model_obj.file.path.startswith(self.model_persistent_root))

    def test_update_none2file(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.commit()

        # cleanup self.Model.file._states.items() to get the result
        # from scratch, not from cache
        obj_id = obj.id
        obj = None
        gc.collect()
        obj = self.db.query(self.Model).get(obj_id)

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test')
        self.assertEqual(obj.file.size, 4)
        self.assertEqual(obj.file_size, 4)

    def test_update_file2none(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        self.db.commit()

        pf = obj.file

        obj.file = None
        self.assertIsNone(obj.file_name)
        self.assertTrue(os.path.exists(pf.path))
        self.assertEqual(obj.file_size, 4)
        self.db.commit()

        self.assertFalse(os.path.exists(pf.path))
        self.assertEqual(obj.file_size, None)

    def test_update_file2file(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')
        self.db.add(obj)
        self.db.commit()
        pf1 = obj.file

        self.assertEqual(obj.file_size, 5)

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test22')
        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.commit()

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertFalse(os.path.exists(pf1.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test22')
        self.assertEqual(obj.file_size, 6)

    def test_update_file2self(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')
        self.db.add(obj)
        self.db.commit()
        pf1 = obj.file

        obj.file = self.file_manager.get_persistent(obj.file.name)
        self.db.commit()

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertTrue(os.path.exists(obj.file.path))
        self.assertEqual(pf1.path, obj.file.path)

        # XXX for test coverage
        #     have no idea what extra check can be performed
        obj.file = obj.file
        self.assertTrue(os.path.exists(obj.file.path))
        self.assertEqual(pf1.path, obj.file.path)

    @unittest.expectedFailure
    def test_update_file2file_not_random(self):
        obj = self.Model()

        obj.file_by_id = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')
        self.db.add(obj)
        self.db.commit()
        self.assertEqual(obj.file_by_id_name,
                         self.Model.file_by_id.name_template.format(item=obj))
        pf1 = obj.file_by_id

        obj.file_by_id = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test2')
        self.assertIsInstance(obj.file_by_id, TransientFile)
        self.assertIsNotNone(obj.file_by_id_name)
        self.db.commit()

        self.assertIsInstance(obj.file_by_id, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertFalse(os.path.exists(pf1.path))
        self.assertTrue(os.path.isfile(obj.file_by_id.path))
        self.assertEqual(open(obj.file_by_id.path).read(), 'test2')

    @unittest.expectedFailure
    def test_update_random_collision(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()

        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')

        persistent = self.file_manager.get_persistent(obj.file_name)
        dirname = os.path.dirname(persistent.path)
        if not os.path.isdir(dirname):
            os.makedirs(dirname)
        with open(persistent.path, 'wb') as fp:
            fp.write(b'taken')

        self.assertIsInstance(obj.file, TransientFile)
        self.assertIsNotNone(obj.file_name)
        self.db.commit()
        self.assertIsInstance(obj.file, PersistentFile)
        self.assertFalse(os.path.exists(f.path))
        self.assertTrue(os.path.isfile(obj.file.path))
        self.assertEqual(open(obj.file.path).read(), 'test')
        self.assertNotEqual(persistent.path, obj.file.path)
        self.assertEqual(open(persistent.path).read(), 'taken')

    def test_update_none2persistent(self):
        f = self.file_manager.get_persistent('persistent.txt')
        with open(f.path, 'wb') as fp:
            fp.write(b'test1')

        obj = self.Model()
        obj.file = f
        self.db.add(obj)
        self.db.commit()

        self.assertIsInstance(obj.file, PersistentFile)
        self.assertTrue(os.path.exists(obj.file.path))
        self.assertEqual(obj.file.name, 'persistent.txt')

    def test_delete(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        self.db.commit()
        pf = obj.file
        self.db.delete(obj)
        self.db.commit()
        self.assertFalse(os.path.exists(pf.path))

    def test_set_invalid(self):
        obj = self.Model()
        self.assertRaises(ValueError, lambda: setattr(obj, 'file', 'test'))

    def test_cached_lost(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.commit()

        os.unlink(obj.file.path)

        self.assertEqual(obj.file.size, 4)
        self.assertEqual(obj.file_size, 4)

        del obj.file.size
        self.assertEqual(obj.file.size, None)

    def test_file2none_lost(self):
        obj = self.Model()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        self.db.commit()

        os.unlink(obj.file.path)
        obj.file = None
        self.db.commit()

        self.assertEqual(obj.file_size, None)

    def test_file_manager_for_field(self):
        def make():
            file_manager = FileManager(self.transient_root,
                                       self.persistent_root,
                                       self.transient_url, self.persistent_url)
            filesessionmaker(orm.sessionmaker(),
                             self.file_manager,
                             file_managers={
                                 ObjWithFile.file: file_manager,
                             })

        self.assertRaises(NotImplementedError, make)

    def test_detached_object(self):
        obj = self.Model()
        self.db.add(obj)
        self.db.commit()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.commit()
        # cleanup self.Model.file._states.items() to get the result
        # from scratch, not from cache
        obj_id = obj.id
        obj = None
        gc.collect()
        obj = self.db.query(self.Model).get(obj_id)

        with mock.patch.object(iktomi.db.sqla.files,
                               'object_session',
                               return_value=None):
            with self.assertRaises(RuntimeError) as exc:
                obj.file
            self.assertEqual('Object is detached', str(exc.exception))

    def test_absent_file_manager(self):
        obj = self.Model()
        del self.db.file_manager
        self.db.add(obj)
        self.db.commit()
        obj.file = f = self.file_manager.new_transient()
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.commit()
        # cleanup self.Model.file._states.items() to get the result
        # from scratch, not from cache
        obj_id = obj.id
        obj = None
        gc.collect()
        obj = self.db.query(self.Model).get(obj_id)

        with self.assertRaises(RuntimeError) as exc:
            obj.file
        self.assertEqual("Session doesn't support file management",
                         str(exc.exception))
Ejemplo n.º 15
0
class SqlaImagesTests(unittest.TestCase):

    def setUp(self):
        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'
        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)
        Session = filesessionmaker(orm.sessionmaker(), self.file_manager)
        engine = create_engine('sqlite://')
        Base.metadata.create_all(engine)
        self.db = Session(bind=engine)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)

    def test_create(self):
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient('.gif')
        _create_image(f.path)

        def return_image(image, filter):
            # asserting that filter was called
            self.assertEqual(filter, ImageFilter.BLUR)
            return image

        with mock.patch('PIL.Image.Image.filter',
                        side_effect=return_image,
                        autospec=True):
            self.db.add(obj)
            self.db.commit()

            self.assertIsInstance(obj.image, PersistentFile)
            self.assertIsInstance(obj.thumb, PersistentFile)
            self.assertIsInstance(obj.thumb_filter, PersistentFile)
            self.assertIsInstance(obj.thumb_optimize, PersistentFile)

            img = Image.open(obj.image.path)
            self.assertEqual(img.size, (200, 200))
            self.assertEqual(obj.image.width, img.width)
            self.assertEqual(obj.image.height, img.height)

            thumb = Image.open(obj.thumb.path)
            self.assertEqual(thumb.size, (100, 100))
            self.assertEqual(obj.thumb.height, thumb.height)
            self.assertEqual(obj.thumb.width, thumb.width)
            pixels = thumb.load()
            self.assertEqual(pixels[50, 50], (186, 186, 186))

            self.assertLessEqual(os.stat(obj.thumb_optimize.path).st_size,
                                 os.stat(obj.thumb.path).st_size)

    def test_no_original_image(self):
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient()
        _create_image(f.path, format='PNG')

        warn = []
        with mock.patch('os.path.isfile', return_value=False):
            with mock.patch('logging.Logger.warn',
                            side_effect=lambda m, *args: warn.append(m % args)):
                self.db.add(obj)
                self.db.commit()

        self.assertEqual(len(warn), 3)
        self.assertEqual(warn[0], warn[1])
        self.assertEqual(warn[1], warn[2])
        self.assertIn("Original file is absent", warn[0])
        self.assertIn(obj.image.path, warn[0])

    def test_no_ext(self):
        # test for extraction image extension from image instead of file path
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient()
        _create_image(f.path, format='PNG')
        self.db.add(obj)
        self.db.commit()
        self.assertIsInstance(obj.image, PersistentFile)
        self.assertTrue(obj.image.path.endswith('.png'))

    def test_no_size(self):
        obj = ObjWithImage()
        obj.icon = f = self.file_manager.new_transient('.gif')
        _create_image(f.path, 200, 300)
        self.db.add(obj)
        self.db.commit()

        self.assertIsNone(obj.image)
        self.assertIsNone(obj.thumb)
        self.assertIsInstance(obj.icon, PersistentFile)

        img = Image.open(obj.icon.path)
        self.assertEqual(img.size, (200, 300))

    def test_no_img(self):
        obj = ObjWithImage()
        self.db.add(obj)
        self.db.commit()

        self.assertEqual(obj.image, None)
        self.assertEqual(obj.thumb, None)
        self.assertEqual(obj.icon, None)

    def test_update(self):
        obj = ObjWithImage()
        self.db.add(obj)
        self.db.commit()

        obj.image = f = self.file_manager.new_transient('.gif')
        _create_image(f.path)
        self.db.commit()

        self.assertIsInstance(obj.image, PersistentFile)
        self.assertIsInstance(obj.thumb, PersistentFile)

        img = Image.open(obj.image.path)
        self.assertEqual(img.size, (200, 200))

        thumb = Image.open(obj.thumb.path)
        self.assertEqual(thumb.size, (100, 100))

    def test_invalid(self):
        obj = ObjWithImage()
        obj.image = f = self.file_manager.new_transient('.gif')
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        self.db.add(obj)
        with self.assertRaises(IOError):
            self.db.commit()

    def test_fill_without_size(self):
        with self.assertRaises(AssertionError):
            class Test(Base):

                id = Column(Integer, primary_key=True)
                image_name = Column(VARBINARY(250))
                image = ImageProperty(image_name,
                                      name_template='image/{random}')

                thumb_name = Column(VARBINARY(250))
                thumb = ImageProperty(thumb_name,
                                      name_template='thumb/{random}',
                                      fill_from='image')
Ejemplo n.º 16
0
class FormFilesTests(unittest.TestCase):

    def setUp(self):
        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'
        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)
        self.env = AppEnvironment.create(file_manager=self.file_manager)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)

    def _create_persistent(self):
        f = self.file_manager.get_persistent('test.txt')
        with open(f.path, 'wb') as fp:
            fp.write(b'test')
        return f

    def _create_transient(self, content, original_name='test.txt'):
        f = self.file_manager.new_transient(ext=os.path.splitext(original_name)[1])
        with open(f.path, 'wb') as fp:
            fp.write(content)
        return f

    def _create_fs(self, mimetype, content, filename='uploaded.txt', name="file"):
        # http://stackoverflow.com/questions/12032807/how-to-create-cgi-fieldstorage-for-testing-purposes
        content = content.encode('utf-8')
        m = {u'content-disposition': u'form-data; name="{}"; filename="{}"'.format(name, filename),
             u'content-length': len(content),
             u'content-type': mimetype}
        environ = {'REQUEST_METHOD': 'POST'}
        fp = BytesIO(content)
        return cgi.FieldStorage(fp=fp, headers=m, environ=environ)

    def test_none2empty(self):
        form = FormWithFile(self.env)
        form.accept(MultiDict({'file.file': None,
                               'file.original_name': '',
                               'file.transient_name': '',
                               'file.mode': 'empty',}))
        data = form.python_data
        self.assertEqual(data['file'], None)

    def test_transient2empty(self):
        transient = self._create_transient(b'transient1')
        form = FormWithFile(self.env)
        form.accept(MultiDict({'file.file': None,
                               'file.original_name': 'test.txt',
                               'file.transient_name': transient.name,
                               'file.mode': 'transient',}))
        data = form.python_data
        self.assertIsInstance(data['file'], TransientFile)
        self.assertEqual(data['file'].name, transient.name)

    def test_transient_lost(self):
        form = FormWithFile(self.env)
        form.accept(MultiDict({'file.file': None,
                               'file.original_name': 'test.txt',
                               'file.transient_name': 'lost.txt',
                               'file.mode': 'transient',}))
        self.assertIn('file', form.errors)

    def test_transient_invalid(self):
        illegal = ['more/../../../lost.txt',
                   '../pass',
                   '/etc/pass',
                   '..',
                   '~',
                   ]
        for filename in illegal:
            form = FormWithFile(self.env)
            form.accept(MultiDict({'file.file': None,
                                   'file.original_name': 'test.txt',
                                   'file.transient_name': filename,
                                   'file.mode': 'transient',}))
            self.assertIn('file.transient_name', form.errors,
                          'file name is not filtered: %s' % filename)

    def test_file2empty(self):
        form = FormWithFile(self.env)
        fs = self._create_fs('text', 'file-content', 'filename.ttt')
        form.accept(MultiDict({'file.file': fs,
                               'file.mode': 'existing',}))
        data = form.python_data
        self.assertIsInstance(data['file'], TransientFile)
        self.assertEqual(os.path.splitext(data['file'].name)[1],
                         '.ttt')
        with open(data['file'].path) as fp:
            self.assertEqual(fp.read(), 'file-content')

    def test_none2persistent(self):
        persistent = self._create_persistent()
        form = FormWithFile(self.env, initial={'file': persistent})
        form.accept(MultiDict({'file.file': None,
                               'file.original_name': '',
                               'file.transient_name': '',
                               'file.mode': 'existing',}))
        data = form.python_data
        self.assertEqual(data['file'], persistent)

    def test_empty2persistent(self):
        persistent = self._create_persistent()
        form = FormWithFile(self.env, initial={'file': persistent})
        form.accept(MultiDict({'file.file': None,
                               'file.original_name': '',
                               'file.transient_name': '',
                               'file.mode': 'empty',}))
        data = form.python_data
        self.assertEqual(data['file'], None)

    def test_transient2persistent(self):
        persistent = self._create_persistent()
        transient = self._create_transient(b'transient1')
        form = FormWithFile(self.env, initial={'file': persistent})
        form.accept(MultiDict({'file.file': None,
                               'file.original_name': 'test.txt',
                               'file.transient_name': transient.name,
                               'file.mode': 'transient',}))
        data = form.python_data
        self.assertIsInstance(data['file'], TransientFile)
        self.assertEqual(data['file'].name, transient.name)

    def test_file2persistent(self):
        persistent = self._create_persistent()
        form = FormWithFile(self.env, initial={'file': persistent})
        fs = self._create_fs('text', 'file-content', 'filename.ttt')
        form.accept(MultiDict({'file.file': fs,
                               'file.mode': 'existing',}))
        data = form.python_data
        self.assertIsInstance(data['file'], TransientFile)
        self.assertEqual(os.path.splitext(data['file'].name)[1],
                         '.ttt')
        with open(data['file'].path) as fp:
            self.assertEqual(fp.read(), 'file-content')
Ejemplo n.º 17
0
class SqlaFilesTests(unittest.TestCase):

    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.ro_file_manager = ReadonlyFileManager(self.persistent_root,
                                                   self.persistent_url)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)


    def test_file_attrs(self):
        with open(os.path.join(self.transient_root, 'testfile.html'), 'w') as f:
            f.write('<html></html>')

        fl = TransientFile(self.transient_root, 'testfile.html', self.file_manager)

        self.assertEqual(fl.mimetype, 'text/html')
        self.assertEqual(fl.size, 13)
        self.assertEqual(fl.file_name, 'testfile.html')
        self.assertEqual(fl.ext, '.html')
        self.assertEqual(fl.url, '/transient/testfile.html')

    def test_repr(self):
        with open(os.path.join(self.transient_root, 'testfile.html'), 'w') as f:
            f.write('<html></html>')

        fl = TransientFile(self.transient_root, 'testfile.html', self.file_manager)
        represent = repr(fl)
        self.assertIn('TransientFile', represent)
        self.assertIn('testfile.html', represent)

    def test_no_file(self):
        fl = PersistentFile(self.persistent_root, 'testfile2.html', self.file_manager)

        self.assertEqual(fl.mimetype, 'text/html')
        self.assertEqual(fl.size, None)
        self.assertEqual(fl.file_name, 'testfile2.html')
        self.assertEqual(fl.ext, '.html')
        self.assertEqual(fl.url, '/media/testfile2.html')

    def test_delete(self):
        with open(os.path.join(self.transient_root, 'delfile1.html'), 'w') as f:
            f.write('<html></html>')

        fl1 = TransientFile(self.transient_root, 'delfile1.html', self.file_manager)
        fl2 = TransientFile(self.transient_root, 'delfile2.html', self.file_manager)

        self.assertTrue(os.path.isfile(fl1.path))
        self.assertFalse(os.path.isfile(fl2.path))

        log = []
        with patch('logging.Logger.warning',
                   side_effect=lambda m: log.append(m)):
            self.file_manager.delete(fl1)
            self.file_manager.delete(fl2)

        self.assertFalse(os.path.isfile(fl1.path))
        self.assertFalse(os.path.isfile(fl2.path))
        self.assertIn('delfile2.html', log[0])
        self.assertIn('was not found', log[0])

    def test_delete_error(self):
        path = os.path.join(self.transient_root, 'delfile1.html')
        with open(path, 'w') as f:
            f.write('<html></html>')

        fl1 = TransientFile(self.transient_root, 'delfile1.html', self.file_manager)
        self.assertTrue(os.path.isfile(fl1.path))
        log = []

        # mocking permission error
        def unlink_error(path):
            raise OSError("[Errno 13] Permission denied: {}".format(path))

        with patch('logging.Logger.error',
                   side_effect=lambda m: log.append(m)):
            with patch('os.unlink', side_effect=unlink_error):
                with self.assertRaises(OSError) as exc:
                    self.file_manager.delete(fl1)

    def test_readonly_file_manager(self):
        get_persistent = self.ro_file_manager.get_persistent

        fl = get_persistent('name.txt')
        self.assertIsInstance(fl, PersistentFile)
        self.assertEqual(self.ro_file_manager.get_persistent_url(fl), '/media/name.txt')


        self.assertRaises(ValueError, get_persistent, 'something/../name.txt')
        self.assertRaises(ValueError, get_persistent, '/something/name.txt')
        self.assertRaises(ValueError, get_persistent, '~/something/name.txt')


    def test_create_transient(self):
        req_fl = os.path.join(self.transient_root, 'xxxxx.html')
        with open(req_fl, 'w') as f:
            f.write('<html></html>' * 10000)

        with open(req_fl) as f:
            request = Request.blank('/', POST={'file': ('big.html', f)})

            fl = self.file_manager.create_transient(request.POST['file'].file,
                                                    request.POST['file'].name)

        self.assertEqual(fl.size, 130000)

        # XXX this is a test of strange behaviour when browser does not
        #     pass Content-Length header when uploading a file in POST body
        #     See iktomi.cms.ajax_file_upload
        #     There is no obvious way to simulate this behaviour except
        #     hardcoded length variable.
        with open(req_fl, 'w') as f:
            f.write('<html></html>' * 10000)

        with open(req_fl) as f:
            request = Request.blank('/', POST={'file': ('big.html', f)})

            fl = self.file_manager.create_transient(request.POST['file'].file,
                                                    request.POST['file'].name,
                                                    length=130000)

        self.assertEqual(fl.size, 130000)

    def test_create_transient_dir(self):
        req_fl = os.path.join(self.transient_root, 'xxxxx.html')
        with open(req_fl, 'w') as f:
            f.write('<html></html>' * 10000)

        nonexistent_dir = os.path.join(self.transient_root,
                                       "non/existent/dir")

        self.assertFalse(os.path.exists(nonexistent_dir))

        self.file_manager.transient_root = nonexistent_dir

        with open(req_fl) as f:
            request = Request.blank('/', POST={'file': ('big.html', f)})
            fl = self.file_manager.create_transient(request.POST['file'].file,
                                                    request.POST['file'].name)

        self.assertEqual(fl.path, os.path.join(nonexistent_dir, fl.name))
        self.assertEqual(fl.size, 130000)

    def test_create_symlink(self):
        stream1 = BytesIO(b'hello')
        stream2 = BytesIO(b'world')

        source1 = self.file_manager.create_transient(stream1, 'hello.txt')
        source2 = self.file_manager.create_transient(stream2, 'world.txt')

        target_file_dir = os.path.join(self.persistent_root, 'dir/subdir')
        target_file = PersistentFile(target_file_dir, 'target.txt')
        target_file_path = os.path.join(target_file_dir, 'target.txt')
        self.assertFalse(os.path.isfile(target_file_path))

        self.file_manager.create_symlink(source1, target_file)

        self.assertTrue(os.path.isfile(target_file_path))

        with open(target_file_path) as f:
            self.assertEqual('hello', f.read())

        self.file_manager.create_symlink(source2, target_file)

        self.assertTrue(os.path.isfile(target_file_path))

        with open(target_file_path) as f:
            self.assertEqual('world', f.read())
Ejemplo n.º 18
0
class SqlaFilesTests(unittest.TestCase):
    def setUp(self):

        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = '/transient/'
        self.persistent_url = '/media/'

        self.file_manager = FileManager(self.transient_root,
                                        self.persistent_root,
                                        self.transient_url,
                                        self.persistent_url)

        self.ro_file_manager = ReadonlyFileManager(self.persistent_root,
                                                   self.persistent_url)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)

    def test_file_attrs(self):
        with open(os.path.join(self.transient_root, 'testfile.html'),
                  'w') as f:
            f.write('<html></html>')

        fl = TransientFile(self.transient_root, 'testfile.html',
                           self.file_manager)

        self.assertEqual(fl.mimetype, 'text/html')
        self.assertEqual(fl.size, 13)
        self.assertEqual(fl.file_name, 'testfile.html')
        self.assertEqual(fl.ext, '.html')
        self.assertEqual(fl.url, '/transient/testfile.html')

    def test_repr(self):
        with open(os.path.join(self.transient_root, 'testfile.html'),
                  'w') as f:
            f.write('<html></html>')

        fl = TransientFile(self.transient_root, 'testfile.html',
                           self.file_manager)
        represent = repr(fl)
        self.assertIn('TransientFile', represent)
        self.assertIn('testfile.html', represent)

    def test_no_file(self):
        fl = PersistentFile(self.persistent_root, 'testfile2.html',
                            self.file_manager)

        self.assertEqual(fl.mimetype, 'text/html')
        self.assertEqual(fl.size, None)
        self.assertEqual(fl.file_name, 'testfile2.html')
        self.assertEqual(fl.ext, '.html')
        self.assertEqual(fl.url, '/media/testfile2.html')

    def test_delete(self):
        with open(os.path.join(self.transient_root, 'delfile1.html'),
                  'w') as f:
            f.write('<html></html>')

        fl1 = TransientFile(self.transient_root, 'delfile1.html',
                            self.file_manager)
        fl2 = TransientFile(self.transient_root, 'delfile2.html',
                            self.file_manager)

        self.assertTrue(os.path.isfile(fl1.path))
        self.assertFalse(os.path.isfile(fl2.path))

        log = []
        with patch('logging.Logger.warning',
                   side_effect=lambda m: log.append(m)):
            self.file_manager.delete(fl1)
            self.file_manager.delete(fl2)

        self.assertFalse(os.path.isfile(fl1.path))
        self.assertFalse(os.path.isfile(fl2.path))
        self.assertIn('delfile2.html', log[0])
        self.assertIn('was not found', log[0])

    def test_delete_error(self):
        path = os.path.join(self.transient_root, 'delfile1.html')
        with open(path, 'w') as f:
            f.write('<html></html>')

        fl1 = TransientFile(self.transient_root, 'delfile1.html',
                            self.file_manager)
        self.assertTrue(os.path.isfile(fl1.path))
        log = []

        # mocking permission error
        def unlink_error(path):
            raise OSError("[Errno 13] Permission denied: {}".format(path))

        with patch('logging.Logger.error',
                   side_effect=lambda m: log.append(m)):
            with patch('os.unlink', side_effect=unlink_error):
                with self.assertRaises(OSError) as exc:
                    self.file_manager.delete(fl1)

    def test_readonly_file_manager(self):
        get_persistent = self.ro_file_manager.get_persistent

        fl = get_persistent('name.txt')
        self.assertIsInstance(fl, PersistentFile)
        self.assertEqual(self.ro_file_manager.get_persistent_url(fl),
                         '/media/name.txt')

        self.assertRaises(ValueError, get_persistent, 'something/../name.txt')
        self.assertRaises(ValueError, get_persistent, '/something/name.txt')
        self.assertRaises(ValueError, get_persistent, '~/something/name.txt')

    def test_create_transient(self):
        req_fl = os.path.join(self.transient_root, 'xxxxx.html')
        with open(req_fl, 'w') as f:
            f.write('<html></html>' * 10000)

        with open(req_fl) as f:
            request = Request.blank('/', POST={'file': ('big.html', f)})

            fl = self.file_manager.create_transient(request.POST['file'].file,
                                                    request.POST['file'].name)

        self.assertEqual(fl.size, 130000)

        # XXX this is a test of strange behaviour when browser does not
        #     pass Content-Length header when uploading a file in POST body
        #     See iktomi.cms.ajax_file_upload
        #     There is no obvious way to simulate this behaviour except
        #     hardcoded length variable.
        with open(req_fl, 'w') as f:
            f.write('<html></html>' * 10000)

        with open(req_fl) as f:
            request = Request.blank('/', POST={'file': ('big.html', f)})

            fl = self.file_manager.create_transient(request.POST['file'].file,
                                                    request.POST['file'].name,
                                                    length=130000)

        self.assertEqual(fl.size, 130000)

    def test_create_transient_dir(self):
        req_fl = os.path.join(self.transient_root, 'xxxxx.html')
        with open(req_fl, 'w') as f:
            f.write('<html></html>' * 10000)

        nonexistent_dir = os.path.join(self.transient_root, "non/existent/dir")

        self.assertFalse(os.path.exists(nonexistent_dir))

        self.file_manager.transient_root = nonexistent_dir

        with open(req_fl) as f:
            request = Request.blank('/', POST={'file': ('big.html', f)})
            fl = self.file_manager.create_transient(request.POST['file'].file,
                                                    request.POST['file'].name)

        self.assertEqual(fl.path, os.path.join(nonexistent_dir, fl.name))
        self.assertEqual(fl.size, 130000)

    def test_create_symlink(self):
        stream1 = BytesIO(b'hello')
        stream2 = BytesIO(b'world')

        source1 = self.file_manager.create_transient(stream1, 'hello.txt')
        source2 = self.file_manager.create_transient(stream2, 'world.txt')

        target_file_dir = os.path.join(self.persistent_root, 'dir/subdir')
        target_file = PersistentFile(target_file_dir, 'target.txt')
        target_file_path = os.path.join(target_file_dir, 'target.txt')
        self.assertFalse(os.path.isfile(target_file_path))

        self.file_manager.create_symlink(source1, target_file)

        self.assertTrue(os.path.isfile(target_file_path))

        with open(target_file_path) as f:
            self.assertEqual('hello', f.read())

        self.file_manager.create_symlink(source2, target_file)

        self.assertTrue(os.path.isfile(target_file_path))

        with open(target_file_path) as f:
            self.assertEqual('world', f.read())
Ejemplo n.º 19
0
class FormFilesTests(unittest.TestCase):
    def setUp(self):
        self.transient_root = tempfile.mkdtemp()
        self.persistent_root = tempfile.mkdtemp()
        self.transient_url = "/transient/"
        self.persistent_url = "/media/"
        self.file_manager = FileManager(
            self.transient_root, self.persistent_root, self.transient_url, self.persistent_url
        )
        self.env = AppEnvironment.create(file_manager=self.file_manager)

    def tearDown(self):
        shutil.rmtree(self.transient_root)
        shutil.rmtree(self.persistent_root)

    def _create_persistent(self):
        f = self.file_manager.get_persistent("test.txt")
        with open(f.path, "wb") as fp:
            fp.write(b"test")
        return f

    def _create_transient(self, content, original_name="test.txt"):
        f = self.file_manager.new_transient(ext=os.path.splitext(original_name)[1])
        with open(f.path, "wb") as fp:
            fp.write(content)
        return f

    def _create_fs(self, mimetype, content, filename="uploaded.txt", name="file"):
        # http://stackoverflow.com/questions/12032807/how-to-create-cgi-fieldstorage-for-testing-purposes
        content = content.encode("utf-8")
        m = {
            u"content-disposition": u'form-data; name="{}"; filename="{}"'.format(name, filename),
            u"content-length": len(content),
            u"content-type": mimetype,
        }
        environ = {"REQUEST_METHOD": "POST"}
        fp = BytesIO(content)
        return cgi.FieldStorage(fp=fp, headers=m, environ=environ)

    def test_none2empty(self):
        form = FormWithFile(self.env)
        form.accept(
            MultiDict({"file.file": None, "file.original_name": "", "file.transient_name": "", "file.mode": "empty"})
        )
        data = form.python_data
        self.assertEqual(data["file"], None)

    def test_transient2empty(self):
        transient = self._create_transient(b"transient1")
        form = FormWithFile(self.env)
        form.accept(
            MultiDict(
                {
                    "file.file": None,
                    "file.original_name": "test.txt",
                    "file.transient_name": transient.name,
                    "file.mode": "transient",
                }
            )
        )
        data = form.python_data
        self.assertIsInstance(data["file"], TransientFile)
        self.assertEqual(data["file"].name, transient.name)

    def test_transient_lost(self):
        form = FormWithFile(self.env)
        form.accept(
            MultiDict(
                {
                    "file.file": None,
                    "file.original_name": "test.txt",
                    "file.transient_name": "lost.txt",
                    "file.mode": "transient",
                }
            )
        )
        self.assertIn("file", form.errors)

    def test_transient_invalid(self):
        illegal = ["more/../../../lost.txt", "../pass", "/etc/pass", "..", "~"]
        for filename in illegal:
            form = FormWithFile(self.env)
            form.accept(
                MultiDict(
                    {
                        "file.file": None,
                        "file.original_name": "test.txt",
                        "file.transient_name": filename,
                        "file.mode": "transient",
                    }
                )
            )
            self.assertIn("file.transient_name", form.errors, "file name is not filtered: %s" % filename)

    def test_file2empty(self):
        form = FormWithFile(self.env)
        fs = self._create_fs("text", "file-content", "filename.ttt")
        form.accept(MultiDict({"file.file": fs, "file.mode": "existing"}))
        data = form.python_data
        self.assertIsInstance(data["file"], TransientFile)
        self.assertEqual(os.path.splitext(data["file"].name)[1], ".ttt")
        with open(data["file"].path) as fp:
            self.assertEqual(fp.read(), "file-content")

    def test_none2persistent(self):
        persistent = self._create_persistent()
        form = FormWithFile(self.env, initial={"file": persistent})
        form.accept(
            MultiDict({"file.file": None, "file.original_name": "", "file.transient_name": "", "file.mode": "existing"})
        )
        data = form.python_data
        self.assertEqual(data["file"], persistent)

    def test_empty2persistent(self):
        persistent = self._create_persistent()
        form = FormWithFile(self.env, initial={"file": persistent})
        form.accept(
            MultiDict({"file.file": None, "file.original_name": "", "file.transient_name": "", "file.mode": "empty"})
        )
        data = form.python_data
        self.assertEqual(data["file"], None)

    def test_transient2persistent(self):
        persistent = self._create_persistent()
        transient = self._create_transient(b"transient1")
        form = FormWithFile(self.env, initial={"file": persistent})
        form.accept(
            MultiDict(
                {
                    "file.file": None,
                    "file.original_name": "test.txt",
                    "file.transient_name": transient.name,
                    "file.mode": "transient",
                }
            )
        )
        data = form.python_data
        self.assertIsInstance(data["file"], TransientFile)
        self.assertEqual(data["file"].name, transient.name)

    def test_file2persistent(self):
        persistent = self._create_persistent()
        form = FormWithFile(self.env, initial={"file": persistent})
        fs = self._create_fs("text", "file-content", "filename.ttt")
        form.accept(MultiDict({"file.file": fs, "file.mode": "existing"}))
        data = form.python_data
        self.assertIsInstance(data["file"], TransientFile)
        self.assertEqual(os.path.splitext(data["file"].name)[1], ".ttt")
        with open(data["file"].path) as fp:
            self.assertEqual(fp.read(), "file-content")