Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Unit test suite for the template engine, covering parsing, rendering, inheritance and localization
* Template compiler that translates templates into bytecode, falling back to the previous rendering for the constructs it does not cover - [#33](https://github.com/hivesolutions/colony-plugins/issues/33)
* New `TEMPLATE_COMPILER` configuration option (default `True`) to control the compilation of templates
* Option to have a file or directory that does not exist reported with the same not found error for every file storage engine

### Changed

Expand All @@ -55,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

* Files stored with the zip file storage engine can now be retrieved
* Diagnostics gathering no longer fails when a request ends with an error - [#38](https://github.com/hivesolutions/colony-plugins/issues/38)
* A request that fails before it starts being handled is now logged instead of being reported only to the client - [#38](https://github.com/hivesolutions/colony-plugins/issues/38)
* Sentry error reporting now starts with the application instead of staying installed but inactive - [#38](https://github.com/hivesolutions/colony-plugins/issues/38)
Expand Down
3 changes: 3 additions & 0 deletions data/src/file_fs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
__license__ = "Apache License, Version 2.0"
""" The license for the module """

from . import mocks
from . import system
from . import test

from .system import FileFS
from .test import FileFSTest
39 changes: 39 additions & 0 deletions data/src/file_fs/mocks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Hive Colony Framework
# Copyright (c) 2008-2024 Hive Solutions Lda.
#
# This file is part of Hive Colony Framework.
#
# Hive Colony Framework is free software: you can redistribute it and/or modify
# it under the terms of the Apache License as published by the Apache
# Foundation, either version 2.0 of the License, or (at your option) any
# later version.
#
# Hive Colony Framework is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# Apache License for more details.
#
# You should have received a copy of the Apache License along with
# Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.

__author__ = "João Magalhães <joamag@hive.pt>"
""" The author(s) of the module """

__copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
""" The copyright for the module """

__license__ = "Apache License, Version 2.0"
""" The license for the module """


class MockConnection(object):
"""
Mock connection, holding the (engine) file connection
that is used by the file engine operations.
"""

def __init__(self, file_connection):
self.file_connection = file_connection
31 changes: 31 additions & 0 deletions data/src/file_fs/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,37 @@ def mtime(self, connection, file_name):
target_file_path = os.path.normpath(target_file_path)
return os.path.getmtime(target_file_path)

def exists(self, connection, file_name):
# retrieves the base file connection and
# then uses it to retrieve the base path
file_connection = connection.file_connection
base_path = file_connection.base_path

# strips the extra path separator values
# (avoids problems working with the file system)
file_name = file_name.lstrip("/")

# creates the target file path from the base path
# and uses it to verify if the file exists
target_file_path = os.path.join(base_path, file_name)
target_file_path = os.path.normpath(target_file_path)
return os.path.exists(target_file_path)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

def exists_directory(self, connection, directory_name):
# retrieves the base file connection and
# then uses it to retrieve the base path
file_connection = connection.file_connection
base_path = file_connection.base_path

# strips the extra path separator values
# (avoids problems working with the file system)
directory_name = directory_name.lstrip("/")

# creates the full directory name from the base path
# and uses it to verify if the directory exists
full_directory_name = os.path.join(base_path, directory_name)
return os.path.isdir(full_directory_name)


class FsConnection(object):
"""
Expand Down
107 changes: 107 additions & 0 deletions data/src/file_fs/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Hive Colony Framework
# Copyright (c) 2008-2024 Hive Solutions Lda.
#
# This file is part of Hive Colony Framework.
#
# Hive Colony Framework is free software: you can redistribute it and/or modify
# it under the terms of the Apache License as published by the Apache
# Foundation, either version 2.0 of the License, or (at your option) any
# later version.
#
# Hive Colony Framework is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# Apache License for more details.
#
# You should have received a copy of the Apache License along with
# Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.

__author__ = "João Magalhães <joamag@hive.pt>"
""" The author(s) of the module """

__copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
""" The copyright for the module """

__license__ = "Apache License, Version 2.0"
""" The license for the module """

import shutil
import tempfile

import colony

from . import mocks
from . import system


class FileFSTest(colony.Test):
"""
The file FS infra-structure test class, responsible
for the returning of the associated tests.
"""

def get_bundle(self):
return (FileFSTestCase,)

def set_up(self, test_case):
colony.Test.set_up(self, test_case)

def tear_down(self, test_case):
colony.Test.tear_down(self, test_case)


class FileFSTestCase(colony.ColonyTestCase):
"""
The file FS test case, verifying the file engine operations
against a temporary directory used as the base path.
"""

@staticmethod
def get_description():
return "File FS test case"

def setUp(self):
colony.ColonyTestCase.setUp(self)
self.temp_path = tempfile.mkdtemp()
self.connection = mocks.MockConnection(
system.FsConnection("default", self.temp_path)
)

def tearDown(self):
shutil.rmtree(self.temp_path, ignore_errors=True)
colony.ColonyTestCase.tearDown(self)

def test_exists(self):
self.plugin.put_data(self.connection, b"hello", "images/hello.txt")

self.assertEqual(self.plugin.exists(self.connection, "images/hello.txt"), True)
self.assertEqual(self.plugin.exists(self.connection, "/images/hello.txt"), True)
self.assertEqual(
self.plugin.exists(self.connection, "images/missing.txt"), False
)

# verifies that a directory is considered to exist, so that its
# retrieval as a file fails with the error of the file system (not
# being reported as a file that does not exist)
self.assertEqual(self.plugin.exists(self.connection, "images"), True)
self.assertRaises(IOError, self.plugin.get, self.connection, "images")

def test_exists_directory(self):
self.plugin.put_data(self.connection, b"hello", "images/hello.txt")

self.assertEqual(self.plugin.exists_directory(self.connection, "images"), True)
self.assertEqual(self.plugin.exists_directory(self.connection, "/images"), True)
self.assertEqual(self.plugin.exists_directory(self.connection, "images/"), True)
self.assertEqual(self.plugin.exists_directory(self.connection, ""), True)
self.assertEqual(
self.plugin.exists_directory(self.connection, "missing"), False
)

# verifies that a file is not considered to be a directory, so
# that its listing is reported as a directory that does not exist
self.assertEqual(
self.plugin.exists_directory(self.connection, "images/hello.txt"), False
)
9 changes: 8 additions & 1 deletion data/src/file_fs_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ class FileFSPlugin(colony.Plugin):
version = "1.0.0"
author = "Hive Solutions Lda. <development@hive.pt>"
platforms = [colony.CPYTHON_ENVIRONMENT]
capabilities = ["file_engine"]
capabilities = ["file_engine", "test"]
main_modules = ["file_fs"]

def load_plugin(self):
colony.Plugin.load_plugin(self)
import file_fs

self.system = file_fs.FileFS(self)
self.test = file_fs.FileFSTest(self)

def get_engine_name(self):
return self.system.get_engine_name()
Expand Down Expand Up @@ -86,3 +87,9 @@ def size(self, connection, file_name):

def mtime(self, connection, file_name):
return self.system.mtime(connection, file_name)

def exists(self, connection, file_name):
return self.system.exists(connection, file_name)

def exists_directory(self, connection, directory_name):
return self.system.exists_directory(connection, directory_name)
46 changes: 46 additions & 0 deletions data/src/file_gridfs/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,49 @@ def size(self, connection, file_name):

def mtime(self, connection, file_name):
pass

def exists(self, connection, file_name):
# retrieves the base file connection as the
# GridFS system
gridfs_sytem = connection.file_connection

# adds the path separator value to the file name
# in case it's necessary
file_name = file_name.startswith("/") and file_name or "/" + file_name

# verifies if there's any file (version) with
# the given file name in the GridFS system
return gridfs_sytem.exists(filename=file_name)

def exists_directory(self, connection, directory_name):
# retrieves the base file connection as the
# GridFS system
gridfs_sytem = connection.file_connection

# adds the path separator value to the directory name
# in case it's necessary
directory_name = (
directory_name.startswith("/") and directory_name or "/" + directory_name
)

# sets the directory name according to the default separator value
directory_name = (
directory_name.endswith("/") and directory_name or directory_name + "/"
)

# the root directory always exists, as there's
# no structure to be created for it in GridFS
if directory_name == "/":
return True

# retrieves the file name list from the
# GridFS system and filters the values
# based on the directory name prefix
file_name_list = gridfs_sytem.list()
file_name_list = [
value for value in file_name_list if value.startswith(directory_name)
]

# returns if the directory exists in the GridFS system, meaning
# that there's at least one file contained in it
return True if file_name_list else False
6 changes: 6 additions & 0 deletions data/src/file_gridfs_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,9 @@ def size(self, connection, file_name):

def mtime(self, connection, file_name):
return self.system.mtime(connection, file_name)

def exists(self, connection, file_name):
return self.system.exists(connection, file_name)

def exists_directory(self, connection, directory_name):
return self.system.exists_directory(connection, directory_name)
5 changes: 5 additions & 0 deletions data/src/file_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
__license__ = "Apache License, Version 2.0"
""" The license for the module """

from . import exceptions
from . import mocks
from . import system
from . import test

from .exceptions import FileManagerException, FileNotFound, DirectoryNotFound
from .system import DataFileManager
from .test import FileManagerTest
Loading