Skip to content

Commit

Permalink
feat: add handler functions for new storage folder on core config
Browse files Browse the repository at this point in the history
  • Loading branch information
joaoandre-avaiga committed Feb 12, 2024
1 parent f5a8b2a commit 886ed47
Show file tree
Hide file tree
Showing 26 changed files with 154 additions and 46 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ dist/

# Core .data directory
.data/
.taipy/
user_data/

# demo files
demo-*
Expand Down
4 changes: 2 additions & 2 deletions taipy/config/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ dataset

# Filesystem default local storage
.data/
.user_data/
.taipy_data/
user_data/
.taipy/

# python notebook
*.ipynb
Expand Down
4 changes: 2 additions & 2 deletions taipy/core/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ dataset
# Filesystem default local storage
.data/
.my_data/
.user_data/
.taipy_data/
user_data/
.taipy/

# python notebook
*.ipynb
Expand Down
7 changes: 4 additions & 3 deletions taipy/core/_entity/_migrate_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from typing import List

from taipy._cli._base_cli import _CLI
from taipy.config.config import Config
from taipy.logger._taipy_logger import _TaipyLogger

from ._migrate import (
Expand Down Expand Up @@ -84,7 +85,7 @@ def parse_arguments(cls):
@classmethod
def __handle_remove_backup(cls, repository_type: str, repository_args: List):
if repository_type == "filesystem":
path = repository_args[0] or ".data"
path = repository_args[0] or Config.core.taipy_storage_folder
if not _remove_backup_file_entities(path):
sys.exit(1)
elif repository_type == "sql":
Expand All @@ -102,7 +103,7 @@ def __handle_remove_backup(cls, repository_type: str, repository_args: List):
@classmethod
def __handle_restore_backup(cls, repository_type: str, repository_args: List):
if repository_type == "filesystem":
path = repository_args[0] or ".data"
path = repository_args[0] or Config.core.taipy_storage_folder
if not _restore_migrate_file_entities(path):
sys.exit(1)
elif repository_type == "sql":
Expand All @@ -120,7 +121,7 @@ def __handle_restore_backup(cls, repository_type: str, repository_args: List):
@classmethod
def __migrate_entities(cls, repository_type: str, repository_args: List, do_backup: bool):
if repository_type == "filesystem":
path = repository_args[0] or ".data"
path = repository_args[0] or Config.core.taipy_storage_folder
if not _migrate_fs_entities(path, do_backup):
sys.exit(1)

Expand Down
2 changes: 1 addition & 1 deletion taipy/core/_repository/_filesystem_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def dir_path(self):

@property
def _storage_folder(self) -> pathlib.Path:
return pathlib.Path(Config.core.storage_folder)
return pathlib.Path(Config.core.taipy_storage_folder)

###############################
# ## Inherited methods ## #
Expand Down
50 changes: 29 additions & 21 deletions taipy/core/config/core_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ class CoreSection(UniqueSection):
Attributes:
root_folder (str): Path of the base folder for the taipy application. The default value is "./taipy/"
storage_folder (str): Folder name used to store user data. The default value is ".user_data/". It is used in
conjunction with the *root_folder* attribute. That means the storage path is <root_folder><storage_folder>
(The default path is "./taipy/.user_data/").
tp_storage_folder (str): Folder name used to store Taipy data. The default value is ".taipy_data/". It is used
in conjunction with the *root_folder* attribute. That means the storage path is
<root_folder><storage_folder> (The default path is "./taipy/.taipy_data/").
storage_folder (str): Folder name used to store user data. The default value is "user_data/". The default
path is "user_data/".
taipy_storage_folder (str): Folder name used to store Taipy data. The default value is ".taipy/". The default
path is "./taipy/".
repository_type (str): Type of the repository to be used to store Taipy data. The default value is
"filesystem".
repository_properties (Dict[str, Union[str, int]]): A dictionary of additional properties to be used by the
Expand All @@ -56,11 +54,11 @@ class CoreSection(UniqueSection):
_ROOT_FOLDER_KEY = "root_folder"
_DEFAULT_ROOT_FOLDER = "./taipy/"

_STORAGE_FOLDER_KEY = "tp_storage_folder"
_DEFAULT_STORAGE_FOLDER = ".taipy_data/"
_STORAGE_FOLDER_KEY = "storage_folder"
_DEFAULT_STORAGE_FOLDER = "user_data/"

_STORAGE_FOLDER_USER_KEY = "storage_folder"
_DEFAULT_STORAGE_FOLDER_USER = ".user_data/"
_STORAGE_FOLDER_TP_KEY = "taipy_storage_folder"
_DEFAULT_STORAGE_FOLDER_TP = ".taipy/"

_REPOSITORY_TYPE_KEY = "repository_type"
_DEFAULT_REPOSITORY_TYPE = "filesystem"
Expand Down Expand Up @@ -89,7 +87,7 @@ def __init__(
self,
root_folder: Optional[str] = None,
storage_folder: Optional[str] = None,
tp_storage_folder: Optional[str] = None,
taipy_storage_folder: Optional[str] = None,
repository_type: Optional[str] = None,
repository_properties: Optional[Dict[str, Union[str, int]]] = None,
read_entity_retry: Optional[int] = None,
Expand All @@ -101,7 +99,7 @@ def __init__(
):
self._root_folder = root_folder
self._storage_folder = storage_folder
self._tp_storage_folder = tp_storage_folder
self._taipy_storage_folder = taipy_storage_folder
self._repository_type = repository_type
self._repository_properties = repository_properties or {}
self._read_entity_retry = (
Expand All @@ -120,7 +118,7 @@ def __copy__(self):
return CoreSection(
self.root_folder,
self.storage_folder,
self.tp_storage_folder,
self.taipy_storage_folder,
self.repository_type,
self.repository_properties,
self.read_entity_retry,
Expand All @@ -141,13 +139,13 @@ def storage_folder(self, val):
self._storage_folder = val

@property
def tp_storage_folder(self):
return _tpl._replace_templates(self._tp_storage_folder)
def taipy_storage_folder(self):
return _tpl._replace_templates(self._taipy_storage_folder)

@tp_storage_folder.setter # type: ignore
@taipy_storage_folder.setter # type: ignore
@_ConfigBlocker._check()
def tp_storage_folder(self, val):
self._tp_storage_folder = val
def taipy_storage_folder(self, val):
self._taipy_storage_folder = val

@property
def root_folder(self):
Expand Down Expand Up @@ -221,6 +219,7 @@ def default_config(cls):
return CoreSection(
cls._DEFAULT_ROOT_FOLDER,
cls._DEFAULT_STORAGE_FOLDER,
cls._DEFAULT_STORAGE_FOLDER_TP,
cls._DEFAULT_REPOSITORY_TYPE,
cls._DEFAULT_REPOSITORY_PROPERTIES,
cls._DEFAULT_READ_ENTITY_RETRY,
Expand All @@ -233,6 +232,7 @@ def default_config(cls):
def _clean(self):
self._root_folder = self._DEFAULT_ROOT_FOLDER
self._storage_folder = self._DEFAULT_STORAGE_FOLDER
self._taipy_storage_folder = self._DEFAULT_STORAGE_FOLDER
self._repository_type = self._DEFAULT_REPOSITORY_TYPE
self._repository_properties = self._DEFAULT_REPOSITORY_PROPERTIES.copy()
self._read_entity_retry = self._DEFAULT_READ_ENTITY_RETRY
Expand All @@ -248,6 +248,8 @@ def _to_dict(self):
as_dict[self._ROOT_FOLDER_KEY] = self._root_folder
if self._storage_folder:
as_dict[self._STORAGE_FOLDER_KEY] = self._storage_folder
if self._taipy_storage_folder:
as_dict[self._STORAGE_FOLDER_TP_KEY] = self._taipy_storage_folder
if self._repository_type:
as_dict[self._REPOSITORY_TYPE_KEY] = self._repository_type
if self._repository_properties:
Expand All @@ -269,6 +271,7 @@ def _to_dict(self):
def _from_dict(cls, as_dict: Dict[str, Any], id=None, config: Optional[_Config] = None):
root_folder = as_dict.pop(cls._ROOT_FOLDER_KEY, None)
storage_folder = as_dict.pop(cls._STORAGE_FOLDER_KEY, None)
taipy_storage_folder = as_dict.pop(cls._STORAGE_FOLDER_TP_KEY, None)
repository_type = as_dict.pop(cls._REPOSITORY_TYPE_KEY, None)
repository_properties = as_dict.pop(cls._REPOSITORY_PROPERTIES_KEY, None)
read_entity_retry = as_dict.pop(cls._READ_ENTITY_RETRY_KEY, None)
Expand All @@ -279,6 +282,7 @@ def _from_dict(cls, as_dict: Dict[str, Any], id=None, config: Optional[_Config]
return CoreSection(
root_folder,
storage_folder,
taipy_storage_folder,
repository_type,
repository_properties,
read_entity_retry,
Expand All @@ -292,6 +296,7 @@ def _from_dict(cls, as_dict: Dict[str, Any], id=None, config: Optional[_Config]
def _update(self, as_dict: Dict[str, Any], default_section=None):
self._root_folder = as_dict.pop(self._ROOT_FOLDER_KEY, self._root_folder)
self._storage_folder = as_dict.pop(self._STORAGE_FOLDER_KEY, self._storage_folder)
self._taipy_storage_folder = as_dict.pop(self._STORAGE_FOLDER_TP_KEY, self._taipy_storage_folder)
self._repository_type = as_dict.pop(self._REPOSITORY_TYPE_KEY, self._repository_type)
self._repository_properties.update(as_dict.pop(self._REPOSITORY_PROPERTIES_KEY, self._repository_properties))
self._read_entity_retry = as_dict.pop(self._READ_ENTITY_RETRY_KEY, self._read_entity_retry)
Expand Down Expand Up @@ -342,9 +347,12 @@ def _configure(
Parameters:
root_folder (Optional[str]): Path of the base folder for the taipy application.
The default value is "./taipy/"
storage_folder (Optional[str]): Folder name used to store Taipy data. The default value is ".data/".
It is used in conjunction with the `root_folder` field. That means the storage path is
<root_folder><storage_folder> (The default path is "./taipy/.data/").
storage_folder (str): Folder name used to store user data. The default value is "user_data/". It is used in
conjunction with the *root_folder* attribute. That means the storage path is
<root_folder><storage_folder> (The default path is "./taipy/user_data/").
taipy_storage_folder (str): Folder name used to store Taipy data. The default value is ".taipy/". It is
used in conjunction with the *root_folder* attribute. That means the storage path is
<root_folder><storage_folder> (The default path is "./taipy/.taipy/").
repository_type (Optional[str]): The type of the repository to be used to store Taipy data.
The default value is "filesystem".
repository_properties (Optional[Dict[str, Union[str, int]]]): A dictionary of additional properties
Expand Down
9 changes: 8 additions & 1 deletion taipy/core/data/_abstract_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

import os
import pathlib
import shutil


class _AbstractFileDataNode(object):
Expand All @@ -26,3 +27,9 @@ def _build_path(self, storage_type):
if not dir_path.exists():
dir_path.mkdir(parents=True, exist_ok=True)
return dir_path / f"{self.id}.{self.__EXTENSION_MAP.get(storage_type)}"

def _migrate_path(self, storage_type, old_path):
new_path = self._build_path(storage_type)
if os.path.exists(old_path):
shutil.move(old_path, new_path)
return new_path
7 changes: 5 additions & 2 deletions taipy/core/data/csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,13 @@ def __init__(
_AbstractTabularDataNode.__init__(self, **properties)

self._path = properties.get(self.__PATH_KEY, properties.get(self.__DEFAULT_PATH_KEY))
if self._path and ".data" in self._path:
self._path = self._migrate_path(self.storage_type(), self._path)

if not self._path:
self._path = self._build_path(self.storage_type())
properties[self.__PATH_KEY] = self._path

if not self._last_edit_date and isfile(self._path):
self._last_edit_date = datetime.now()
if default_value is not None and not os.path.exists(self._path):
self._write(default_value)
self._last_edit_date = datetime.now()
Expand All @@ -142,6 +143,8 @@ def __init__(
}
)
)
if not self._last_edit_date and isfile(self._path):
self._last_edit_date = datetime.now()

self._TAIPY_PROPERTIES.update(
{
Expand Down
3 changes: 3 additions & 0 deletions taipy/core/data/excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ def __init__(
**properties,
)
_AbstractTabularDataNode.__init__(self, **properties)
if self._path and ".data" in self._path:
self._path = self._migrate_path(self.storage_type(), self._path)

if not self._path:
self._path = self._build_path(self.storage_type())
properties[self.__PATH_KEY] = self._path
Expand Down
3 changes: 3 additions & 0 deletions taipy/core/data/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ def __init__(
**properties,
)
self._path = properties.get(self.__PATH_KEY, properties.get(self.__DEFAULT_PATH_KEY))
if self._path and ".data" in self._path:
self._path = self._migrate_path(self.storage_type(), self._path)

if not self._path:
self._path = self._build_path(self.storage_type())
properties[self.__PATH_KEY] = self._path
Expand Down
4 changes: 4 additions & 0 deletions taipy/core/data/parquet.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,12 @@ def __init__(
**properties,
)
self._path = properties.get(self.__PATH_KEY, properties.get(self.__DEFAULT_PATH_KEY))

if self._path and ".data" in self._path:
self._path = self._migrate_path(self.storage_type(), self._path)
if not self._path:
self._path = self._build_path(self.storage_type())

properties[self.__PATH_KEY] = self._path

if default_value is not None and not os.path.exists(self._path):
Expand Down
8 changes: 6 additions & 2 deletions taipy/core/data/pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,12 @@ def __init__(
editor_expiration_date,
**properties,
)
if self._path and ".data" in self._path:
self._path = self._migrate_path(self.storage_type(), self._path)

if self._path is None:
self._path = self._build_path(self.storage_type())
if not self._last_edit_date and os.path.exists(self._path):
self._last_edit_date = datetime.now()

if default_value is not None and not os.path.exists(self._path):
self._write(default_value)
self._last_edit_date = datetime.now()
Expand All @@ -118,6 +120,8 @@ def __init__(
}
)
)
if not self._last_edit_date and os.path.exists(self._path):
self._last_edit_date = datetime.now()

self._TAIPY_PROPERTIES.update(
{
Expand Down
4 changes: 2 additions & 2 deletions taipy/gui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ Dockerfile.dev

# Filesystem default local storage
.data/
.user_data/
.taipy_data/
user_data/
.taipy/

# Python notebook
*.ipynb
Expand Down
4 changes: 2 additions & 2 deletions taipy/templates/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ dist/

# Core .data directory
.data/
.user_data/
.taipy_data/
user_data/
.taipy/

# demo files
demo-*
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Taipy
.data/
.user_data/
.taipy_data/
user_data/
.taipy/
2 changes: 1 addition & 1 deletion tests/core/_entity/test_migrate_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_migrate_fs_default(caplog):
with pytest.raises(SystemExit):
with patch("sys.argv", ["prog", "migrate", "--repository-type", "filesystem", "--skip-backup"]):
_MigrateCLI.parse_arguments()
assert "Starting entity migration from '.data' folder" in caplog.text
assert "Starting entity migration from '.taipy/' folder" in caplog.text


def test_migrate_fs_specified_folder(caplog):
Expand Down
6 changes: 4 additions & 2 deletions tests/core/config/test_config_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ def test_read_write_toml_configuration_file():
[CORE]
root_folder = "./taipy/"
storage_folder = ".data/"
storage_folder = "user_data/"
taipy_storage_folder = ".taipy/"
repository_type = "filesystem"
read_entity_retry = "0:int"
mode = "development"
Expand Down Expand Up @@ -289,7 +290,8 @@ def test_read_write_json_configuration_file():
},
"CORE": {
"root_folder": "./taipy/",
"storage_folder": ".data/",
"storage_folder": "user_data/",
"taipy_storage_folder": ".taipy/",
"repository_type": "filesystem",
"read_entity_retry": "0:int",
"mode": "development",
Expand Down
3 changes: 2 additions & 1 deletion tests/core/config/test_default_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def _test_default_core_section(core_section: CoreSection):
assert core_section.version_number == ""
assert not core_section.force
assert core_section.root_folder == "./taipy/"
assert core_section.storage_folder == ".data/"
assert core_section.storage_folder == "user_data/"
assert core_section.taipy_storage_folder == ".taipy/"
assert core_section.repository_type == "filesystem"
assert core_section.repository_properties == {}
assert len(core_section.properties) == 0
Expand Down
3 changes: 2 additions & 1 deletion tests/core/config/test_file_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def test_write_configuration_file():
[CORE]
root_folder = "./taipy/"
storage_folder = ".data/"
storage_folder = "user_data/"
taipy_storage_folder = ".taipy/"
repository_type = "filesystem"
read_entity_retry = "0:int"
mode = "development"
Expand Down
Loading

0 comments on commit 886ed47

Please sign in to comment.