From 5fd18bb6dd26dd11456eead1b47a8a48f3dc9185 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Thu, 24 Aug 2023 10:02:49 +0200 Subject: [PATCH 01/54] [ADD] fs_storage: Get access to filesyste storages This addon define a new model 'fs.storage' used to get access to a filesystem storage (ftp, sftp, s3, azure, ...) through an unified interface provided by the 'fsspec' python library (https://filesystem-spec.readthedocs.io/en/latest) --- fs_storage/README.rst | 35 ++ fs_storage/__init__.py | 6 + fs_storage/__manifest__.py | 22 + fs_storage/demo/fs_storage.xml | 8 + fs_storage/i18n/storage_backend.pot | 144 ++++++ fs_storage/models/__init__.py | 1 + fs_storage/models/fs_storage.py | 409 ++++++++++++++++ fs_storage/odoo_file_system.py | 50 ++ fs_storage/readme/CONTRIBUTORS.rst | 2 + fs_storage/readme/DESCRIPTION.rst | 63 +++ fs_storage/readme/HISTORY.rst | 0 fs_storage/readme/ROADMAP.rst | 9 + fs_storage/readme/USAGE.rst | 84 ++++ fs_storage/rooted_dir_file_system.py | 37 ++ fs_storage/security/ir.model.access.csv | 2 + fs_storage/static/description/icon.png | Bin 0 -> 9455 bytes fs_storage/static/description/index.html | 563 +++++++++++++++++++++++ fs_storage/tests/__init__.py | 1 + fs_storage/tests/test_fs_storage.py | 153 ++++++ fs_storage/views/fs_storage_view.xml | 117 +++++ 20 files changed, 1706 insertions(+) create mode 100644 fs_storage/README.rst create mode 100644 fs_storage/__init__.py create mode 100644 fs_storage/__manifest__.py create mode 100644 fs_storage/demo/fs_storage.xml create mode 100644 fs_storage/i18n/storage_backend.pot create mode 100644 fs_storage/models/__init__.py create mode 100644 fs_storage/models/fs_storage.py create mode 100644 fs_storage/odoo_file_system.py create mode 100644 fs_storage/readme/CONTRIBUTORS.rst create mode 100644 fs_storage/readme/DESCRIPTION.rst create mode 100644 fs_storage/readme/HISTORY.rst create mode 100644 fs_storage/readme/ROADMAP.rst create mode 100644 fs_storage/readme/USAGE.rst create mode 100644 fs_storage/rooted_dir_file_system.py create mode 100644 fs_storage/security/ir.model.access.csv create mode 100644 fs_storage/static/description/icon.png create mode 100644 fs_storage/static/description/index.html create mode 100644 fs_storage/tests/__init__.py create mode 100644 fs_storage/tests/test_fs_storage.py create mode 100644 fs_storage/views/fs_storage_view.xml diff --git a/fs_storage/README.rst b/fs_storage/README.rst new file mode 100644 index 0000000000..38929e8775 --- /dev/null +++ b/fs_storage/README.rst @@ -0,0 +1,35 @@ +**This file is going to be generated by oca-gen-addon-readme.** + +*Manual changes will be overwritten.* + +Please provide content in the ``readme`` directory: + +* **DESCRIPTION.rst** (required) +* INSTALL.rst (optional) +* CONFIGURE.rst (optional) +* **USAGE.rst** (optional, highly recommended) +* DEVELOP.rst (optional) +* ROADMAP.rst (optional) +* HISTORY.rst (optional, recommended) +* **CONTRIBUTORS.rst** (optional, highly recommended) +* CREDITS.rst (optional) + +Content of this README will also be drawn from the addon manifest, +from keys such as name, authors, maintainers, development_status, +and license. + +A good, one sentence summary in the manifest is also highly recommended. + + +Automatic changelog generation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`HISTORY.rst` can be auto generated using `towncrier `_. + +Just put towncrier compatible changelog fragments into `readme/newsfragments` +and the changelog file will be automatically generated and updated when a new fragment is added. + +Please refer to `towncrier` documentation to know more. + +NOTE: the changelog will be automatically generated when using `/ocabot merge $option`. +If you need to run it manually, refer to `OCA/maintainer-tools README `_. diff --git a/fs_storage/__init__.py b/fs_storage/__init__.py new file mode 100644 index 0000000000..1df985fe64 --- /dev/null +++ b/fs_storage/__init__.py @@ -0,0 +1,6 @@ +# register protocols first +from . import odoo_file_system +from . import rooted_dir_file_system + +# then add normal imports +from . import models diff --git a/fs_storage/__manifest__.py b/fs_storage/__manifest__.py new file mode 100644 index 0000000000..c66b69f7e4 --- /dev/null +++ b/fs_storage/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Filesystem Storage Backend", + "summary": "Implement the concept of Storage with amazon S3, sftp...", + "version": "16.0.1.0.1", + "category": "FS Storage", + "website": "https://github.com/OCA/storage", + "author": " ACSONE SA/NV, Odoo Community Association (OCA)", + "license": "LGPL-3", + "development_status": "Beta", + "installable": True, + "depends": ["base", "base_sparse_field", "server_environment"], + "data": [ + "views/fs_storage_view.xml", + "security/ir.model.access.csv", + ], + "demo": ["demo/fs_storage.xml"], + "external_dependencies": {"python": ["fsspec"]}, +} diff --git a/fs_storage/demo/fs_storage.xml b/fs_storage/demo/fs_storage.xml new file mode 100644 index 0000000000..a1fd01fd70 --- /dev/null +++ b/fs_storage/demo/fs_storage.xml @@ -0,0 +1,8 @@ + + + + Odoo Filesystem Backend + odoofs + odoofs + + diff --git a/fs_storage/i18n/storage_backend.pot b/fs_storage/i18n/storage_backend.pot new file mode 100644 index 0000000000..45503812f9 --- /dev/null +++ b/fs_storage/i18n/storage_backend.pot @@ -0,0 +1,144 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fs_storage +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__backend_type_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_default +msgid " Env Default" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/components/filesystem_adapter.py:0 +#, python-format +msgid "Access to %s is forbidden" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__backend_type +msgid "Backend Type" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__backend_type_env_is_editable +msgid "Backend Type Env Is Editable" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Connection Test Failed!" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Connection Test Succeeded!" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_uid +msgid "Created by" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_date +msgid "Created on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path +msgid "Directory Path" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_is_editable +msgid "Directory Path Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name +msgid "Display Name" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Everything seems properly set up!" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields.selection,name:fs_storage.selection__fs_storage__backend_type__filesystem +msgid "Filesystem" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__has_validation +msgid "Has Validation" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__id +msgid "ID" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage____last_update +msgid "Last Modified on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_date +msgid "Last Updated on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__name +msgid "Name" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path +#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path_env_default +msgid "Relative path to the directory to store the file" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__server_env_defaults +msgid "Server Env Defaults" +msgstr "" + +#. module: fs_storage +#: model:ir.actions.act_window,name:fs_storage.act_open_fs_storage_view +#: model:ir.model,name:fs_storage.model_fs_storage +#: model:ir.ui.menu,name:fs_storage.menu_storage +#: model:ir.ui.menu,name:fs_storage.menu_fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_view_form +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_view_search +msgid "FS Storage" +msgstr "" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_view_form +msgid "Test connection" +msgstr "" diff --git a/fs_storage/models/__init__.py b/fs_storage/models/__init__.py new file mode 100644 index 0000000000..349bb0495a --- /dev/null +++ b/fs_storage/models/__init__.py @@ -0,0 +1 @@ +from . import fs_storage diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py new file mode 100644 index 0000000000..5bcc5f3e5e --- /dev/null +++ b/fs_storage/models/fs_storage.py @@ -0,0 +1,409 @@ +# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from __future__ import annotations + +import base64 +import functools +import inspect +import json +import logging +import os.path +import re +import warnings +from typing import AnyStr + +import fsspec + +from odoo import _, api, fields, models, tools +from odoo.exceptions import ValidationError + +from odoo.addons.base_sparse_field.models.fields import Serialized + +_logger = logging.getLogger(__name__) + + +# TODO: useful for the whole OCA? +def deprecated(reason): + """Mark functions or classes as deprecated. + + Emit warning at execution. + + The @deprecated is used with a 'reason'. + + .. code-block:: python + + @deprecated("please, use another function") + def old_function(x, y): + pass + """ + + def decorator(func1): + + if inspect.isclass(func1): + fmt1 = "Call to deprecated class {name} ({reason})." + else: + fmt1 = "Call to deprecated function {name} ({reason})." + + @functools.wraps(func1) + def new_func1(*args, **kwargs): + warnings.simplefilter("always", DeprecationWarning) + warnings.warn( + fmt1.format(name=func1.__name__, reason=reason), + category=DeprecationWarning, + stacklevel=2, + ) + warnings.simplefilter("default", DeprecationWarning) + return func1(*args, **kwargs) + + return new_func1 + + return decorator + + +class FSStorage(models.Model): + _name = "fs.storage" + _inherit = "server.env.mixin" + _description = "FS Storage" + + __slots__ = ("__fs", "__odoo_storage_path") + + def __init__(self, env, ids=(), prefetch_ids=()): + super().__init__(env, ids=ids, prefetch_ids=prefetch_ids) + self.__fs = None + self.__odoo_storage_path = None + + name = fields.Char(required=True) + code = fields.Char( + required=True, + help="Technical code used to identify the storage backend into the code." + "This code must be unique. This code is used for example to define the " + "storage backend to store the attachments via the configuration parameter " + "'ir_attachment.storage.force.database' when the module 'fs_attachment' " + "is installed.", + ) + protocol = fields.Selection( + selection="_get_protocols", + required=True, + default="odoofs", + help="The protocol used to access the content of filesystem.\n" + "This list is the one supported by the fsspec library (see " + "https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocol" + "is added by default and refers to the odoo local filesystem.\n" + "Pay attention that according to the protocol, some options must be" + "provided through the options field.", + ) + protocol_descr = fields.Text( + compute="_compute_protocol_descr", + ) + options = fields.Text( + help="The options used to initialize the filesystem.\n" + "This is a JSON field that depends on the protocol used.\n" + "For example, for the sftp protocol, you can provide the following:\n" + "{\n" + " 'host': 'my.sftp.server',\n" + " 'ssh_kwrags': {\n" + " 'username': 'myuser',\n" + " 'password': 'mypassword',\n" + " 'port': 22,\n" + " }\n" + "}\n" + "For more information, please refer to the fsspec documentation:\n" + "https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-implementations" + ) + + json_options = Serialized( + help="The options used to initialize the filesystem.\n", + compute="_compute_json_options", + inverse="_inverse_json_options", + ) + directory_path = fields.Char( + help="Relative path to the directory to store the file" + ) + + # the next fields are used to display documentation to help the user + # to configure the backend + options_protocol = fields.Selection( + string="Describes Protocol", + selection="_get_options_protocol", + default="odoofs", + help="The protocol used to access the content of filesystem.\n" + "This list is the one supported by the fsspec library (see " + "https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocol" + "is added by default and refers to the odoo local filesystem.\n" + "Pay attention that according to the protocol, some options must be" + "provided through the options field.", + store=False, + ) + options_properties = fields.Text( + string="Available properties", + compute="_compute_options_properties", + store=False, + ) + + _sql_constraints = [ + ( + "code_uniq", + "unique(code)", + "The code must be unique", + ), + ] + + _server_env_section_name_field = "code" + + @property + def _server_env_fields(self): + return {"protocol": {}, "options": {}, "directory_path": {}} + + def write(self, vals): + self.__fs = None + self.clear_caches() + return super().write(vals) + + @api.model + @tools.ormcache() + def get_id_by_code_map(self): + """Return a dictionary with the code as key and the id as value.""" + return {rec.code: rec.id for rec in self.search([])} + + @api.model + def get_id_by_code(self, code): + """Return the id of the filesystem associated to the given code.""" + return self.get_id_by_code_map().get(code) + + @api.model + def get_by_code(self, code) -> FSStorage: + """Return the filesystem associated to the given code.""" + res = self.browse() + res_id = self.get_id_by_code(code) + if res_id: + res = self.browse(res_id) + return res + + @api.model + @tools.ormcache() + def get_storage_codes(self): + """Return the list of codes of the existing filesystems.""" + return [s.code for s in self.search([])] + + @api.model + @tools.ormcache("code") + def get_fs_by_code(self, code): + """Return the filesystem associated to the given code. + + :param code: the code of the filesystem + """ + fs = None + fs_storage = self.get_by_code(code) + if fs_storage: + fs = fs_storage.fs + return fs + + def copy(self, default=None): + default = default or {} + if "code" not in default: + default["code"] = "{}_copy".format(self.code) + return super().copy(default) + + @api.model + def _get_protocols(self) -> list[tuple[str, str]]: + protocol = [("odoofs", "Odoo's FileSystem")] + for p in fsspec.available_protocols(): + try: + cls = fsspec.get_filesystem_class(p) + protocol.append((p, f"{p} ({cls.__name__})")) + except ImportError as e: + _logger.debug("Cannot load the protocol %s. Reason: %s", p, e) + return protocol + + @api.constrains("options") + def _check_options(self) -> None: + for rec in self: + try: + json.loads(rec.options or "{}") + except Exception as e: + raise ValidationError(_("The options must be a valid JSON")) from e + + @api.depends("options") + def _compute_json_options(self) -> None: + for rec in self: + rec.json_options = json.loads(rec.options or "{}") + + def _inverse_json_options(self) -> None: + for rec in self: + rec.options = json.dumps(rec.json_options) + + @api.depends("protocol") + def _compute_protocol_descr(self) -> None: + for rec in self: + rec.protocol_descr = fsspec.get_filesystem_class(rec.protocol).__doc__ + + @api.model + def _get_options_protocol(self) -> list[tuple[str, str]]: + protocol = [("odoofs", "Odoo's Filesystem")] + for p in fsspec.available_protocols(): + try: + fsspec.get_filesystem_class(p) + protocol.append((p, p)) + except ImportError as e: + _logger.debug("Cannot load the protocol %s. Reason: %s", p, e) + return protocol + + @api.depends("options_protocol") + def _compute_options_properties(self) -> None: + for rec in self: + cls = fsspec.get_filesystem_class(rec.options_protocol) + signature = inspect.signature(cls.__init__) + doc = inspect.getdoc(cls.__init__) + rec.options_properties = f"__init__{signature}\n{doc}" + + @property + def fs(self) -> fsspec.AbstractFileSystem: + """Get the fsspec filesystem for this backend.""" + self.ensure_one() + if not self.__fs: + self.__fs = self._get_filesystem() + return self.__fs + + def _get_filesystem_storage_path(self) -> str: + """Get the path to the storage directory. + + This path is relative to the odoo filestore.and is used as root path + when the protocol is filesystem. + """ + self.ensure_one() + path = os.path.join(self.env["ir.attachment"]._filestore(), "storage") + if not os.path.exists(path): + os.makedirs(path) + return path + + @property + def _odoo_storage_path(self) -> str: + """Get the path to the storage directory. + + This path is relative to the odoo filestore.and is used as root path + when the protocol is filesystem. + """ + if not self.__odoo_storage_path: + self.__odoo_storage_path = self._get_filesystem_storage_path() + return self.__odoo_storage_path + + def _recursive_add_odoo_storage_path(self, options: dict) -> dict: + """Add the odoo storage path to the options. + + This is a recursive function that will add the odoo_storage_path + option to the nested target_options if the target_protocol is + odoofs + """ + if "target_protocol" in options: + target_options = options.get("target_options", {}) + if options["target_protocol"] == "odoofs": + target_options["odoo_storage_path"] = self._odoo_storage_path + options["target_options"] = target_options + self._recursive_add_odoo_storage_path(target_options) + return options + + def _get_filesystem(self) -> fsspec.AbstractFileSystem: + """Get the fsspec filesystem for this backend. + + See https://filesystem-spec.readthedocs.io/en/latest/api.html + #fsspec.spec.AbstractFileSystem + + :return: fsspec.AbstractFileSystem + """ + self.ensure_one() + options = self.json_options + if self.protocol == "odoofs": + options["odoo_storage_path"] = self._odoo_storage_path + options = self._recursive_add_odoo_storage_path(options) + fs = fsspec.filesystem(self.protocol, **options) + directory_path = self.directory_path + if directory_path: + fs = fsspec.filesystem("rooted_dir", path=directory_path, fs=fs) + return fs + + # Deprecated methods used to ease the migration from the storage_backend addons + # to the fs_storage addons. These methods will be removed in the future (Odoo 18) + @deprecated("Please use _get_filesystem() instead and the fsspec API directly.") + def add(self, relative_path, data, binary=True, **kwargs) -> None: + if not binary: + data = base64.b64decode(data) + path = relative_path.split(self.fs.sep)[:-1] + if not self.fs.exists(self.fs.sep.join(path)): + self.fs.makedirs(self.fs.sep.join(path)) + with self.fs.open(relative_path, "wb", **kwargs) as f: + f.write(data) + + @deprecated("Please use _get_filesystem() instead and the fsspec API directly.") + def get(self, relative_path, binary=True, **kwargs) -> AnyStr: + data = self.fs.read_bytes(relative_path, **kwargs) + if not binary and data: + data = base64.b64encode(data) + return data + + @deprecated("Please use _get_filesystem() instead and the fsspec API directly.") + def list_files(self, relative_path="", pattern=False) -> list[str]: + relative_path = relative_path or self.fs.root_marker + if not self.fs.exists(relative_path): + return [] + if pattern: + relative_path = self.fs.sep.join([relative_path, pattern]) + return self.fs.glob(relative_path) + return self.fs.ls(relative_path, detail=False) + + @deprecated("Please use _get_filesystem() instead and the fsspec API directly.") + def find_files(self, pattern, relative_path="", **kw) -> list[str]: + """Find files matching given pattern. + + :param pattern: regex expression + :param relative_path: optional relative path containing files + :return: list of file paths as full paths from the root + """ + result = [] + relative_path = relative_path or self.fs.root_marker + if not self.fs.exists(relative_path): + return [] + regex = re.compile(pattern) + for file_path in self.fs.ls(relative_path, detail=False): + if regex.match(file_path): + result.append(file_path) + return result + + @deprecated("Please use _get_filesystem() instead and the fsspec API directly.") + def move_files(self, files, destination_path, **kw) -> None: + """Move files to given destination. + + :param files: list of file paths to be moved + :param destination_path: directory path where to move files + :return: None + """ + for file_path in files: + self.fs.move( + file_path, + self.fs.sep.join([destination_path, os.path.basename(file_path)]), + **kw, + ) + + @deprecated("Please use _get_filesystem() instead and the fsspec API directly.") + def delete(self, relative_path) -> None: + self.fs.rm_file(relative_path) + + def action_test_config(self) -> None: + try: + self.fs.ls("", detail=False) + title = _("Connection Test Succeeded!") + message = _("Everything seems properly set up!") + msg_type = "success" + except Exception as err: + title = _("Connection Test Failed!") + message = str(err) + msg_type = "danger" + return { + "type": "ir.actions.client", + "tag": "display_notification", + "params": { + "title": title, + "message": message, + "type": msg_type, + "sticky": False, + }, + } diff --git a/fs_storage/odoo_file_system.py b/fs_storage/odoo_file_system.py new file mode 100644 index 0000000000..1827a31acc --- /dev/null +++ b/fs_storage/odoo_file_system.py @@ -0,0 +1,50 @@ +# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + + +from fsspec.registry import register_implementation + +from .rooted_dir_file_system import RootedDirFileSystem + + +class OdooFileSystem(RootedDirFileSystem): + """A directory-based filesystem for Odoo. + + This filesystem is mounted from a specific subdirectory of the Odoo + filestore directory. + + It extends the RootedDirFileSystem to avoid going outside the + specific subdirectory nor the Odoo filestore directory. + + Parameters: + odoo_storage_path: The path of the subdirectory of the Odoo filestore + directory to mount. This parameter is required and is always provided + by the Odoo FS Storage even if it is explicitly defined in the + storage options. + fs: AbstractFileSystem + An instantiated filesystem to wrap. + target_protocol, target_options: + if fs is none, construct it from these + """ + + def __init__( + self, + *, + odoo_storage_path, + fs=None, + target_protocol=None, + target_options=None, + **storage_options + ): + if not odoo_storage_path: + raise ValueError("odoo_storage_path is required") + super().__init__( + path=odoo_storage_path, + fs=fs, + target_protocol=target_protocol, + target_options=target_options, + **storage_options + ) + + +register_implementation("odoofs", OdooFileSystem) diff --git a/fs_storage/readme/CONTRIBUTORS.rst b/fs_storage/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..60c32f1d3f --- /dev/null +++ b/fs_storage/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Laurent Mignon +* Sébastien BEAU diff --git a/fs_storage/readme/DESCRIPTION.rst b/fs_storage/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..1cfc5c1a00 --- /dev/null +++ b/fs_storage/readme/DESCRIPTION.rst @@ -0,0 +1,63 @@ +This addon is a technical addon that allows you to define filesystem like +storage for your data. It's used by other addons to store their data in a +transparent way into different kind of storages. + +Through the fs.storage record, you get access to an object that implements +the `fsspec.spec.AbstractFileSystem `_ interface and therefore give +you an unified interface to access your data whatever the storage protocol you +decide to use. + +The list of supported protocols depends on the installed fsspec implementations. +By default, the addon will install the following protocols: + +* LocalFileSystem +* MemoryFileSystem +* ZipFileSystem +* TarFileSystem +* FTPFileSystem +* CachingFileSystem +* WholeFileSystem +* SimplCacheFileSystem +* ReferenceFileSystem +* GenericFileSystem +* DirFileSystem +* DatabricksFileSystem +* GitHubFileSystem +* JupiterFileSystem +* OdooFileSystem + +The OdooFileSystem is the one that allows you to store your data into a directory +mounted into your Odoo's storage directory. This is the default FS Storage +when creating a new fs.storage record. + +Others protocols are available through the installation of additional +python packages: + +* DropboxDriveFileSystem -> `pip install fsspec[dropbox]` +* HTTPFileSystem -> `pip install fsspec[http]` +* HTTPSFileSystem -> `pip install fsspec[http]` +* GCSFileSystem -> `pip install fsspec[gcs]` +* GSFileSystem -> `pip install fsspec[gs]` +* GoogleDriveFileSystem -> `pip install gdrivefs` +* SFTPFileSystem -> `pip install fsspec[sftp]` +* HaddoopFileSystem -> `pip install fsspec[hdfs]` +* S3FileSystem -> `pip install fsspec[s3]` +* WandbFS -> `pip install wandbfs` +* OCIFileSystem -> `pip install fsspec[oci]` +* AsyncLocalFileSystem -> `pip install 'morefs[asynclocalfs]` +* AzureDatalakeFileSystem -> `pip install fsspec[adl]` +* AzureBlobFileSystem -> `pip install fsspec[abfs]` +* DaskWorkerFileSystem -> `pip install fsspec[dask]` +* GitFileSystem -> `pip install fsspec[git]` +* SMBFileSystem -> `pip install fsspec[smb]` +* LibArchiveFileSystem -> `pip install fsspec[libarchive]` +* OSSFileSystem -> `pip install ossfs` +* WebdavFileSystem -> `pip install webdav4` +* DVCFileSystem -> `pip install dvc` +* XRootDFileSystem -> `pip install fsspec-xrootd` + +This list of supported protocols is not exhaustive or could change in the future +depending on the fsspec releases. You can find more information about the +supported protocols on the `fsspec documentation +`_. diff --git a/fs_storage/readme/HISTORY.rst b/fs_storage/readme/HISTORY.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/fs_storage/readme/ROADMAP.rst b/fs_storage/readme/ROADMAP.rst new file mode 100644 index 0000000000..0c697994d0 --- /dev/null +++ b/fs_storage/readme/ROADMAP.rst @@ -0,0 +1,9 @@ +* Transactions: fsspec comes with a transactional mechanism that once started, + gathers all the files created during the transaction, and if the transaction + is committed, moves them to their final locations. It would be useful to + bridge this with the transactional mechanism of odoo. This would allow to + ensure that all the files created during a transaction are either all + moved to their final locations, or all deleted if the transaction is rolled + back. This mechanism is only valid for files created during the transaction + by a call to the `open` method of the file system. It is not valid for others + operations, such as `rm`, `mv_file`, ... . diff --git a/fs_storage/readme/USAGE.rst b/fs_storage/readme/USAGE.rst new file mode 100644 index 0000000000..f65fb39af2 --- /dev/null +++ b/fs_storage/readme/USAGE.rst @@ -0,0 +1,84 @@ +Configuration +~~~~~~~~~~~~~ + +When you create a new backend, you must specify the following: + +* The name of the backend. This is the name that will be used to + identify the backend into Odoo +* The code of the backend. This code will identify the backend into the store_fname + field of the ir.attachment model. This code must be unique. It will be used + as scheme. example of the store_fname field: ``odoofs://abs34Tg11``. +* The protocol used by the backend. The protocol refers to the supported + protocols of the fsspec python package. +* A directory path. This is a root directory from which the filesystem will + be mounted. This directory must exist. +* The protocol options. These are the options that will be passed to the + fsspec python package when creating the filesystem. These options depend + on the protocol used and are described in the fsspec documentation. + +Some protocols defined in the fsspec package are wrappers around other +protocols. For example, the SimpleCacheFileSystem protocol is a wrapper +around any local filesystem protocol. In such cases, you must specify into the +protocol options the protocol to be wrapped and the options to be passed to +the wrapped protocol. + +For example, if you want to create a backend that uses the SimpleCacheFileSystem +protocol, after selecting the SimpleCacheFileSystem protocol, you must specify +the protocol options as follows: + +.. code-block:: python + + { + "directory_path": "/tmp/my_backend", + "target_protocol": "odoofs", + "target_options": {...}, + } + +In this example, the SimpleCacheFileSystem protocol will be used as a wrapper +around the odoofs protocol. + +Server Environment +~~~~~~~~~~~~~~~~~~ + +To ease the management of the filesystem storages configuration accross the different +environments, the configuration of the filesystem storages can be defined in +environment files or directly in the main configuration file. For example, the +configuration of a filesystem storage with the code `fsprod` can be provided in the +main configuration file as follows: + +.. code-block:: ini + + [fs_storage.fsprod] + protocol=s3 + options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"} + directory_path=my_bucket + +To work, a `storage.backend` record must exist with the code `fsprod` into the database. +In your configuration section, you can specify the value for the following fields: + +* `protocol` +* `options` +* `directory_path` + +Migration from storage_backend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The fs_storage addon can be used to replace the storage_backend addon. (It has +been designed to be a drop-in replacement for the storage_backend addon). To +ease the migration, the `fs.storage` model defines the high-level methods +available in the storage_backend model. These methods are: + +* `add` +* `get` +* `list_files` +* `find_files` +* `move_files` +* `delete` + +These methods are wrappers around the methods of the `fsspec.AbstractFileSystem` +class (see https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem). +These methods are marked as deprecated and will be removed in a future version (V18) +of the addon. You should use the methods of the `fsspec.AbstractFileSystem` class +instead since they are more flexible and powerful. You can access the instance +of the `fsspec.AbstractFileSystem` class using the `fs` property of a `fs.storage` +record. diff --git a/fs_storage/rooted_dir_file_system.py b/fs_storage/rooted_dir_file_system.py new file mode 100644 index 0000000000..8fb401685f --- /dev/null +++ b/fs_storage/rooted_dir_file_system.py @@ -0,0 +1,37 @@ +# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import os + +from fsspec.implementations.dirfs import DirFileSystem +from fsspec.implementations.local import make_path_posix +from fsspec.registry import register_implementation + + +class RootedDirFileSystem(DirFileSystem): + """A directory-based filesystem that uses path as a root. + + The main purpose of this filesystem is to ensure that paths are always + a sub path of the initial path. IOW, it is not possible to go outside + the initial path. That's the only difference with the DirFileSystem provided + by fsspec. + + This one should be provided by fsspec itself. We should propose a PR. + """ + + def _join(self, path): + path = super()._join(path) + # Ensure that the path is a subpath of the root path by resolving + # any relative paths. + # Since the path separator is not always the same on all systems, + # we need to normalize the path separator. + path_posix = os.path.normpath(make_path_posix(path, self.sep)) + root_posix = os.path.normpath(make_path_posix(self.path)) + if not path_posix.startswith(root_posix): + raise PermissionError( + "Path %s is not a subpath of the root path %s" % (path, self.path) + ) + return path + + +register_implementation("rooted_dir", RootedDirFileSystem) diff --git a/fs_storage/security/ir.model.access.csv b/fs_storage/security/ir.model.access.csv new file mode 100644 index 0000000000..9c079b2eef --- /dev/null +++ b/fs_storage/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_fs_storage_edit,fs_storage edit,model_fs_storage,base.group_system,1,1,1,1 diff --git a/fs_storage/static/description/icon.png b/fs_storage/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html new file mode 100644 index 0000000000..e1730e320d --- /dev/null +++ b/fs_storage/static/description/index.html @@ -0,0 +1,563 @@ + + + + + + +Filesystem Storage Backend + + + +
+

Filesystem Storage Backend

+ + +

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runbot

+

This addon is a technical addon that allows you to define filesystem like +storage for your data. It’s used by other addons to store their data in a +transparent way into different kind of storages.

+

Through the fs.storage record, you get access to an object that implements +the fsspec.spec.AbstractFileSystem interface and therefore give +you an unified interface to access your data whatever the storage protocol you +decide to use.

+

The list of supported protocols depends on the installed fsspec implementations. +By default, the addon will install the following protocols:

+
    +
  • LocalFileSystem
  • +
  • MemoryFileSystem
  • +
  • ZipFileSystem
  • +
  • TarFileSystem
  • +
  • FTPFileSystem
  • +
  • CachingFileSystem
  • +
  • WholeFileSystem
  • +
  • SimplCacheFileSystem
  • +
  • ReferenceFileSystem
  • +
  • GenericFileSystem
  • +
  • DirFileSystem
  • +
  • DatabricksFileSystem
  • +
  • GitHubFileSystem
  • +
  • JupiterFileSystem
  • +
  • OdooFileSystem
  • +
+

The OdooFileSystem is the one that allows you to store your data into a directory +mounted into your Odoo’s storage directory. This is the default FS Storage +when creating a new fs.storage record.

+

Others protocols are available through the installation of additional +python packages:

+
    +
  • DropboxDriveFileSystem -> pip install fsspec[dropbox]
  • +
  • HTTPFileSystem -> pip install fsspec[http]
  • +
  • HTTPSFileSystem -> pip install fsspec[http]
  • +
  • GCSFileSystem -> pip install fsspec[gcs]
  • +
  • GSFileSystem -> pip install fsspec[gs]
  • +
  • GoogleDriveFileSystem -> pip install gdrivefs
  • +
  • SFTPFileSystem -> pip install fsspec[sftp]
  • +
  • HaddoopFileSystem -> pip install fsspec[hdfs]
  • +
  • S3FileSystem -> pip install fsspec[s3]
  • +
  • WandbFS -> pip install wandbfs
  • +
  • OCIFileSystem -> pip install fsspec[oci]
  • +
  • AsyncLocalFileSystem -> pip install ‘morefs[asynclocalfs]
  • +
  • AzureDatalakeFileSystem -> pip install fsspec[adl]
  • +
  • AzureBlobFileSystem -> pip install fsspec[abfs]
  • +
  • DaskWorkerFileSystem -> pip install fsspec[dask]
  • +
  • GitFileSystem -> pip install fsspec[git]
  • +
  • SMBFileSystem -> pip install fsspec[smb]
  • +
  • LibArchiveFileSystem -> pip install fsspec[libarchive]
  • +
  • OSSFileSystem -> pip install ossfs
  • +
  • WebdavFileSystem -> pip install webdav4
  • +
  • DVCFileSystem -> pip install dvc
  • +
  • XRootDFileSystem -> pip install fsspec-xrootd
  • +
+

This list of supported protocols is not exhaustive or could change in the future +depending on the fsspec releases. You can find more information about the +supported protocols on the fsspec documentation.

+

Table of contents

+ +
+

Usage

+
+

Configuration

+

When you create a new backend, you must specify the following:

+
    +
  • The name of the backend. This is the name that will be used to +identify the backend into Odoo
  • +
  • The code of the backend. This code will identify the backend into the store_fname +field of the ir.attachment model. This code must be unique. It will be used +as scheme. example of the store_fname field: odoofs://abs34Tg11.
  • +
  • The protocol used by the backend. The protocol refers to the supported +protocols of the fsspec python package.
  • +
  • A directory path. This is a root directory from which the filesystem will +be mounted. This directory must exist.
  • +
  • The protocol options. These are the options that will be passed to the +fsspec python package when creating the filesystem. These options depend +on the protocol used and are described in the fsspec documentation.
  • +
+

Some protocols defined in the fsspec package are wrappers around other +protocols. For example, the SimpleCacheFileSystem protocol is a wrapper +around any local filesystem protocol. In such cases, you must specify into the +protocol options the protocol to be wrapped and the options to be passed to +the wrapped protocol.

+

For example, if you want to create a backend that uses the SimpleCacheFileSystem +protocol, after selecting the SimpleCacheFileSystem protocol, you must specify +the protocol options as follows:

+
+{
+    "directory_path": "/tmp/my_backend",
+    "target_protocol": "odoofs",
+    "target_options": {...},
+}
+
+

In this example, the SimpleCacheFileSystem protocol will be used as a wrapper +around the odoofs protocol.

+
+
+

Server Environment

+

To ease the management of the filesystem storages configuration accross the different +environments, the configuration of the filesystem storages can be defined in +environment files or directly in the main configuration file. For example, the +configuration of a filesystem storage with the code fsprod can be provided in the +main configuration file as follows:

+
+[fs_storage.fsprod]
+protocol=s3
+options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"}
+directory_path=my_bucket
+
+

To work, a storage.backend record must exist with the code fsprod into the database. +In your configuration section, you can specify the value for the following fields:

+
    +
  • protocol
  • +
  • options
  • +
  • directory_path
  • +
+
+
+
+

Known issues / Roadmap

+
    +
  • Transactions: fsspec comes with a transactional mechanism that once started, +gathers all the files created during the transaction, and if the transaction +is committed, moves them to their final locations. It would be useful to +bridge this with the transactional mechanism of odoo. This would allow to +ensure that all the files created during a transaction are either all +moved to their final locations, or all deleted if the transaction is rolled +back. This mechanism is only valid for files created during the transaction +by a call to the open method of the file system. It is not valid for others +operations, such as rm, mv_file, … .
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/storage project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/fs_storage/tests/__init__.py b/fs_storage/tests/__init__.py new file mode 100644 index 0000000000..84bbda192b --- /dev/null +++ b/fs_storage/tests/__init__.py @@ -0,0 +1 @@ +from . import test_fs_storage diff --git a/fs_storage/tests/test_fs_storage.py b/fs_storage/tests/test_fs_storage.py new file mode 100644 index 0000000000..74dfde8814 --- /dev/null +++ b/fs_storage/tests/test_fs_storage.py @@ -0,0 +1,153 @@ +# Copyright 2023 ACSONE SA/NV (http://acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +import base64 +import shutil +import tempfile +import warnings +from unittest import mock + +from odoo.tests.common import TransactionCase +from odoo.tools import mute_logger + +from ..models.fs_storage import FSStorage + + +class TestFSStorage(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.backend: FSStorage = cls.env.ref("fs_storage.default_fs_storage") + cls.backend.json_options = {"target_options": {"auto_mkdir": "True"}} + cls.filedata = base64.b64encode(b"This is a simple file") + cls.filename = "test_file.txt" + cls.case_with_subdirectory = "subdirectory/here" + cls.demo_user = cls.env.ref("base.user_demo") + + def setUp(self): + super().setUp() + mocked_backend = mock.patch.object( + self.backend.__class__, "_get_filesystem_storage_path" + ) + mocked_get_filesystem_storage_path = mocked_backend.start() + tempdir = tempfile.mkdtemp() + mocked_get_filesystem_storage_path.return_value = tempdir + + # pylint: disable=unused-variable + @self.addCleanup + def stop_mock(): + mocked_backend.stop() + # recursively delete the tempdir + shutil.rmtree(tempdir) + + def _create_file(self, backend: FSStorage, filename: str, filedata: str): + with backend.fs.open(filename, "wb") as f: + f.write(filedata) + + @mute_logger("py.warnings") + def _test_deprecated_setting_and_getting_data(self): + # Check that the directory is empty + warnings.filterwarnings("ignore") + files = self.backend.list_files() + self.assertNotIn(self.filename, files) + + # Add a new file + self.backend.add( + self.filename, self.filedata, mimetype="text/plain", binary=False + ) + + # Check that the file exist + files = self.backend.list_files() + self.assertIn(self.filename, files) + + # Retrieve the file added + data = self.backend.get(self.filename, binary=False) + self.assertEqual(data, self.filedata) + + # Delete the file + self.backend.delete(self.filename) + files = self.backend.list_files() + self.assertNotIn(self.filename, files) + + @mute_logger("py.warnings") + def _test_deprecated_find_files(self): + warnings.filterwarnings("ignore") + self.backend.add( + self.filename, self.filedata, mimetype="text/plain", binary=False + ) + try: + res = self.backend.find_files(r".*\.txt") + self.assertListEqual([self.filename], res) + res = self.backend.find_files(r".*\.text") + self.assertListEqual([], res) + finally: + self.backend.delete(self.filename) + + def test_deprecated_setting_and_getting_data_from_root(self): + self._test_deprecated_setting_and_getting_data() + + def test_deprecated_setting_and_getting_data_from_dir(self): + self.backend.directory_path = self.case_with_subdirectory + self._test_deprecated_setting_and_getting_data() + + def test_deprecated_find_files_from_root(self): + self._test_deprecated_find_files() + + def test_deprecated_find_files_from_dir(self): + self.backend.directory_path = self.case_with_subdirectory + self._test_deprecated_find_files() + + def test_ensure_one_fs_by_record(self): + # in this test we ensure that we've one fs by record + backend_ids = [] + for i in range(4): + backend_ids.append( + self.backend.create( + {"name": f"name{i}", "directory_path": f"{i}", "code": f"code{i}"} + ).id + ) + records = self.backend.browse(backend_ids) + fs = None + for rec in records: + self.assertNotEqual(fs, rec.fs) + + def test_relative_access(self): + self.backend.directory_path = self.case_with_subdirectory + self._create_file(self.backend, self.filename, self.filedata) + other_subdirectory = "other_subdirectory" + backend2 = self.backend.copy({"directory_path": other_subdirectory}) + self._create_file(backend2, self.filename, self.filedata) + with self.assertRaises(PermissionError), self.env.cr.savepoint(): + # check that we can't access outside the subdirectory + backend2.fs.ls("../") + with self.assertRaises(PermissionError), self.env.cr.savepoint(): + # check that we can't access the file into another subdirectory + backend2.fs.ls(f"../{self.case_with_subdirectory}") + self.backend.fs.rm_file(self.filename) + backend2.fs.rm_file(self.filename) + + def test_recursive_add_odoo_storage_path_to_options(self): + options = { + "directory_path": "/tmp/my_backend", + "target_protocol": "odoofs", + } + self.backend._recursive_add_odoo_storage_path(options) + self.assertEqual( + self.backend._odoo_storage_path, + options.get("target_options").get("odoo_storage_path"), + ) + options = { + "directory_path": "/tmp/my_backend", + "target_protocol": "dir", + "target_options": { + "path": "/my_backend", + "target_protocol": "odoofs", + }, + } + self.backend._recursive_add_odoo_storage_path(options) + self.assertEqual( + self.backend._odoo_storage_path, + options.get("target_options") + .get("target_options") + .get("odoo_storage_path"), + ) diff --git a/fs_storage/views/fs_storage_view.xml b/fs_storage/views/fs_storage_view.xml new file mode 100644 index 0000000000..3027f29152 --- /dev/null +++ b/fs_storage/views/fs_storage_view.xml @@ -0,0 +1,117 @@ + + + + fs.storage.tree (in fs_storage) + fs.storage + + + + + + + + + + fs.storage.form (in fs_storage) + fs.storage + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + fs.storage.search (in fs_storage) + fs.storage + + + + + + + + + FS Storage + ir.actions.act_window + fs.storage + tree,form + + [] + {} + + + + + form + + + + + + tree + + + + +
From dcc6ddb55e9a0c1bac9d3a2f0a7ccfee72fe30ab Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 24 Aug 2023 08:56:13 +0000 Subject: [PATCH 02/54] [UPD] Update fs_storage.pot --- fs_storage/i18n/fs_storage.pot | 238 +++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 fs_storage/i18n/fs_storage.pot diff --git a/fs_storage/i18n/fs_storage.pot b/fs_storage/i18n/fs_storage.pot new file mode 100644 index 0000000000..e9d28c1b02 --- /dev/null +++ b/fs_storage/i18n/fs_storage.pot @@ -0,0 +1,238 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fs_storage +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Available options" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_properties +msgid "Available properties" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__code +msgid "Code" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Connection Test Failed!" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Connection Test Succeeded!" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_uid +msgid "Created by" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_date +msgid "Created on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_protocol +msgid "Describes Protocol" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path +msgid "Directory Path" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_default +msgid "Directory Path Env Default" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_is_editable +msgid "Directory Path Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name +msgid "Display Name" +msgstr "" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Enter you fsspec options here." +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Everything seems properly set up!" +msgstr "" + +#. module: fs_storage +#: model:ir.actions.act_window,name:fs_storage.act_open_fs_storage_view +#: model:ir.model,name:fs_storage.model_fs_storage +#: model:ir.ui.menu,name:fs_storage.menu_fs_storage +#: model:ir.ui.menu,name:fs_storage.menu_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_search_view +msgid "FS Storage" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__id +msgid "ID" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__json_options +msgid "Json Options" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage____last_update +msgid "Last Modified on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_date +msgid "Last Updated on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__name +msgid "Name" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options +msgid "Options" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_default +msgid "Options Env Default" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_is_editable +msgid "Options Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol +msgid "Protocol" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_descr +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Protocol Descr" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_default +msgid "Protocol Env Default" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_is_editable +msgid "Protocol Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path +#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path_env_default +msgid "Relative path to the directory to store the file" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__server_env_defaults +msgid "Server Env Defaults" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__code +msgid "" +"Technical code used to identify the storage backend into the code.This code " +"must be unique. This code is used for example to define the storage backend " +"to store the attachments via the configuration parameter " +"'ir_attachment.storage.force.database' when the module 'fs_attachment' is " +"installed." +msgstr "" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Test connection" +msgstr "" + +#. module: fs_storage +#: model:ir.model.constraint,message:fs_storage.constraint_fs_storage_code_uniq +msgid "The code must be unique" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "The options must be a valid JSON" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__json_options +msgid "The options used to initialize the filesystem.\n" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__options +#: model:ir.model.fields,help:fs_storage.field_fs_storage__options_env_default +msgid "" +"The options used to initialize the filesystem.\n" +"This is a JSON field that depends on the protocol used.\n" +"For example, for the sftp protocol, you can provide the following:\n" +"{\n" +" 'host': 'my.sftp.server',\n" +" 'ssh_kwrags': {\n" +" 'username': 'myuser',\n" +" 'password': 'mypassword',\n" +" 'port': 22,\n" +" }\n" +"}\n" +"For more information, please refer to the fsspec documentation:\n" +"https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-implementations" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__options_protocol +#: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol +#: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol_env_default +msgid "" +"The protocol used to access the content of filesystem.\n" +"This list is the one supported by the fsspec library (see https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocolis added by default and refers to the odoo local filesystem.\n" +"Pay attention that according to the protocol, some options must beprovided through the options field." +msgstr "" From 29040f54a0182bb2ac8ad7ec446b9ad8aa72a186 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 24 Aug 2023 08:58:12 +0000 Subject: [PATCH 03/54] [UPD] README.rst --- fs_storage/README.rst | 248 ++++++++++++++++++++--- fs_storage/static/description/index.html | 66 +++--- 2 files changed, 266 insertions(+), 48 deletions(-) diff --git a/fs_storage/README.rst b/fs_storage/README.rst index 38929e8775..83f613a370 100644 --- a/fs_storage/README.rst +++ b/fs_storage/README.rst @@ -1,35 +1,237 @@ -**This file is going to be generated by oca-gen-addon-readme.** +========================== +Filesystem Storage Backend +========================== -*Manual changes will be overwritten.* +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -Please provide content in the ``readme`` directory: +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github + :target: https://github.com/OCA/storage/tree/16.0/fs_storage + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-fs_storage + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/275/16.0 + :alt: Try me on Runbot -* **DESCRIPTION.rst** (required) -* INSTALL.rst (optional) -* CONFIGURE.rst (optional) -* **USAGE.rst** (optional, highly recommended) -* DEVELOP.rst (optional) -* ROADMAP.rst (optional) -* HISTORY.rst (optional, recommended) -* **CONTRIBUTORS.rst** (optional, highly recommended) -* CREDITS.rst (optional) +|badge1| |badge2| |badge3| |badge4| |badge5| -Content of this README will also be drawn from the addon manifest, -from keys such as name, authors, maintainers, development_status, -and license. +This addon is a technical addon that allows you to define filesystem like +storage for your data. It's used by other addons to store their data in a +transparent way into different kind of storages. -A good, one sentence summary in the manifest is also highly recommended. +Through the fs.storage record, you get access to an object that implements +the `fsspec.spec.AbstractFileSystem `_ interface and therefore give +you an unified interface to access your data whatever the storage protocol you +decide to use. +The list of supported protocols depends on the installed fsspec implementations. +By default, the addon will install the following protocols: -Automatic changelog generation +* LocalFileSystem +* MemoryFileSystem +* ZipFileSystem +* TarFileSystem +* FTPFileSystem +* CachingFileSystem +* WholeFileSystem +* SimplCacheFileSystem +* ReferenceFileSystem +* GenericFileSystem +* DirFileSystem +* DatabricksFileSystem +* GitHubFileSystem +* JupiterFileSystem +* OdooFileSystem + +The OdooFileSystem is the one that allows you to store your data into a directory +mounted into your Odoo's storage directory. This is the default FS Storage +when creating a new fs.storage record. + +Others protocols are available through the installation of additional +python packages: + +* DropboxDriveFileSystem -> `pip install fsspec[dropbox]` +* HTTPFileSystem -> `pip install fsspec[http]` +* HTTPSFileSystem -> `pip install fsspec[http]` +* GCSFileSystem -> `pip install fsspec[gcs]` +* GSFileSystem -> `pip install fsspec[gs]` +* GoogleDriveFileSystem -> `pip install gdrivefs` +* SFTPFileSystem -> `pip install fsspec[sftp]` +* HaddoopFileSystem -> `pip install fsspec[hdfs]` +* S3FileSystem -> `pip install fsspec[s3]` +* WandbFS -> `pip install wandbfs` +* OCIFileSystem -> `pip install fsspec[oci]` +* AsyncLocalFileSystem -> `pip install 'morefs[asynclocalfs]` +* AzureDatalakeFileSystem -> `pip install fsspec[adl]` +* AzureBlobFileSystem -> `pip install fsspec[abfs]` +* DaskWorkerFileSystem -> `pip install fsspec[dask]` +* GitFileSystem -> `pip install fsspec[git]` +* SMBFileSystem -> `pip install fsspec[smb]` +* LibArchiveFileSystem -> `pip install fsspec[libarchive]` +* OSSFileSystem -> `pip install ossfs` +* WebdavFileSystem -> `pip install webdav4` +* DVCFileSystem -> `pip install dvc` +* XRootDFileSystem -> `pip install fsspec-xrootd` + +This list of supported protocols is not exhaustive or could change in the future +depending on the fsspec releases. You can find more information about the +supported protocols on the `fsspec documentation +`_. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Configuration +~~~~~~~~~~~~~ + +When you create a new backend, you must specify the following: + +* The name of the backend. This is the name that will be used to + identify the backend into Odoo +* The code of the backend. This code will identify the backend into the store_fname + field of the ir.attachment model. This code must be unique. It will be used + as scheme. example of the store_fname field: ``odoofs://abs34Tg11``. +* The protocol used by the backend. The protocol refers to the supported + protocols of the fsspec python package. +* A directory path. This is a root directory from which the filesystem will + be mounted. This directory must exist. +* The protocol options. These are the options that will be passed to the + fsspec python package when creating the filesystem. These options depend + on the protocol used and are described in the fsspec documentation. + +Some protocols defined in the fsspec package are wrappers around other +protocols. For example, the SimpleCacheFileSystem protocol is a wrapper +around any local filesystem protocol. In such cases, you must specify into the +protocol options the protocol to be wrapped and the options to be passed to +the wrapped protocol. + +For example, if you want to create a backend that uses the SimpleCacheFileSystem +protocol, after selecting the SimpleCacheFileSystem protocol, you must specify +the protocol options as follows: + +.. code-block:: python + + { + "directory_path": "/tmp/my_backend", + "target_protocol": "odoofs", + "target_options": {...}, + } + +In this example, the SimpleCacheFileSystem protocol will be used as a wrapper +around the odoofs protocol. + +Server Environment +~~~~~~~~~~~~~~~~~~ + +To ease the management of the filesystem storages configuration accross the different +environments, the configuration of the filesystem storages can be defined in +environment files or directly in the main configuration file. For example, the +configuration of a filesystem storage with the code `fsprod` can be provided in the +main configuration file as follows: + +.. code-block:: ini + + [fs_storage.fsprod] + protocol=s3 + options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"} + directory_path=my_bucket + +To work, a `storage.backend` record must exist with the code `fsprod` into the database. +In your configuration section, you can specify the value for the following fields: + +* `protocol` +* `options` +* `directory_path` + +Migration from storage_backend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -`HISTORY.rst` can be auto generated using `towncrier `_. +The fs_storage addon can be used to replace the storage_backend addon. (It has +been designed to be a drop-in replacement for the storage_backend addon). To +ease the migration, the `fs.storage` model defines the high-level methods +available in the storage_backend model. These methods are: + +* `add` +* `get` +* `list_files` +* `find_files` +* `move_files` +* `delete` + +These methods are wrappers around the methods of the `fsspec.AbstractFileSystem` +class (see https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem). +These methods are marked as deprecated and will be removed in a future version (V18) +of the addon. You should use the methods of the `fsspec.AbstractFileSystem` class +instead since they are more flexible and powerful. You can access the instance +of the `fsspec.AbstractFileSystem` class using the `fs` property of a `fs.storage` +record. + +Known issues / Roadmap +====================== + +* Transactions: fsspec comes with a transactional mechanism that once started, + gathers all the files created during the transaction, and if the transaction + is committed, moves them to their final locations. It would be useful to + bridge this with the transactional mechanism of odoo. This would allow to + ensure that all the files created during a transaction are either all + moved to their final locations, or all deleted if the transaction is rolled + back. This mechanism is only valid for files created during the transaction + by a call to the `open` method of the file system. It is not valid for others + operations, such as `rm`, `mv_file`, ... . + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ACSONE SA/NV + +Contributors +~~~~~~~~~~~~ + +* Laurent Mignon +* Sébastien BEAU + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org -Just put towncrier compatible changelog fragments into `readme/newsfragments` -and the changelog file will be automatically generated and updated when a new fragment is added. +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. -Please refer to `towncrier` documentation to know more. +This module is part of the `OCA/storage `_ project on GitHub. -NOTE: the changelog will be automatically generated when using `/ocabot merge $option`. -If you need to run it manually, refer to `OCA/maintainer-tools README `_. +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html index e1730e320d..08f58cf000 100644 --- a/fs_storage/static/description/index.html +++ b/fs_storage/static/description/index.html @@ -3,7 +3,7 @@ - + Filesystem Storage Backend - - -
-

Filesystem Storage Backend

- - -

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

-

This addon is a technical addon that allows you to define filesystem -like storage for your data. It’s used by other addons to store their -data in a transparent way into different kind of storages.

-

Through the fs.storage record, you get access to an object that -implements the -fsspec.spec.AbstractFileSystem -interface and therefore give you an unified interface to access your -data whatever the storage protocol you decide to use.

-

The list of supported protocols depends on the installed fsspec -implementations. By default, the addon will install the following -protocols:

-
    -
  • LocalFileSystem
  • -
  • MemoryFileSystem
  • -
  • ZipFileSystem
  • -
  • TarFileSystem
  • -
  • FTPFileSystem
  • -
  • CachingFileSystem
  • -
  • WholeFileSystem
  • -
  • SimplCacheFileSystem
  • -
  • ReferenceFileSystem
  • -
  • GenericFileSystem
  • -
  • DirFileSystem
  • -
  • DatabricksFileSystem
  • -
  • GitHubFileSystem
  • -
  • JupiterFileSystem
  • -
  • OdooFileSystem
  • -
-

The OdooFileSystem is the one that allows you to store your data into a -directory mounted into your Odoo’s storage directory. This is the -default FS Storage when creating a new fs.storage record.

-

Others protocols are available through the installation of additional -python packages:

-
    -
  • DropboxDriveFileSystem -> pip install fsspec[dropbox]
  • -
  • HTTPFileSystem -> pip install fsspec[http]
  • -
  • HTTPSFileSystem -> pip install fsspec[http]
  • -
  • GCSFileSystem -> pip install fsspec[gcs]
  • -
  • GSFileSystem -> pip install fsspec[gs]
  • -
  • GoogleDriveFileSystem -> pip install gdrivefs
  • -
  • SFTPFileSystem -> pip install fsspec[sftp]
  • -
  • HaddoopFileSystem -> pip install fsspec[hdfs]
  • -
  • S3FileSystem -> pip install fsspec[s3]
  • -
  • WandbFS -> pip install wandbfs
  • -
  • OCIFileSystem -> pip install fsspec[oci]
  • -
  • AsyncLocalFileSystem -> pip install ‘morefs[asynclocalfs]
  • -
  • AzureDatalakeFileSystem -> pip install fsspec[adl]
  • -
  • AzureBlobFileSystem -> pip install fsspec[abfs]
  • -
  • DaskWorkerFileSystem -> pip install fsspec[dask]
  • -
  • GitFileSystem -> pip install fsspec[git]
  • -
  • SMBFileSystem -> pip install fsspec[smb]
  • -
  • LibArchiveFileSystem -> pip install fsspec[libarchive]
  • -
  • OSSFileSystem -> pip install ossfs
  • -
  • WebdavFileSystem -> pip install webdav4
  • -
  • DVCFileSystem -> pip install dvc
  • -
  • XRootDFileSystem -> pip install fsspec-xrootd
  • -
-

This list of supported protocols is not exhaustive or could change in -the future depending on the fsspec releases. You can find more -information about the supported protocols on the fsspec -documentation.

-

Table of contents

- -
-

Usage

-
-

Configuration

-

When you create a new backend, you must specify the following:

-
    -
  • The name of the backend. This is the name that will be used to -identify the backend into Odoo
  • -
  • The code of the backend. This code will identify the backend into the -store_fname field of the ir.attachment model. This code must be -unique. It will be used as scheme. example of the store_fname field: -odoofs://abs34Tg11.
  • -
  • The protocol used by the backend. The protocol refers to the -supported protocols of the fsspec python package.
  • -
  • A directory path. This is a root directory from which the filesystem -will be mounted. This directory must exist.
  • -
  • The protocol options. These are the options that will be passed to -the fsspec python package when creating the filesystem. These options -depend on the protocol used and are described in the fsspec -documentation.
  • -
  • Resolve env vars. This options resolves the protocol options values -starting with $ from environment variables
  • -
-

Some protocols defined in the fsspec package are wrappers around other -protocols. For example, the SimpleCacheFileSystem protocol is a wrapper -around any local filesystem protocol. In such cases, you must specify -into the protocol options the protocol to be wrapped and the options to -be passed to the wrapped protocol.

-

For example, if you want to create a backend that uses the -SimpleCacheFileSystem protocol, after selecting the -SimpleCacheFileSystem protocol, you must specify the protocol options as -follows:

-
-{
-    "directory_path": "/tmp/my_backend",
-    "target_protocol": "odoofs",
-    "target_options": {...},
-}
-
-

In this example, the SimpleCacheFileSystem protocol will be used as a -wrapper around the odoofs protocol.

-
-
-

Server Environment

-

To ease the management of the filesystem storages configuration accross -the different environments, the configuration of the filesystem storages -can be defined in environment files or directly in the main -configuration file. For example, the configuration of a filesystem -storage with the code fsprod can be provided in the main configuration -file as follows:

-
-[fs_storage.fsprod]
-protocol=s3
-options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"}
-directory_path=my_bucket
-
-

To work, a storage.backend record must exist with the code fsprod into -the database. In your configuration section, you can specify the value -for the following fields:

-
    -
  • protocol
  • -
  • options
  • -
  • directory_path
  • -
-
-
-

Migration from storage_backend

-

The fs_storage addon can be used to replace the storage_backend addon. -(It has been designed to be a drop-in replacement for the -storage_backend addon). To ease the migration, the fs.storage model -defines the high-level methods available in the storage_backend model. -These methods are:

-
    -
  • add
  • -
  • get
  • -
  • list_files
  • -
  • find_files
  • -
  • move_files
  • -
  • delete
  • -
-

These methods are wrappers around the methods of the -fsspec.AbstractFileSystem class (see -https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem). -These methods are marked as deprecated and will be removed in a future -version (V18) of the addon. You should use the methods of the -fsspec.AbstractFileSystem class instead since they are more flexible and -powerful. You can access the instance of the fsspec.AbstractFileSystem -class using the fs property of a fs.storage record.

-
-
-
-

Known issues / Roadmap

-
    -
  • Transactions: fsspec comes with a transactional mechanism that once -started, gathers all the files created during the transaction, and if -the transaction is committed, moves them to their final locations. It -would be useful to bridge this with the transactional mechanism of -odoo. This would allow to ensure that all the files created during a -transaction are either all moved to their final locations, or all -deleted if the transaction is rolled back. This mechanism is only -valid for files created during the transaction by a call to the open -method of the file system. It is not valid for others operations, -such as rm, mv_file, … .
  • -
-
-
-

Changelog

-
-

16.0.1.1.0 (2023-12-22)

-

Features

-
    -
  • Add parameter on storage backend to resolve protocol options values -starting with $ from environment variables -(#303)
  • -
-
-
-

16.0.1.0.3 (2023-10-17)

-

Bugfixes

-
    -
  • Fix access to technical models to be able to upload attachments for -users with basic access -(#289)
  • -
-
-
-

16.0.1.0.2 (2023-10-09)

-

Bugfixes

-
    -
  • Avoid config error when using the webdav protocol. The auth option is -expected to be a tuple not a list. Since our config is loaded from a -json file, we cannot use tuples. The fix converts the list to a tuple -when the config is related to a webdav protocol and the auth option -is into the confix. -(#285)
  • -
-
-
-
-

Bug Tracker

-

Bugs are tracked on GitHub Issues. -In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

-

Do not contact contributors directly about support or help with technical issues.

-
-
-

Credits

-
-

Authors

-
    -
  • ACSONE SA/NV
  • -
-
-
-

Contributors

- -
-
-

Maintainers

-

This module is maintained by the OCA.

-Odoo Community Association -

OCA, or the Odoo Community Association, is a nonprofit organization whose -mission is to support the collaborative development of Odoo features and -promote its widespread use.

-

This module is part of the OCA/storage project on GitHub.

-

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

-
-
-
- + + + + Filesystem Storage Backend + + + +
+

Filesystem Storage Backend

+ + +

+ + Beta + + + License: LGPL-3 + + + OCA/storage + + + Translate me on Weblate + + + Try me on Runboat + +

+

This addon is a technical addon that allows you to define filesystem + like storage for your data. It’s used by other addons to store their + data in a transparent way into different kind of storages. +

+

Through the fs.storage record, you get access to an object that + implements the + + fsspec.spec.AbstractFileSystem + + interface and therefore give you an unified interface to access your + data whatever the storage protocol you decide to use. +

+

The list of supported protocols depends on the installed fsspec + implementations. By default, the addon will install the following + protocols: +

+
    +
  • LocalFileSystem
  • +
  • MemoryFileSystem
  • +
  • ZipFileSystem
  • +
  • TarFileSystem
  • +
  • FTPFileSystem
  • +
  • CachingFileSystem
  • +
  • WholeFileSystem
  • +
  • SimplCacheFileSystem
  • +
  • ReferenceFileSystem
  • +
  • GenericFileSystem
  • +
  • DirFileSystem
  • +
  • DatabricksFileSystem
  • +
  • GitHubFileSystem
  • +
  • JupiterFileSystem
  • +
  • OdooFileSystem
  • +
+

The OdooFileSystem is the one that allows you to store your data into a + directory mounted into your Odoo’s storage directory. This is the + default FS Storage when creating a new fs.storage record. +

+

Others protocols are available through the installation of additional + python packages: +

+
    +
  • DropboxDriveFileSystem -> pip install fsspec[dropbox]
  • +
  • HTTPFileSystem -> pip install fsspec[http]
  • +
  • HTTPSFileSystem -> pip install fsspec[http]
  • +
  • GCSFileSystem -> pip install fsspec[gcs]
  • +
  • GSFileSystem -> pip install fsspec[gs]
  • +
  • GoogleDriveFileSystem -> pip install gdrivefs
  • +
  • SFTPFileSystem -> pip install fsspec[sftp]
  • +
  • HaddoopFileSystem -> pip install fsspec[hdfs]
  • +
  • S3FileSystem -> pip install fsspec[s3]
  • +
  • WandbFS -> pip install wandbfs
  • +
  • OCIFileSystem -> pip install fsspec[oci]
  • +
  • AsyncLocalFileSystem -> pip install ‘morefs[asynclocalfs]
  • +
  • AzureDatalakeFileSystem -> pip install fsspec[adl]
  • +
  • AzureBlobFileSystem -> pip install fsspec[abfs]
  • +
  • DaskWorkerFileSystem -> pip install fsspec[dask]
  • +
  • GitFileSystem -> pip install fsspec[git]
  • +
  • SMBFileSystem -> pip install fsspec[smb]
  • +
  • LibArchiveFileSystem -> pip install fsspec[libarchive]
  • +
  • OSSFileSystem -> pip install ossfs
  • +
  • WebdavFileSystem -> pip install webdav4
  • +
  • DVCFileSystem -> pip install dvc
  • +
  • XRootDFileSystem -> pip install fsspec-xrootd
  • +
+

This list of supported protocols is not exhaustive or could change in + the future depending on the fsspec releases. You can find more + information about the supported protocols on the + fsspec + documentation. +

+

+ Table of contents +

+ +
+

+ Usage +

+
+

+ Configuration +

+

When you create a new backend, you must specify the following:

+
    +
  • The name of the backend. This is the name that will be used to + identify the backend into Odoo +
  • +
  • The code of the backend. This code will identify the backend into the + store_fname field of the ir.attachment model. This code must be + unique. It will be used as scheme. example of the store_fname field: + + odoofs://abs34Tg11 + + . +
  • +
  • The protocol used by the backend. The protocol refers to the + supported protocols of the fsspec python package. +
  • +
  • A directory path. This is a root directory from which the filesystem + will be mounted. This directory must exist. +
  • +
  • The protocol options. These are the options that will be passed to + the fsspec python package when creating the filesystem. These options + depend on the protocol used and are described in the fsspec + documentation. +
  • +
  • Resolve env vars. This options resolves the protocol options values + starting with $ from environment variables +
  • +
+

Some protocols defined in the fsspec package are wrappers around other + protocols. For example, the SimpleCacheFileSystem protocol is a wrapper + around any local filesystem protocol. In such cases, you must specify + into the protocol options the protocol to be wrapped and the options to + be passed to the wrapped protocol. +

+

For example, if you want to create a backend that uses the + SimpleCacheFileSystem protocol, after selecting the + SimpleCacheFileSystem protocol, you must specify the protocol options as + follows: +

+
+                        {
+                        
+                        
+                        "directory_path"
+                        :
+                        "/tmp/my_backend"
+                        ,
+                        
+                        
+                        "target_protocol"
+                        :
+                        "odoofs"
+                        ,
+                        
+                        
+                        "target_options"
+                        :
+                        {
+                        ...
+                        },
+                        
+                        
+                        }
+                    
+

In this example, the SimpleCacheFileSystem protocol will be used as a + wrapper around the odoofs protocol. +

+
+
+

+ Server Environment +

+

To ease the management of the filesystem storages configuration accross + the different environments, the configuration of the filesystem storages + can be defined in environment files or directly in the main + configuration file. For example, the configuration of a filesystem + storage with the code fsprod can be provided in the main configuration + file as follows: +

+
+                        [fs_storage.fsprod]
+                        
+                        
+                        protocol
+                        =
+                        s3
+                        
+                        
+                        options
+                        =
+                        {"endpoint_url": "https://my_s3_server/", "key":
+                            "KEY", "secret": "SECRET"}
+                        
+                        
+                        
+                        directory_path
+                        =
+                        my_bucket
+                    
+

To work, a storage.backend record must exist with the code fsprod into + the database. In your configuration section, you can specify the value + for the following fields: +

+
    +
  • protocol
  • +
  • options
  • +
  • directory_path
  • +
+
+
+

+ Migration from storage_backend +

+

The fs_storage addon can be used to replace the storage_backend addon. + (It has been designed to be a drop-in replacement for the + storage_backend addon). To ease the migration, the fs.storage model + defines the high-level methods available in the storage_backend model. + These methods are: +

+
    +
  • add
  • +
  • get
  • +
  • list_files
  • +
  • find_files
  • +
  • move_files
  • +
  • delete
  • +
+

These methods are wrappers around the methods of the + fsspec.AbstractFileSystem class (see + + https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem + ). + These methods are marked as deprecated and will be removed in a future + version (V18) of the addon. You should use the methods of the + fsspec.AbstractFileSystem class instead since they are more flexible and + powerful. You can access the instance of the fsspec.AbstractFileSystem + class using the fs property of a fs.storage record. +

+
+
+
+

+ Known issues / Roadmap +

+
    +
  • Transactions: fsspec comes with a transactional mechanism that once + started, gathers all the files created during the transaction, and if + the transaction is committed, moves them to their final locations. It + would be useful to bridge this with the transactional mechanism of + odoo. This would allow to ensure that all the files created during a + transaction are either all moved to their final locations, or all + deleted if the transaction is rolled back. This mechanism is only + valid for files created during the transaction by a call to the open + method of the file system. It is not valid for others operations, + such as rm, mv_file, … . +
  • +
+
+
+

+ Changelog +

+
+

+ 16.0.1.1.0 (2023-12-22) +

+

+ Features +

+
    +
  • Add parameter on storage backend to resolve protocol options values + starting with $ from environment variables + (#303) +
  • +
+
+
+

+ 16.0.1.0.3 (2023-10-17) +

+

+ Bugfixes +

+
    +
  • Fix access to technical models to be able to upload attachments for + users with basic access + (#289) +
  • +
+
+
+

+ 16.0.1.0.2 (2023-10-09) +

+

+ Bugfixes +

+
    +
  • Avoid config error when using the webdav protocol. The auth option is + expected to be a tuple not a list. Since our config is loaded from a + json file, we cannot use tuples. The fix converts the list to a tuple + when the config is related to a webdav protocol and the auth option + is into the confix. + (#285) +
  • +
+
+
+
+

+ Bug Tracker +

+

Bugs are tracked on GitHub + Issues. + In case of trouble, please check there if your issue has already been reported. + If you spotted it first, help us to smash it by providing a detailed and welcomed + + feedback. +

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

+ Credits +

+
+

+ Authors +

+
    +
  • ACSONE SA/NV
  • +
+
+
+

+ Contributors +

+ +
+
+

+ Maintainers +

+

This module is maintained by the OCA.

+ + Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose + mission is to support the collaborative development of Odoo features and + promote its widespread use. +

+

This module is part of the + + OCA/storage + + project on GitHub. +

+

You are welcome to contribute. To learn how please visit + https://odoo-community.org/page/Contribute. +

+
+
+
+ diff --git a/fs_storage/tests/common.py b/fs_storage/tests/common.py index a6b2ca00d9..03dd68762f 100644 --- a/fs_storage/tests/common.py +++ b/fs_storage/tests/common.py @@ -16,7 +16,7 @@ class TestFSStorageCase(TransactionCase): def setUpClass(cls): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - cls.backend: FSStorage = cls.env.ref("fs_storage.default_fs_storage") + cls.backend: FSStorage = cls.env.ref("fs_storage.fs_storage_demo") cls.backend.json_options = {"target_options": {"auto_mkdir": "True"}} cls.filedata = base64.b64encode(b"This is a simple file") cls.filename = "test_file.txt" From f4511e24623a9ac8b70ce34d811913720faf2ec3 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Mon, 11 Mar 2024 08:56:59 +0000 Subject: [PATCH 32/54] [UPD] Update fs_storage.pot --- fs_storage/i18n/fs_storage.pot | 49 +++++++++++++++------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/fs_storage/i18n/fs_storage.pot b/fs_storage/i18n/fs_storage.pot index eb253cca0c..0cddd25360 100644 --- a/fs_storage/i18n/fs_storage.pot +++ b/fs_storage/i18n/fs_storage.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 16.0\n" +"Project-Id-Version: Odoo Server 17.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -63,15 +63,10 @@ msgid "Directory Path" msgstr "" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Directory Path Env Default" msgstr "" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_is_editable -msgid "Directory Path Env Is Editable" -msgstr "" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name msgid "Display Name" @@ -109,11 +104,6 @@ msgstr "" msgid "Json Options" msgstr "" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage____last_update -msgid "Last Modified on" -msgstr "" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid msgid "Last Updated by" @@ -135,15 +125,10 @@ msgid "Options" msgstr "" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_default msgid "Options Env Default" msgstr "" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_is_editable -msgid "Options Env Is Editable" -msgstr "" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol msgid "Protocol" @@ -156,18 +141,13 @@ msgid "Protocol Descr" msgstr "" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_default msgid "Protocol Env Default" msgstr "" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_is_editable -msgid "Protocol Env Is Editable" -msgstr "" - #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path -#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Relative path to the directory to store the file" msgstr "" @@ -225,7 +205,7 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options -#: model:ir.model.fields,help:fs_storage.field_fs_storage__options_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_options_env_default msgid "" "The options used to initialize the filesystem.\n" "This is a JSON field that depends on the protocol used.\n" @@ -245,9 +225,24 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options_protocol #: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol -#: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_protocol_env_default msgid "" "The protocol used to access the content of filesystem.\n" "This list is the one supported by the fsspec library (see https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocolis added by default and refers to the odoo local filesystem.\n" "Pay attention that according to the protocol, some options must beprovided through the options field." msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable +msgid "X Directory Path Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable +msgid "X Options Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable +msgid "X Protocol Env Is Editable" +msgstr "" From a7a468ea3ebd5fffaac48b86ca06f3140c442be2 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 11 Mar 2024 08:58:42 +0000 Subject: [PATCH 33/54] [BOT] post-merge updates --- fs_storage/README.rst | 2 +- fs_storage/static/description/index.html | 1543 +++++++++------------- 2 files changed, 631 insertions(+), 914 deletions(-) diff --git a/fs_storage/README.rst b/fs_storage/README.rst index 0cacc6f8c7..f98b7dceb3 100644 --- a/fs_storage/README.rst +++ b/fs_storage/README.rst @@ -7,7 +7,7 @@ Filesystem Storage Backend !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:dd4db3023bb0dbe1251fdec870a17f9de6321d7cdf1d17183cfc78f39b74c390 + !! source digest: sha256:355feb510aea55f05a4c8ccdba08ac2d0e7de55e23bd39763d65c193c8b53231 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html index bcd180fc1f..2d8f9c5d41 100644 --- a/fs_storage/static/description/index.html +++ b/fs_storage/static/description/index.html @@ -1,915 +1,632 @@ - + - - - - Filesystem Storage Backend - - - -
-

Filesystem Storage Backend

- - -

- - Beta - - - License: LGPL-3 - - - OCA/storage - - - Translate me on Weblate - - - Try me on Runboat - -

-

This addon is a technical addon that allows you to define filesystem - like storage for your data. It’s used by other addons to store their - data in a transparent way into different kind of storages. -

-

Through the fs.storage record, you get access to an object that - implements the - - fsspec.spec.AbstractFileSystem - - interface and therefore give you an unified interface to access your - data whatever the storage protocol you decide to use. -

-

The list of supported protocols depends on the installed fsspec - implementations. By default, the addon will install the following - protocols: -

-
    -
  • LocalFileSystem
  • -
  • MemoryFileSystem
  • -
  • ZipFileSystem
  • -
  • TarFileSystem
  • -
  • FTPFileSystem
  • -
  • CachingFileSystem
  • -
  • WholeFileSystem
  • -
  • SimplCacheFileSystem
  • -
  • ReferenceFileSystem
  • -
  • GenericFileSystem
  • -
  • DirFileSystem
  • -
  • DatabricksFileSystem
  • -
  • GitHubFileSystem
  • -
  • JupiterFileSystem
  • -
  • OdooFileSystem
  • -
-

The OdooFileSystem is the one that allows you to store your data into a - directory mounted into your Odoo’s storage directory. This is the - default FS Storage when creating a new fs.storage record. -

-

Others protocols are available through the installation of additional - python packages: -

-
    -
  • DropboxDriveFileSystem -> pip install fsspec[dropbox]
  • -
  • HTTPFileSystem -> pip install fsspec[http]
  • -
  • HTTPSFileSystem -> pip install fsspec[http]
  • -
  • GCSFileSystem -> pip install fsspec[gcs]
  • -
  • GSFileSystem -> pip install fsspec[gs]
  • -
  • GoogleDriveFileSystem -> pip install gdrivefs
  • -
  • SFTPFileSystem -> pip install fsspec[sftp]
  • -
  • HaddoopFileSystem -> pip install fsspec[hdfs]
  • -
  • S3FileSystem -> pip install fsspec[s3]
  • -
  • WandbFS -> pip install wandbfs
  • -
  • OCIFileSystem -> pip install fsspec[oci]
  • -
  • AsyncLocalFileSystem -> pip install ‘morefs[asynclocalfs]
  • -
  • AzureDatalakeFileSystem -> pip install fsspec[adl]
  • -
  • AzureBlobFileSystem -> pip install fsspec[abfs]
  • -
  • DaskWorkerFileSystem -> pip install fsspec[dask]
  • -
  • GitFileSystem -> pip install fsspec[git]
  • -
  • SMBFileSystem -> pip install fsspec[smb]
  • -
  • LibArchiveFileSystem -> pip install fsspec[libarchive]
  • -
  • OSSFileSystem -> pip install ossfs
  • -
  • WebdavFileSystem -> pip install webdav4
  • -
  • DVCFileSystem -> pip install dvc
  • -
  • XRootDFileSystem -> pip install fsspec-xrootd
  • -
-

This list of supported protocols is not exhaustive or could change in - the future depending on the fsspec releases. You can find more - information about the supported protocols on the - fsspec - documentation. -

-

- Table of contents -

- -
-

- Usage -

-
-

- Configuration -

-

When you create a new backend, you must specify the following:

-
    -
  • The name of the backend. This is the name that will be used to - identify the backend into Odoo -
  • -
  • The code of the backend. This code will identify the backend into the - store_fname field of the ir.attachment model. This code must be - unique. It will be used as scheme. example of the store_fname field: - - odoofs://abs34Tg11 - - . -
  • -
  • The protocol used by the backend. The protocol refers to the - supported protocols of the fsspec python package. -
  • -
  • A directory path. This is a root directory from which the filesystem - will be mounted. This directory must exist. -
  • -
  • The protocol options. These are the options that will be passed to - the fsspec python package when creating the filesystem. These options - depend on the protocol used and are described in the fsspec - documentation. -
  • -
  • Resolve env vars. This options resolves the protocol options values - starting with $ from environment variables -
  • -
-

Some protocols defined in the fsspec package are wrappers around other - protocols. For example, the SimpleCacheFileSystem protocol is a wrapper - around any local filesystem protocol. In such cases, you must specify - into the protocol options the protocol to be wrapped and the options to - be passed to the wrapped protocol. -

-

For example, if you want to create a backend that uses the - SimpleCacheFileSystem protocol, after selecting the - SimpleCacheFileSystem protocol, you must specify the protocol options as - follows: -

-
-                        {
-                        
-                        
-                        "directory_path"
-                        :
-                        "/tmp/my_backend"
-                        ,
-                        
-                        
-                        "target_protocol"
-                        :
-                        "odoofs"
-                        ,
-                        
-                        
-                        "target_options"
-                        :
-                        {
-                        ...
-                        },
-                        
-                        
-                        }
-                    
-

In this example, the SimpleCacheFileSystem protocol will be used as a - wrapper around the odoofs protocol. -

-
-
-

- Server Environment -

-

To ease the management of the filesystem storages configuration accross - the different environments, the configuration of the filesystem storages - can be defined in environment files or directly in the main - configuration file. For example, the configuration of a filesystem - storage with the code fsprod can be provided in the main configuration - file as follows: -

-
-                        [fs_storage.fsprod]
-                        
-                        
-                        protocol
-                        =
-                        s3
-                        
-                        
-                        options
-                        =
-                        {"endpoint_url": "https://my_s3_server/", "key":
-                            "KEY", "secret": "SECRET"}
-                        
-                        
-                        
-                        directory_path
-                        =
-                        my_bucket
-                    
-

To work, a storage.backend record must exist with the code fsprod into - the database. In your configuration section, you can specify the value - for the following fields: -

-
    -
  • protocol
  • -
  • options
  • -
  • directory_path
  • -
-
-
-

- Migration from storage_backend -

-

The fs_storage addon can be used to replace the storage_backend addon. - (It has been designed to be a drop-in replacement for the - storage_backend addon). To ease the migration, the fs.storage model - defines the high-level methods available in the storage_backend model. - These methods are: -

-
    -
  • add
  • -
  • get
  • -
  • list_files
  • -
  • find_files
  • -
  • move_files
  • -
  • delete
  • -
-

These methods are wrappers around the methods of the - fsspec.AbstractFileSystem class (see - - https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem - ). - These methods are marked as deprecated and will be removed in a future - version (V18) of the addon. You should use the methods of the - fsspec.AbstractFileSystem class instead since they are more flexible and - powerful. You can access the instance of the fsspec.AbstractFileSystem - class using the fs property of a fs.storage record. -

-
-
-
-

- Known issues / Roadmap -

-
    -
  • Transactions: fsspec comes with a transactional mechanism that once - started, gathers all the files created during the transaction, and if - the transaction is committed, moves them to their final locations. It - would be useful to bridge this with the transactional mechanism of - odoo. This would allow to ensure that all the files created during a - transaction are either all moved to their final locations, or all - deleted if the transaction is rolled back. This mechanism is only - valid for files created during the transaction by a call to the open - method of the file system. It is not valid for others operations, - such as rm, mv_file, … . -
  • -
-
-
-

- Changelog -

-
-

- 16.0.1.1.0 (2023-12-22) -

-

- Features -

-
    -
  • Add parameter on storage backend to resolve protocol options values - starting with $ from environment variables - (#303) -
  • -
-
-
-

- 16.0.1.0.3 (2023-10-17) -

-

- Bugfixes -

-
    -
  • Fix access to technical models to be able to upload attachments for - users with basic access - (#289) -
  • -
-
-
-

- 16.0.1.0.2 (2023-10-09) -

-

- Bugfixes -

-
    -
  • Avoid config error when using the webdav protocol. The auth option is - expected to be a tuple not a list. Since our config is loaded from a - json file, we cannot use tuples. The fix converts the list to a tuple - when the config is related to a webdav protocol and the auth option - is into the confix. - (#285) -
  • -
-
-
-
-

- Bug Tracker -

-

Bugs are tracked on GitHub - Issues. - In case of trouble, please check there if your issue has already been reported. - If you spotted it first, help us to smash it by providing a detailed and welcomed - - feedback. -

-

Do not contact contributors directly about support or help with technical issues.

-
-
-

- Credits -

-
-

- Authors -

-
    -
  • ACSONE SA/NV
  • -
-
-
-

- Contributors -

- -
-
-

- Maintainers -

-

This module is maintained by the OCA.

- - Odoo Community Association - -

OCA, or the Odoo Community Association, is a nonprofit organization whose - mission is to support the collaborative development of Odoo features and - promote its widespread use. -

-

This module is part of the - - OCA/storage - - project on GitHub. -

-

You are welcome to contribute. To learn how please visit - https://odoo-community.org/page/Contribute. -

-
-
-
- + + + +Filesystem Storage Backend + + + +
+

Filesystem Storage Backend

+ + +

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

This addon is a technical addon that allows you to define filesystem +like storage for your data. It’s used by other addons to store their +data in a transparent way into different kind of storages.

+

Through the fs.storage record, you get access to an object that +implements the +fsspec.spec.AbstractFileSystem +interface and therefore give you an unified interface to access your +data whatever the storage protocol you decide to use.

+

The list of supported protocols depends on the installed fsspec +implementations. By default, the addon will install the following +protocols:

+
    +
  • LocalFileSystem
  • +
  • MemoryFileSystem
  • +
  • ZipFileSystem
  • +
  • TarFileSystem
  • +
  • FTPFileSystem
  • +
  • CachingFileSystem
  • +
  • WholeFileSystem
  • +
  • SimplCacheFileSystem
  • +
  • ReferenceFileSystem
  • +
  • GenericFileSystem
  • +
  • DirFileSystem
  • +
  • DatabricksFileSystem
  • +
  • GitHubFileSystem
  • +
  • JupiterFileSystem
  • +
  • OdooFileSystem
  • +
+

The OdooFileSystem is the one that allows you to store your data into a +directory mounted into your Odoo’s storage directory. This is the +default FS Storage when creating a new fs.storage record.

+

Others protocols are available through the installation of additional +python packages:

+
    +
  • DropboxDriveFileSystem -> pip install fsspec[dropbox]
  • +
  • HTTPFileSystem -> pip install fsspec[http]
  • +
  • HTTPSFileSystem -> pip install fsspec[http]
  • +
  • GCSFileSystem -> pip install fsspec[gcs]
  • +
  • GSFileSystem -> pip install fsspec[gs]
  • +
  • GoogleDriveFileSystem -> pip install gdrivefs
  • +
  • SFTPFileSystem -> pip install fsspec[sftp]
  • +
  • HaddoopFileSystem -> pip install fsspec[hdfs]
  • +
  • S3FileSystem -> pip install fsspec[s3]
  • +
  • WandbFS -> pip install wandbfs
  • +
  • OCIFileSystem -> pip install fsspec[oci]
  • +
  • AsyncLocalFileSystem -> pip install ‘morefs[asynclocalfs]
  • +
  • AzureDatalakeFileSystem -> pip install fsspec[adl]
  • +
  • AzureBlobFileSystem -> pip install fsspec[abfs]
  • +
  • DaskWorkerFileSystem -> pip install fsspec[dask]
  • +
  • GitFileSystem -> pip install fsspec[git]
  • +
  • SMBFileSystem -> pip install fsspec[smb]
  • +
  • LibArchiveFileSystem -> pip install fsspec[libarchive]
  • +
  • OSSFileSystem -> pip install ossfs
  • +
  • WebdavFileSystem -> pip install webdav4
  • +
  • DVCFileSystem -> pip install dvc
  • +
  • XRootDFileSystem -> pip install fsspec-xrootd
  • +
+

This list of supported protocols is not exhaustive or could change in +the future depending on the fsspec releases. You can find more +information about the supported protocols on the fsspec +documentation.

+

Table of contents

+ +
+

Usage

+
+

Configuration

+

When you create a new backend, you must specify the following:

+
    +
  • The name of the backend. This is the name that will be used to +identify the backend into Odoo
  • +
  • The code of the backend. This code will identify the backend into the +store_fname field of the ir.attachment model. This code must be +unique. It will be used as scheme. example of the store_fname field: +odoofs://abs34Tg11.
  • +
  • The protocol used by the backend. The protocol refers to the +supported protocols of the fsspec python package.
  • +
  • A directory path. This is a root directory from which the filesystem +will be mounted. This directory must exist.
  • +
  • The protocol options. These are the options that will be passed to +the fsspec python package when creating the filesystem. These options +depend on the protocol used and are described in the fsspec +documentation.
  • +
  • Resolve env vars. This options resolves the protocol options values +starting with $ from environment variables
  • +
+

Some protocols defined in the fsspec package are wrappers around other +protocols. For example, the SimpleCacheFileSystem protocol is a wrapper +around any local filesystem protocol. In such cases, you must specify +into the protocol options the protocol to be wrapped and the options to +be passed to the wrapped protocol.

+

For example, if you want to create a backend that uses the +SimpleCacheFileSystem protocol, after selecting the +SimpleCacheFileSystem protocol, you must specify the protocol options as +follows:

+
+{
+    "directory_path": "/tmp/my_backend",
+    "target_protocol": "odoofs",
+    "target_options": {...},
+}
+
+

In this example, the SimpleCacheFileSystem protocol will be used as a +wrapper around the odoofs protocol.

+
+
+

Server Environment

+

To ease the management of the filesystem storages configuration accross +the different environments, the configuration of the filesystem storages +can be defined in environment files or directly in the main +configuration file. For example, the configuration of a filesystem +storage with the code fsprod can be provided in the main configuration +file as follows:

+
+[fs_storage.fsprod]
+protocol=s3
+options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"}
+directory_path=my_bucket
+
+

To work, a storage.backend record must exist with the code fsprod into +the database. In your configuration section, you can specify the value +for the following fields:

+
    +
  • protocol
  • +
  • options
  • +
  • directory_path
  • +
+
+
+

Migration from storage_backend

+

The fs_storage addon can be used to replace the storage_backend addon. +(It has been designed to be a drop-in replacement for the +storage_backend addon). To ease the migration, the fs.storage model +defines the high-level methods available in the storage_backend model. +These methods are:

+
    +
  • add
  • +
  • get
  • +
  • list_files
  • +
  • find_files
  • +
  • move_files
  • +
  • delete
  • +
+

These methods are wrappers around the methods of the +fsspec.AbstractFileSystem class (see +https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem). +These methods are marked as deprecated and will be removed in a future +version (V18) of the addon. You should use the methods of the +fsspec.AbstractFileSystem class instead since they are more flexible and +powerful. You can access the instance of the fsspec.AbstractFileSystem +class using the fs property of a fs.storage record.

+
+
+
+

Known issues / Roadmap

+
    +
  • Transactions: fsspec comes with a transactional mechanism that once +started, gathers all the files created during the transaction, and if +the transaction is committed, moves them to their final locations. It +would be useful to bridge this with the transactional mechanism of +odoo. This would allow to ensure that all the files created during a +transaction are either all moved to their final locations, or all +deleted if the transaction is rolled back. This mechanism is only +valid for files created during the transaction by a call to the open +method of the file system. It is not valid for others operations, +such as rm, mv_file, … .
  • +
+
+
+

Changelog

+
+

16.0.1.1.0 (2023-12-22)

+

Features

+
    +
  • Add parameter on storage backend to resolve protocol options values +starting with $ from environment variables +(#303)
  • +
+
+
+

16.0.1.0.3 (2023-10-17)

+

Bugfixes

+
    +
  • Fix access to technical models to be able to upload attachments for +users with basic access +(#289)
  • +
+
+
+

16.0.1.0.2 (2023-10-09)

+

Bugfixes

+
    +
  • Avoid config error when using the webdav protocol. The auth option is +expected to be a tuple not a list. Since our config is loaded from a +json file, we cannot use tuples. The fix converts the list to a tuple +when the config is related to a webdav protocol and the auth option +is into the confix. +(#285)
  • +
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/storage project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ From e828c38e90c3cc317e2940e9f3ec6d38bc5a5bb9 Mon Sep 17 00:00:00 2001 From: Weblate Date: Mon, 11 Mar 2024 12:00:03 +0000 Subject: [PATCH 34/54] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: storage-17.0/storage-17.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage/ --- fs_storage/i18n/es.po | 59 ++++++++++++++++++++++++------------------- fs_storage/i18n/it.po | 59 ++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 52 deletions(-) diff --git a/fs_storage/i18n/es.po b/fs_storage/i18n/es.po index 409a3b76ac..2404957899 100644 --- a/fs_storage/i18n/es.po +++ b/fs_storage/i18n/es.po @@ -66,15 +66,10 @@ msgid "Directory Path" msgstr "Ruta del Directorio" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Directory Path Env Default" msgstr "Ruta del Directorio Env Predet" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_is_editable -msgid "Directory Path Env Is Editable" -msgstr "La Ruta de Directorio Env es Editable" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name msgid "Display Name" @@ -112,11 +107,6 @@ msgstr "ID (identificación)" msgid "Json Options" msgstr "Opciones Json" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage____last_update -msgid "Last Modified on" -msgstr "Última Modificación el" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid msgid "Last Updated by" @@ -138,15 +128,10 @@ msgid "Options" msgstr "Opciones" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_default msgid "Options Env Default" msgstr "Opciones Env Por Defecto" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_is_editable -msgid "Options Env Is Editable" -msgstr "Las Opciones Env son Editables" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol msgid "Protocol" @@ -159,18 +144,13 @@ msgid "Protocol Descr" msgstr "Descr. del Protocolo" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_default msgid "Protocol Env Default" msgstr "Protocolo Env Predeterminado" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_is_editable -msgid "Protocol Env Is Editable" -msgstr "El Protocolo Env es Editable" - #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path -#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Relative path to the directory to store the file" msgstr "Ruta relativa al directorio para almacenar el archivo" @@ -238,7 +218,7 @@ msgstr "Las opciones utilizadas para inicializar el sistema de archivos.\n" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options -#: model:ir.model.fields,help:fs_storage.field_fs_storage__options_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_options_env_default msgid "" "The options used to initialize the filesystem.\n" "This is a JSON field that depends on the protocol used.\n" @@ -273,7 +253,7 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options_protocol #: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol -#: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_protocol_env_default msgid "" "The protocol used to access the content of filesystem.\n" "This list is the one supported by the fsspec library (see https://filesystem-" @@ -288,3 +268,30 @@ msgstr "" "agregado por defecto y se refiere al sistema de archivos local de odoo.\n" "Preste atención que de acuerdo al protocolo, algunas opciones deben ser " "provistas a través del campo opciones." + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable +msgid "X Directory Path Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable +msgid "X Options Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable +msgid "X Protocol Env Is Editable" +msgstr "" + +#~ msgid "Directory Path Env Is Editable" +#~ msgstr "La Ruta de Directorio Env es Editable" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación el" + +#~ msgid "Options Env Is Editable" +#~ msgstr "Las Opciones Env son Editables" + +#~ msgid "Protocol Env Is Editable" +#~ msgstr "El Protocolo Env es Editable" diff --git a/fs_storage/i18n/it.po b/fs_storage/i18n/it.po index f4c3e38ed2..7091222c96 100644 --- a/fs_storage/i18n/it.po +++ b/fs_storage/i18n/it.po @@ -66,15 +66,10 @@ msgid "Directory Path" msgstr "Percorso cartella" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Directory Path Env Default" msgstr "Percorso cartella ambiente predefinito" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path_env_is_editable -msgid "Directory Path Env Is Editable" -msgstr "Percorso cartella ambiente è modificabile" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name msgid "Display Name" @@ -112,11 +107,6 @@ msgstr "ID" msgid "Json Options" msgstr "Opzioni JSON" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage____last_update -msgid "Last Modified on" -msgstr "Ultima modifica il" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid msgid "Last Updated by" @@ -138,15 +128,10 @@ msgid "Options" msgstr "Opzioni" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_default msgid "Options Env Default" msgstr "Opzioni ambiente predefinite" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_env_is_editable -msgid "Options Env Is Editable" -msgstr "Opzioni ambiente sono modificabili" - #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol msgid "Protocol" @@ -159,18 +144,13 @@ msgid "Protocol Descr" msgstr "Descrizione protocollo" #. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_default +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_default msgid "Protocol Env Default" msgstr "Protocollo ambiene predefinito" -#. module: fs_storage -#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_env_is_editable -msgid "Protocol Env Is Editable" -msgstr "Protocollo ambiente è modificabile" - #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path -#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Relative path to the directory to store the file" msgstr "Percorso relativo alla cartella per archiviare il file" @@ -237,7 +217,7 @@ msgstr "Le opzioni per inizializzare il filesystem.\n" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options -#: model:ir.model.fields,help:fs_storage.field_fs_storage__options_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_options_env_default msgid "" "The options used to initialize the filesystem.\n" "This is a JSON field that depends on the protocol used.\n" @@ -272,7 +252,7 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options_protocol #: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol -#: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol_env_default +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_protocol_env_default msgid "" "The protocol used to access the content of filesystem.\n" "This list is the one supported by the fsspec library (see https://filesystem-" @@ -287,3 +267,30 @@ msgstr "" "aggiunto in modo predefinito e fa riferimento al filesystem locale Odoo.\n" "Fare attenzione che in accordo con il protocollo, alcune opzioni devono " "essere fonrite attraverso il campo opzioni." + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable +msgid "X Directory Path Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable +msgid "X Options Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable +msgid "X Protocol Env Is Editable" +msgstr "" + +#~ msgid "Directory Path Env Is Editable" +#~ msgstr "Percorso cartella ambiente è modificabile" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "Options Env Is Editable" +#~ msgstr "Opzioni ambiente sono modificabili" + +#~ msgid "Protocol Env Is Editable" +#~ msgstr "Protocollo ambiente è modificabile" From 6c5245a55aa5dacd288616c2b9e62ee866f20265 Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 12 Mar 2024 08:15:47 +0000 Subject: [PATCH 35/54] Translated using Weblate (Italian) Currently translated at 92.1% (35 of 38 strings) Translation: storage-17.0/storage-17.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage/it/ --- fs_storage/i18n/it.po | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs_storage/i18n/it.po b/fs_storage/i18n/it.po index 7091222c96..d81b3a44ef 100644 --- a/fs_storage/i18n/it.po +++ b/fs_storage/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2023-12-24 17:36+0000\n" +"PO-Revision-Date: 2024-03-12 10:36+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -270,18 +270,21 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable +#, fuzzy msgid "X Directory Path Env Is Editable" -msgstr "" +msgstr "Esecuzione percorso ambiente cartella è modificabile" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable +#, fuzzy msgid "X Options Env Is Editable" -msgstr "" +msgstr "Opzioni esecuzione ambiente sono modificabili" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable +#, fuzzy msgid "X Protocol Env Is Editable" -msgstr "" +msgstr "Protocollo esecuzione ambiente è modificabile" #~ msgid "Directory Path Env Is Editable" #~ msgstr "Percorso cartella ambiente è modificabile" From 6e4cc6c52a33f0271d6fc7e92b3add0efa439bd5 Mon Sep 17 00:00:00 2001 From: mymage Date: Wed, 27 Mar 2024 13:24:48 +0000 Subject: [PATCH 36/54] Translated using Weblate (Italian) Currently translated at 92.1% (35 of 38 strings) Translation: storage-17.0/storage-17.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage/it/ --- fs_storage/i18n/it.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs_storage/i18n/it.po b/fs_storage/i18n/it.po index d81b3a44ef..53ad2f1090 100644 --- a/fs_storage/i18n/it.po +++ b/fs_storage/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-03-12 10:36+0000\n" +"PO-Revision-Date: 2024-03-27 15:35+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" From 71ed381b9e1afc9f8d59acea4abdcf0a9c05fc7e Mon Sep 17 00:00:00 2001 From: Ivorra78 Date: Wed, 24 Apr 2024 08:32:51 +0000 Subject: [PATCH 37/54] Translated using Weblate (Spanish) Currently translated at 100.0% (38 of 38 strings) Translation: storage-17.0/storage-17.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage/es/ --- fs_storage/i18n/es.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs_storage/i18n/es.po b/fs_storage/i18n/es.po index 2404957899..f558b305aa 100644 --- a/fs_storage/i18n/es.po +++ b/fs_storage/i18n/es.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2023-12-28 02:07+0000\n" +"PO-Revision-Date: 2024-04-24 10:40+0000\n" "Last-Translator: Ivorra78 \n" "Language-Team: none\n" "Language: es\n" @@ -272,17 +272,17 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable msgid "X Directory Path Env Is Editable" -msgstr "" +msgstr "X La Ruta de Directorio Env Es Editable" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable msgid "X Options Env Is Editable" -msgstr "" +msgstr "X Las Opciones Env son Editables" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable msgid "X Protocol Env Is Editable" -msgstr "" +msgstr "El Protocolo X Env es Editable" #~ msgid "Directory Path Env Is Editable" #~ msgstr "La Ruta de Directorio Env es Editable" From 586f52c5091e71b654733cc9d19a2a274313aa75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Fri, 17 May 2024 10:25:16 +0200 Subject: [PATCH 38/54] [FIX] fs_storage: Change make_path_posix() to only 1 argument Since https://github.com/fsspec/filesystem_spec/commit/da7754870bb9ab30c99fcd6dccdd39421f420691 it is necessary to set in make_path_posix() only 1 argument --- fs_storage/__manifest__.py | 2 +- fs_storage/rooted_dir_file_system.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs_storage/__manifest__.py b/fs_storage/__manifest__.py index 12ec886435..b27fd55fb1 100644 --- a/fs_storage/__manifest__.py +++ b/fs_storage/__manifest__.py @@ -18,5 +18,5 @@ "security/ir.model.access.csv", ], "demo": ["demo/fs_storage_demo.xml"], - "external_dependencies": {"python": ["fsspec"]}, + "external_dependencies": {"python": ["fsspec>=2024.5.0"]}, } diff --git a/fs_storage/rooted_dir_file_system.py b/fs_storage/rooted_dir_file_system.py index 84f93ff26c..91bae52200 100644 --- a/fs_storage/rooted_dir_file_system.py +++ b/fs_storage/rooted_dir_file_system.py @@ -25,7 +25,7 @@ def _join(self, path): # any relative paths. # Since the path separator is not always the same on all systems, # we need to normalize the path separator. - path_posix = os.path.normpath(make_path_posix(path, self.sep)) + path_posix = os.path.normpath(make_path_posix(path)) root_posix = os.path.normpath(make_path_posix(self.path)) if not path_posix.startswith(root_posix): raise PermissionError( From f2d1e91f5fb933b6b31a50bfab7ab122c21c4d76 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 24 May 2024 08:31:37 +0000 Subject: [PATCH 39/54] [BOT] post-merge updates --- fs_storage/README.rst | 2 +- fs_storage/__manifest__.py | 2 +- fs_storage/static/description/index.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs_storage/README.rst b/fs_storage/README.rst index f98b7dceb3..42e1b63438 100644 --- a/fs_storage/README.rst +++ b/fs_storage/README.rst @@ -7,7 +7,7 @@ Filesystem Storage Backend !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:355feb510aea55f05a4c8ccdba08ac2d0e7de55e23bd39763d65c193c8b53231 + !! source digest: sha256:18d4d4b731b8b2f099884e59e086b00212a759e1104a4be927d2f68af1395699 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/fs_storage/__manifest__.py b/fs_storage/__manifest__.py index b27fd55fb1..af55e711d7 100644 --- a/fs_storage/__manifest__.py +++ b/fs_storage/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Filesystem Storage Backend", "summary": "Implement the concept of Storage with amazon S3, sftp...", - "version": "17.0.1.0.0", + "version": "17.0.1.0.1", "category": "FS Storage", "website": "https://github.com/OCA/storage", "author": " ACSONE SA/NV, Odoo Community Association (OCA)", diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html index 2d8f9c5d41..3214c60426 100644 --- a/fs_storage/static/description/index.html +++ b/fs_storage/static/description/index.html @@ -366,7 +366,7 @@

Filesystem Storage Backend

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:355feb510aea55f05a4c8ccdba08ac2d0e7de55e23bd39763d65c193c8b53231 +!! source digest: sha256:18d4d4b731b8b2f099884e59e086b00212a759e1104a4be927d2f68af1395699 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

This addon is a technical addon that allows you to define filesystem From aee0600e7e421c2f82d410b6ac79cfb9c74bacd9 Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 14 Jun 2024 14:25:49 +0000 Subject: [PATCH 40/54] Translated using Weblate (Italian) Currently translated at 100.0% (38 of 38 strings) Translation: storage-17.0/storage-17.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage/it/ --- fs_storage/i18n/it.po | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs_storage/i18n/it.po b/fs_storage/i18n/it.po index 53ad2f1090..86beb594d7 100644 --- a/fs_storage/i18n/it.po +++ b/fs_storage/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-03-27 15:35+0000\n" +"PO-Revision-Date: 2024-06-14 16:37+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -270,21 +270,18 @@ msgstr "" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable -#, fuzzy msgid "X Directory Path Env Is Editable" -msgstr "Esecuzione percorso ambiente cartella è modificabile" +msgstr "Il percorso ambiente cartella X è modificabile" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable -#, fuzzy msgid "X Options Env Is Editable" -msgstr "Opzioni esecuzione ambiente sono modificabili" +msgstr "Opzioni X ambiente sono modificabili" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable -#, fuzzy msgid "X Protocol Env Is Editable" -msgstr "Protocollo esecuzione ambiente è modificabile" +msgstr "Protocollo X ambiente è modificabile" #~ msgid "Directory Path Env Is Editable" #~ msgstr "Percorso cartella ambiente è modificabile" From df3a74260c8c62d2fa3bddc5c19ab7dd41316872 Mon Sep 17 00:00:00 2001 From: xtanuiha Date: Mon, 26 Aug 2024 05:45:06 +0000 Subject: [PATCH 41/54] Added translation using Weblate (Chinese (Simplified) (zh_CN)) --- fs_storage/i18n/zh_CN.po | 249 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 fs_storage/i18n/zh_CN.po diff --git a/fs_storage/i18n/zh_CN.po b/fs_storage/i18n/zh_CN.po new file mode 100644 index 0000000000..0637f468fa --- /dev/null +++ b/fs_storage/i18n/zh_CN.po @@ -0,0 +1,249 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fs_storage +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Available options" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_properties +msgid "Available properties" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__code +msgid "Code" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Connection Test Failed!" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Connection Test Succeeded!" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_uid +msgid "Created by" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_date +msgid "Created on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_protocol +msgid "Describes Protocol" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path +msgid "Directory Path" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_default +msgid "Directory Path Env Default" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name +msgid "Display Name" +msgstr "" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Enter you fsspec options here." +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "Everything seems properly set up!" +msgstr "" + +#. module: fs_storage +#: model:ir.actions.act_window,name:fs_storage.act_open_fs_storage_view +#: model:ir.model,name:fs_storage.model_fs_storage +#: model:ir.ui.menu,name:fs_storage.menu_fs_storage +#: model:ir.ui.menu,name:fs_storage.menu_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_search_view +msgid "FS Storage" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__id +msgid "ID" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__json_options +msgid "Json Options" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_date +msgid "Last Updated on" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__name +msgid "Name" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options +msgid "Options" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_default +msgid "Options Env Default" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol +msgid "Protocol" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_descr +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Protocol Descr" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_default +msgid "Protocol Env Default" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_directory_path_env_default +msgid "Relative path to the directory to store the file" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__eval_options_from_env +msgid "Resolve env vars" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__eval_options_from_env +msgid "" +"Resolve options values starting with $ from environment variables. e.g\n" +" {\n" +" \"endpoint_url\": \"$AWS_ENDPOINT_URL\",\n" +" }\n" +" " +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__server_env_defaults +msgid "Server Env Defaults" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__code +msgid "" +"Technical code used to identify the storage backend into the code.This code " +"must be unique. This code is used for example to define the storage backend " +"to store the attachments via the configuration parameter " +"'ir_attachment.storage.force.database' when the module 'fs_attachment' is " +"installed." +msgstr "" + +#. module: fs_storage +#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view +msgid "Test connection" +msgstr "" + +#. module: fs_storage +#: model:ir.model.constraint,message:fs_storage.constraint_fs_storage_code_uniq +msgid "The code must be unique" +msgstr "" + +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +#, python-format +msgid "The options must be a valid JSON" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__json_options +msgid "The options used to initialize the filesystem.\n" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__options +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_options_env_default +msgid "" +"The options used to initialize the filesystem.\n" +"This is a JSON field that depends on the protocol used.\n" +"For example, for the sftp protocol, you can provide the following:\n" +"{\n" +" 'host': 'my.sftp.server',\n" +" 'ssh_kwrags': {\n" +" 'username': 'myuser',\n" +" 'password': 'mypassword',\n" +" 'port': 22,\n" +" }\n" +"}\n" +"For more information, please refer to the fsspec documentation:\n" +"https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-implementations" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,help:fs_storage.field_fs_storage__options_protocol +#: model:ir.model.fields,help:fs_storage.field_fs_storage__protocol +#: model:ir.model.fields,help:fs_storage.field_fs_storage__x_protocol_env_default +msgid "" +"The protocol used to access the content of filesystem.\n" +"This list is the one supported by the fsspec library (see https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocolis added by default and refers to the odoo local filesystem.\n" +"Pay attention that according to the protocol, some options must beprovided through the options field." +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable +msgid "X Directory Path Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable +msgid "X Options Env Is Editable" +msgstr "" + +#. module: fs_storage +#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable +msgid "X Protocol Env Is Editable" +msgstr "" From 5bbc1cd7d77427d71a4caced201b44d6f5bc6619 Mon Sep 17 00:00:00 2001 From: xtanuiha Date: Mon, 26 Aug 2024 05:53:14 +0000 Subject: [PATCH 42/54] Translated using Weblate (Chinese (Simplified) (zh_CN)) Currently translated at 100.0% (38 of 38 strings) Translation: storage-17.0/storage-17.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage/zh_CN/ --- fs_storage/i18n/zh_CN.po | 98 ++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/fs_storage/i18n/zh_CN.po b/fs_storage/i18n/zh_CN.po index 0637f468fa..612f80dc59 100644 --- a/fs_storage/i18n/zh_CN.po +++ b/fs_storage/i18n/zh_CN.po @@ -6,84 +6,86 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 17.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2024-08-26 08:06+0000\n" +"Last-Translator: xtanuiha \n" "Language-Team: none\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 5.6.2\n" #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view msgid "Available options" -msgstr "" +msgstr "可用选项" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_properties msgid "Available properties" -msgstr "" +msgstr "可用属性" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__code msgid "Code" -msgstr "" +msgstr "代码" #. module: fs_storage #. odoo-python #: code:addons/fs_storage/models/fs_storage.py:0 #, python-format msgid "Connection Test Failed!" -msgstr "" +msgstr "连接测试失败!" #. module: fs_storage #. odoo-python #: code:addons/fs_storage/models/fs_storage.py:0 #, python-format msgid "Connection Test Succeeded!" -msgstr "" +msgstr "连接测试成功!" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_uid msgid "Created by" -msgstr "" +msgstr "创建者" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__create_date msgid "Created on" -msgstr "" +msgstr "创建于" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options_protocol msgid "Describes Protocol" -msgstr "" +msgstr "描述协议" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__directory_path msgid "Directory Path" -msgstr "" +msgstr "目录路径" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Directory Path Env Default" -msgstr "" +msgstr "目录路径环境默认值" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__display_name msgid "Display Name" -msgstr "" +msgstr "目录路径环境默认值" #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view msgid "Enter you fsspec options here." -msgstr "" +msgstr "在这里输入你的fsspec选项。" #. module: fs_storage #. odoo-python #: code:addons/fs_storage/models/fs_storage.py:0 #, python-format msgid "Everything seems properly set up!" -msgstr "" +msgstr "一切看起来都设置得当!" #. module: fs_storage #: model:ir.actions.act_window,name:fs_storage.act_open_fs_storage_view @@ -93,69 +95,69 @@ msgstr "" #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_search_view msgid "FS Storage" -msgstr "" +msgstr "文件系统存储" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__id msgid "ID" -msgstr "" +msgstr "ID" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__json_options msgid "Json Options" -msgstr "" +msgstr "JSON选项" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_uid msgid "Last Updated by" -msgstr "" +msgstr "最后更新者" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__write_date msgid "Last Updated on" -msgstr "" +msgstr "最后更新于" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__name msgid "Name" -msgstr "" +msgstr "名称" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__options msgid "Options" -msgstr "" +msgstr "选项" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_default msgid "Options Env Default" -msgstr "" +msgstr "选项环境默认值" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol msgid "Protocol" -msgstr "" +msgstr "协议" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__protocol_descr #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view msgid "Protocol Descr" -msgstr "" +msgstr "协议描述" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_default msgid "Protocol Env Default" -msgstr "" +msgstr "协议环境默认值" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__directory_path #: model:ir.model.fields,help:fs_storage.field_fs_storage__x_directory_path_env_default msgid "Relative path to the directory to store the file" -msgstr "" +msgstr "存储文件的目录的相对路径" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__eval_options_from_env msgid "Resolve env vars" -msgstr "" +msgstr "解析环境变量" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__eval_options_from_env @@ -166,11 +168,16 @@ msgid "" " }\n" " " msgstr "" +"从环境变量解析以$开头的选项值。例如:\n" +"{\n" +" \"endpoint_url\": \"$AWS_ENDPOINT_URL\"\n" +"}\n" +" " #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__server_env_defaults msgid "Server Env Defaults" -msgstr "" +msgstr "服务器环境默认值" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__code @@ -181,28 +188,31 @@ msgid "" "'ir_attachment.storage.force.database' when the module 'fs_attachment' is " "installed." msgstr "" +"用于在代码中标识存储后端的技术代码。此代码必须是唯一的。例如,当安装'fs_attac" +"hment'模块时,此代码用于通过配置参数'ir_attachment.storage.force." +"database'定义存储附件的存储后端。" #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view msgid "Test connection" -msgstr "" +msgstr "测试连接" #. module: fs_storage #: model:ir.model.constraint,message:fs_storage.constraint_fs_storage_code_uniq msgid "The code must be unique" -msgstr "" +msgstr "代码必须是唯一的" #. module: fs_storage #. odoo-python #: code:addons/fs_storage/models/fs_storage.py:0 #, python-format msgid "The options must be a valid JSON" -msgstr "" +msgstr "选项必须是有效的JSON" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__json_options msgid "The options used to initialize the filesystem.\n" -msgstr "" +msgstr "用于初始化文件系统的选项。\n" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options @@ -222,6 +232,20 @@ msgid "" "For more information, please refer to the fsspec documentation:\n" "https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-implementations" msgstr "" +"用于初始化文件系统的选项。\n" +"这是一个依赖于所使用的协议的JSON字段。\n" +"例如,对于sftp协议,您可以提供以下内容:\n" +"{\n" +" 'host': 'my.sftp.server',\n" +" 'ssh_kwrags': {\n" +" 'username': 'myuser',\n" +" 'password': 'mypassword',\n" +" 'port': 22,\n" +" }\n" +"}\n" +"有关更多信息,请参考fsspec文档:\n" +"https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-" +"implementations" #. module: fs_storage #: model:ir.model.fields,help:fs_storage.field_fs_storage__options_protocol @@ -232,18 +256,22 @@ msgid "" "This list is the one supported by the fsspec library (see https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocolis added by default and refers to the odoo local filesystem.\n" "Pay attention that according to the protocol, some options must beprovided through the options field." msgstr "" +"用于访问文件系统内容的协议。\n" +"此列表是fsspec库支持的(见 https://filesystem-spec.readthedocs.io/en/" +"latest)。默认添加了一个文件系统协议,指的是Odoo本地文件系统。\n" +"请注意,根据协议,某些选项必须通过选项字段提供。" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_directory_path_env_is_editable msgid "X Directory Path Env Is Editable" -msgstr "" +msgstr "X目录路径环境可编辑" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_options_env_is_editable msgid "X Options Env Is Editable" -msgstr "" +msgstr "X选项环境可编辑" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__x_protocol_env_is_editable msgid "X Protocol Env Is Editable" -msgstr "" +msgstr "X协议环境可编辑" From 41d1f70da4fc357b9900866d085d8dc8b65d783c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 15 Mar 2024 18:21:49 +0100 Subject: [PATCH 43/54] fs_storage: remove default protocol Since protocol is under server_environment control, it seems its default value takes priority over a value set in an XML record. Since it does really make much sense to create a storage backend without specifying the protocol, we remove the default value. --- fs_storage/models/fs_storage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index b811e59d84..a42751a374 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -83,7 +83,6 @@ def __init__(self, env, ids=(), prefetch_ids=()): protocol = fields.Selection( selection="_get_protocols", required=True, - default="odoofs", help="The protocol used to access the content of filesystem.\n" "This list is the one supported by the fsspec library (see " "https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocol" From 11ed64df0f2141905fe23ac01225802917bfd9e7 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Sat, 5 Oct 2024 11:48:09 +0000 Subject: [PATCH 44/54] [BOT] post-merge updates --- fs_storage/README.rst | 2 +- fs_storage/__manifest__.py | 2 +- fs_storage/static/description/index.html | 13 ++++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/fs_storage/README.rst b/fs_storage/README.rst index 42e1b63438..445c949f88 100644 --- a/fs_storage/README.rst +++ b/fs_storage/README.rst @@ -7,7 +7,7 @@ Filesystem Storage Backend !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:18d4d4b731b8b2f099884e59e086b00212a759e1104a4be927d2f68af1395699 + !! source digest: sha256:6e7abac468ff2942178ac2df68774f75820b618173acf8c7b76f51fbdbe3b7bc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/fs_storage/__manifest__.py b/fs_storage/__manifest__.py index af55e711d7..8d80a3cb18 100644 --- a/fs_storage/__manifest__.py +++ b/fs_storage/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Filesystem Storage Backend", "summary": "Implement the concept of Storage with amazon S3, sftp...", - "version": "17.0.1.0.1", + "version": "17.0.1.0.2", "category": "FS Storage", "website": "https://github.com/OCA/storage", "author": " ACSONE SA/NV, Odoo Community Association (OCA)", diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html index 3214c60426..588354460a 100644 --- a/fs_storage/static/description/index.html +++ b/fs_storage/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -366,7 +367,7 @@

Filesystem Storage Backend

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:18d4d4b731b8b2f099884e59e086b00212a759e1104a4be927d2f68af1395699 +!! source digest: sha256:6e7abac468ff2942178ac2df68774f75820b618173acf8c7b76f51fbdbe3b7bc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

This addon is a technical addon that allows you to define filesystem @@ -619,7 +620,9 @@

Contributors

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

From 834f1c4b3662f1d7a5a627f975e64fc6f8be511f Mon Sep 17 00:00:00 2001 From: JordiMForgeFlow Date: Fri, 12 Jan 2024 10:59:15 +0100 Subject: [PATCH 45/54] [IMP] fs_storage: invalidate filesystem cache when connection fails --- fs_storage/models/fs_storage.py | 23 ++++++++++++++++++++- fs_storage/readme/newsfragments/320.feature | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 fs_storage/readme/newsfragments/320.feature diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index a42751a374..d140cb795f 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -264,12 +264,33 @@ def _compute_options_properties(self) -> None: doc = inspect.getdoc(cls.__init__) rec.options_properties = f"__init__{signature}\n{doc}" + def _get_marker_file_name(self): + return ".odoo_fs_storage_%s.marker" % self.id + + def _check_connection(self, fs): + marker_file_name = self._get_marker_file_name() + try: + marker_file = fs.ls(marker_file_name, detail=False) + if not marker_file: + fs.touch(marker_file_name) + except FileNotFoundError: + fs.touch(marker_file_name) + return True + @property def fs(self) -> fsspec.AbstractFileSystem: """Get the fsspec filesystem for this backend.""" self.ensure_one() if not self.__fs: self.__fs = self._get_filesystem() + if not tools.config["test_enable"]: + # Check whether we need to invalidate FS cache or not. + # Use a marker file to limit the scope of the LS command for performance. + try: + self._check_connection(self.__fs) + except Exception as e: + self.__fs.clear_instance_cache() + raise e return self.__fs def _get_filesystem_storage_path(self) -> str: @@ -431,7 +452,7 @@ def delete(self, relative_path) -> None: def action_test_config(self) -> None: try: - self.fs.ls("", detail=False) + self._check_connection(self.__fs) title = _("Connection Test Succeeded!") message = _("Everything seems properly set up!") msg_type = "success" diff --git a/fs_storage/readme/newsfragments/320.feature b/fs_storage/readme/newsfragments/320.feature new file mode 100644 index 0000000000..5644d66085 --- /dev/null +++ b/fs_storage/readme/newsfragments/320.feature @@ -0,0 +1 @@ +Invalidate FS filesystem object cache when the connection fails, forcing a reconnection. From c3ed72f83bd07997581a7611fcf83f6bc67cb09a Mon Sep 17 00:00:00 2001 From: Tran Anh Tuan Date: Thu, 4 Jan 2024 17:35:18 +0700 Subject: [PATCH 46/54] [IMP] fs_storage: improve find_files pattern match, pattern matching should only apply to file name, not full path --- fs_storage/models/fs_storage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index d140cb795f..4d7610d232 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -427,7 +427,8 @@ def find_files(self, pattern, relative_path="", **kw) -> list[str]: return [] regex = re.compile(pattern) for file_path in self.fs.ls(relative_path, detail=False): - if regex.match(file_path): + # fs.ls returns a relative path + if regex.match(os.path.basename(file_path)): result.append(file_path) return result From 23f5797175da11df4249df0d4b24684ad0b6f1ce Mon Sep 17 00:00:00 2001 From: Nils Hamerlinck Date: Wed, 7 Feb 2024 14:17:55 +0700 Subject: [PATCH 47/54] [IMP] fs_storage: use fs.info() to check for the marker file --- fs_storage/models/fs_storage.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index 4d7610d232..9e9958d25f 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -270,9 +270,7 @@ def _get_marker_file_name(self): def _check_connection(self, fs): marker_file_name = self._get_marker_file_name() try: - marker_file = fs.ls(marker_file_name, detail=False) - if not marker_file: - fs.touch(marker_file_name) + fs.info(marker_file_name) except FileNotFoundError: fs.touch(marker_file_name) return True From c49b83cccca2a2f98440ddb0b13bd50aa894097a Mon Sep 17 00:00:00 2001 From: JordiMForgeFlow Date: Wed, 7 Feb 2024 09:19:04 +0100 Subject: [PATCH 48/54] [FIX] fs_storage: fix test connection when __fs slot is not initialized --- fs_storage/models/fs_storage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index 9e9958d25f..ab75c5f3e1 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -451,7 +451,8 @@ def delete(self, relative_path) -> None: def action_test_config(self) -> None: try: - self._check_connection(self.__fs) + # pylint: disable=W0104 + self.fs title = _("Connection Test Succeeded!") message = _("Everything seems properly set up!") msg_type = "success" From 899e11aa333e22803a75f8a1f913dbfe56f91fb3 Mon Sep 17 00:00:00 2001 From: JordiMForgeFlow Date: Thu, 8 Feb 2024 15:21:43 +0100 Subject: [PATCH 49/54] [IMP] fs_storage: clear slot when connection fails --- fs_storage/models/fs_storage.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index ab75c5f3e1..0745df38d9 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -288,6 +288,7 @@ def fs(self) -> fsspec.AbstractFileSystem: self._check_connection(self.__fs) except Exception as e: self.__fs.clear_instance_cache() + self.__fs = None raise e return self.__fs @@ -451,6 +452,7 @@ def delete(self, relative_path) -> None: def action_test_config(self) -> None: try: + # Accessing the property will check the connection # pylint: disable=W0104 self.fs title = _("Connection Test Succeeded!") From db9a676352c7a0eb2e204503111fe5e61895c635 Mon Sep 17 00:00:00 2001 From: Florian da Costa Date: Fri, 5 Apr 2024 10:39:20 +0200 Subject: [PATCH 50/54] [IMP] fs_storage : Allow to choose different method to check connection --- fs_storage/__init__.py | 1 + fs_storage/__manifest__.py | 1 + fs_storage/models/fs_storage.py | 46 ++++++++++++++++++++++- fs_storage/readme/USAGE.md | 10 +++++ fs_storage/security/ir.model.access.csv | 1 + fs_storage/views/fs_storage_view.xml | 1 + fs_storage/wizards/__init__.py | 1 + fs_storage/wizards/fs_test_connection.py | 28 ++++++++++++++ fs_storage/wizards/fs_test_connection.xml | 31 +++++++++++++++ 9 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 fs_storage/wizards/__init__.py create mode 100644 fs_storage/wizards/fs_test_connection.py create mode 100644 fs_storage/wizards/fs_test_connection.xml diff --git a/fs_storage/__init__.py b/fs_storage/__init__.py index 1df985fe64..6f3a6c7170 100644 --- a/fs_storage/__init__.py +++ b/fs_storage/__init__.py @@ -4,3 +4,4 @@ # then add normal imports from . import models +from . import wizards diff --git a/fs_storage/__manifest__.py b/fs_storage/__manifest__.py index 8d80a3cb18..d209fd8ea7 100644 --- a/fs_storage/__manifest__.py +++ b/fs_storage/__manifest__.py @@ -16,6 +16,7 @@ "data": [ "views/fs_storage_view.xml", "security/ir.model.access.csv", + "wizards/fs_test_connection.xml", ], "demo": ["demo/fs_storage_demo.xml"], "external_dependencies": {"python": ["fsspec>=2024.5.0"]}, diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index 0745df38d9..ed289a8f0e 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -146,6 +146,15 @@ def __init__(self, env, ids=(), prefetch_ids=()): compute="_compute_options_properties", store=False, ) + check_connection_method = fields.Selection( + selection="_get_check_connection_method_selection", + default="marker_file", + help="Set a method if you want the connection to remote to be checked every " + "time the storage is used, in order to remove the obsolete connection from" + " the cache.\n" + "* Create Marker file : Create a file on remote and check it exists\n" + "* List File : List all files from root directory", + ) _sql_constraints = [ ( @@ -157,6 +166,13 @@ def __init__(self, env, ids=(), prefetch_ids=()): _server_env_section_name_field = "code" + @api.model + def _get_check_connection_method_selection(self): + return [ + ("marker_file", _("Create Marker file")), + ("ls", _("List File")), + ] + @property def _server_env_fields(self): return {"protocol": {}, "options": {}, "directory_path": {}} @@ -267,14 +283,29 @@ def _compute_options_properties(self) -> None: def _get_marker_file_name(self): return ".odoo_fs_storage_%s.marker" % self.id - def _check_connection(self, fs): + def _marker_file_check_connection(self, fs): marker_file_name = self._get_marker_file_name() try: fs.info(marker_file_name) except FileNotFoundError: fs.touch(marker_file_name) + + def _ls_check_connection(self, fs): + fs.ls("", detail=False) + + def _check_connection_with_method(self, fs, check_connection_method): + if check_connection_method == "marker_file": + self._marker_file_check_connection(fs) + elif check_connection_method == "ls": + self._ls_check_connection(fs) return True + def _check_connection(self, fs): + check_connection_method = self.check_connection_method or self.env.context.get( + "force_connection_method", "" + ) + return self._check_connection_with_method(fs, check_connection_method) + @property def fs(self) -> fsspec.AbstractFileSystem: """Get the fsspec filesystem for this backend.""" @@ -450,7 +481,18 @@ def move_files(self, files, destination_path, **kw) -> None: def delete(self, relative_path) -> None: self.fs.rm_file(relative_path) - def action_test_config(self) -> None: + def action_test_config(self): + self.ensure_one() + if self.check_connection_method: + return self._test_config() + else: + action = self.env["ir.actions.actions"]._for_xml_id( + "fs_storage.act_open_fs_test_connection_view" + ) + action["context"] = {"active_model": "fs.storage", "active_id": self.id} + return action + + def _test_config(self): try: # Accessing the property will check the connection # pylint: disable=W0104 diff --git a/fs_storage/readme/USAGE.md b/fs_storage/readme/USAGE.md index 2379e3b398..ac73b9bc4b 100644 --- a/fs_storage/readme/USAGE.md +++ b/fs_storage/readme/USAGE.md @@ -18,6 +18,16 @@ When you create a new backend, you must specify the following: documentation. - Resolve env vars. This options resolves the protocol options values starting with \$ from environment variables +- Check Connection Method. If set, Odoo will always check the connection before + using a storage and it will remove the fs connection from the cache if the + check fails. + + - `Create Marker file`: create a hidden file on remote and then check it + exists with Use it if you have write access to the remote and if it is not + an issue to leave the marker file in the root directory. + - `List file`: list all files from the root directory. You can use it if the + directory path does not contain a big list of files (for performance + reasons) Some protocols defined in the fsspec package are wrappers around other protocols. For example, the SimpleCacheFileSystem protocol is a wrapper diff --git a/fs_storage/security/ir.model.access.csv b/fs_storage/security/ir.model.access.csv index 9c079b2eef..c1a81aae11 100644 --- a/fs_storage/security/ir.model.access.csv +++ b/fs_storage/security/ir.model.access.csv @@ -1,2 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_fs_storage_edit,fs_storage edit,model_fs_storage,base.group_system,1,1,1,1 +access_fs_test_connection,fs.test.connection.access,model_fs_test_connection,base.group_system,1,1,1,1 diff --git a/fs_storage/views/fs_storage_view.xml b/fs_storage/views/fs_storage_view.xml index 3e25196230..712bb2a656 100644 --- a/fs_storage/views/fs_storage_view.xml +++ b/fs_storage/views/fs_storage_view.xml @@ -42,6 +42,7 @@ options="{'mode': 'python'}" placeholder="Enter you fsspec options here." /> + diff --git a/fs_storage/wizards/__init__.py b/fs_storage/wizards/__init__.py new file mode 100644 index 0000000000..197ee33cb7 --- /dev/null +++ b/fs_storage/wizards/__init__.py @@ -0,0 +1 @@ +from . import fs_test_connection diff --git a/fs_storage/wizards/fs_test_connection.py b/fs_storage/wizards/fs_test_connection.py new file mode 100644 index 0000000000..b5bc86a2ca --- /dev/null +++ b/fs_storage/wizards/fs_test_connection.py @@ -0,0 +1,28 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import api, fields, models + + +class FSTestConnection(models.TransientModel): + _name = "fs.test.connection" + _description = "FS Test Connection Wizard" + + def _get_check_connection_method_selection(self): + return self.env["fs.storage"]._get_check_connection_method_selection() + + storage_id = fields.Many2one("fs.storage") + check_connection_method = fields.Selection( + selection="_get_check_connection_method_selection", + required=True, + ) + + @api.model + def default_get(self, field_list): + res = super().default_get(field_list) + res["storage_id"] = self.env.context.get("active_id", False) + return res + + def action_test_config(self): + return self.storage_id.with_context( + force_connection_method=self.check_connection_method + )._test_config() diff --git a/fs_storage/wizards/fs_test_connection.xml b/fs_storage/wizards/fs_test_connection.xml new file mode 100644 index 0000000000..2abed80164 --- /dev/null +++ b/fs_storage/wizards/fs_test_connection.xml @@ -0,0 +1,31 @@ + + + + fs.test.connection.form + fs.test.connection + +
+ + + + +
+
+
+
+
+ + FS Test Connection + ir.actions.act_window + fs.test.connection + form + new + +
From ca5c809dac505f3bc31a52d6c555419b4a983fd3 Mon Sep 17 00:00:00 2001 From: Florian da Costa Date: Mon, 8 Apr 2024 18:39:31 +0200 Subject: [PATCH 51/54] [FIX] Avoid use of context to pass the check_connection_method --- fs_storage/models/fs_storage.py | 18 +++++------------- fs_storage/wizards/fs_test_connection.py | 4 +--- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index ed289a8f0e..1961a50bd2 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -293,19 +293,13 @@ def _marker_file_check_connection(self, fs): def _ls_check_connection(self, fs): fs.ls("", detail=False) - def _check_connection_with_method(self, fs, check_connection_method): + def _check_connection(self, fs, check_connection_method): if check_connection_method == "marker_file": self._marker_file_check_connection(fs) elif check_connection_method == "ls": self._ls_check_connection(fs) return True - def _check_connection(self, fs): - check_connection_method = self.check_connection_method or self.env.context.get( - "force_connection_method", "" - ) - return self._check_connection_with_method(fs, check_connection_method) - @property def fs(self) -> fsspec.AbstractFileSystem: """Get the fsspec filesystem for this backend.""" @@ -316,7 +310,7 @@ def fs(self) -> fsspec.AbstractFileSystem: # Check whether we need to invalidate FS cache or not. # Use a marker file to limit the scope of the LS command for performance. try: - self._check_connection(self.__fs) + self._check_connection(self.__fs, self.check_connection_method) except Exception as e: self.__fs.clear_instance_cache() self.__fs = None @@ -484,7 +478,7 @@ def delete(self, relative_path) -> None: def action_test_config(self): self.ensure_one() if self.check_connection_method: - return self._test_config() + return self._test_config(self.check_connection_method) else: action = self.env["ir.actions.actions"]._for_xml_id( "fs_storage.act_open_fs_test_connection_view" @@ -492,11 +486,9 @@ def action_test_config(self): action["context"] = {"active_model": "fs.storage", "active_id": self.id} return action - def _test_config(self): + def _test_config(self, connection_method): try: - # Accessing the property will check the connection - # pylint: disable=W0104 - self.fs + self._check_connection(self.fs, connection_method) title = _("Connection Test Succeeded!") message = _("Everything seems properly set up!") msg_type = "success" diff --git a/fs_storage/wizards/fs_test_connection.py b/fs_storage/wizards/fs_test_connection.py index b5bc86a2ca..ebaf6154cc 100644 --- a/fs_storage/wizards/fs_test_connection.py +++ b/fs_storage/wizards/fs_test_connection.py @@ -23,6 +23,4 @@ def default_get(self, field_list): return res def action_test_config(self): - return self.storage_id.with_context( - force_connection_method=self.check_connection_method - )._test_config() + return self.storage_id._test_config(self.check_connection_method) From b72f7f6a9e28215d36f1545591fac4e90f7067d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 12 Jul 2024 16:10:01 +0200 Subject: [PATCH 52/54] [FIX] fs_storage: add missing sudo when creating FilsSystem This is necessary for non admin users to access file systems, for instance for attachments. This went unnoticed so far presumably because the filesystem is cached and likely accessed by the server during server bootstrap. --- fs_storage/models/fs_storage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index 1961a50bd2..ebbb51149c 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -305,7 +305,7 @@ def fs(self) -> fsspec.AbstractFileSystem: """Get the fsspec filesystem for this backend.""" self.ensure_one() if not self.__fs: - self.__fs = self._get_filesystem() + self.__fs = self.sudo()._get_filesystem() if not tools.config["test_enable"]: # Check whether we need to invalidate FS cache or not. # Use a marker file to limit the scope of the LS command for performance. From 086be25dd871633683f01844ca8d82958d197a36 Mon Sep 17 00:00:00 2001 From: Quentin Groulard Date: Mon, 7 Oct 2024 12:16:58 +0200 Subject: [PATCH 53/54] [IMP] fs_storage: pre-commit auto fixes --- fs_storage/README.rst | 27 ++++++++++++++++++----- fs_storage/models/fs_storage.py | 2 +- fs_storage/static/description/index.html | 18 ++++++++++++--- fs_storage/wizards/fs_test_connection.xml | 1 - requirements.txt | 2 ++ 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 requirements.txt diff --git a/fs_storage/README.rst b/fs_storage/README.rst index 445c949f88..372ec4d1b6 100644 --- a/fs_storage/README.rst +++ b/fs_storage/README.rst @@ -17,13 +17,13 @@ Filesystem Storage Backend :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github - :target: https://github.com/OCA/storage/tree/17.0/fs_storage + :target: https://github.com/OCA/storage/tree/18.0/fs_storage :alt: OCA/storage .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_storage + :target: https://translation.odoo-community.org/projects/storage-18-0/storage-18-0-fs_storage :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=17.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -108,21 +108,38 @@ When you create a new backend, you must specify the following: - The name of the backend. This is the name that will be used to identify the backend into Odoo + - The code of the backend. This code will identify the backend into the store_fname field of the ir.attachment model. This code must be unique. It will be used as scheme. example of the store_fname field: ``odoofs://abs34Tg11``. + - The protocol used by the backend. The protocol refers to the supported protocols of the fsspec python package. + - A directory path. This is a root directory from which the filesystem will be mounted. This directory must exist. + - The protocol options. These are the options that will be passed to the fsspec python package when creating the filesystem. These options depend on the protocol used and are described in the fsspec documentation. + - Resolve env vars. This options resolves the protocol options values starting with $ from environment variables +- Check Connection Method. If set, Odoo will always check the + connection before using a storage and it will remove the fs + connection from the cache if the check fails. + + - ``Create Marker file``: create a hidden file on remote and then + check it exists with Use it if you have write access to the remote + and if it is not an issue to leave the marker file in the root + directory. + - ``List file``: list all files from the root directory. You can use + it if the directory path does not contain a big list of files (for + performance reasons) + Some protocols defined in the fsspec package are wrappers around other protocols. For example, the SimpleCacheFileSystem protocol is a wrapper around any local filesystem protocol. In such cases, you must specify @@ -248,7 +265,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -279,6 +296,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/storage `_ project on GitHub. +This module is part of the `OCA/storage `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index ebbb51149c..f43f7b4bad 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -281,7 +281,7 @@ def _compute_options_properties(self) -> None: rec.options_properties = f"__init__{signature}\n{doc}" def _get_marker_file_name(self): - return ".odoo_fs_storage_%s.marker" % self.id + return f".odoo_fs_storage_{self.id}.marker" def _marker_file_check_connection(self, fs): marker_file_name = self._get_marker_file_name() diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html index 588354460a..bd85d3c61c 100644 --- a/fs_storage/static/description/index.html +++ b/fs_storage/static/description/index.html @@ -369,7 +369,7 @@

Filesystem Storage Backend

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:6e7abac468ff2942178ac2df68774f75820b618173acf8c7b76f51fbdbe3b7bc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

This addon is a technical addon that allows you to define filesystem like storage for your data. It’s used by other addons to store their data in a transparent way into different kind of storages.

@@ -478,6 +478,18 @@

Configuration

documentation.
  • Resolve env vars. This options resolves the protocol options values starting with $ from environment variables
  • +
  • Check Connection Method. If set, Odoo will always check the +connection before using a storage and it will remove the fs +connection from the cache if the check fails.
      +
    • Create Marker file: create a hidden file on remote and then +check it exists with Use it if you have write access to the remote +and if it is not an issue to leave the marker file in the root +directory.
    • +
    • List file: list all files from the root directory. You can use +it if the directory path does not contain a big list of files (for +performance reasons)
    • +
    +
  • Some protocols defined in the fsspec package are wrappers around other protocols. For example, the SimpleCacheFileSystem protocol is a wrapper @@ -599,7 +611,7 @@

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

    @@ -626,7 +638,7 @@

    Maintainers

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    -

    This module is part of the OCA/storage project on GitHub.

    +

    This module is part of the OCA/storage project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    diff --git a/fs_storage/wizards/fs_test_connection.xml b/fs_storage/wizards/fs_test_connection.xml index 2abed80164..2846f7e3d3 100644 --- a/fs_storage/wizards/fs_test_connection.xml +++ b/fs_storage/wizards/fs_test_connection.xml @@ -16,7 +16,6 @@ string="Test connection" />