diff --git a/.copier-answers.yml b/.copier-answers.yml
index a406cf7de8..f63257825c 100644
--- a/.copier-answers.yml
+++ b/.copier-answers.yml
@@ -1,5 +1,5 @@
# Do NOT update manually; changes here will be overwritten by Copier
-_commit: v1.34
+_commit: v1.35
_src_path: git+https://github.com/OCA/oca-addons-repo-template
additional_ruff_rules: []
ci: GitHub
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f737dac10a..bc2df15a45 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -8,7 +8,6 @@ exclude: |
^fs_folder_demo/|
^fs_folder_ms_drive/|
^fs_image/|
- ^fs_storage/|
^fs_storage_ms_drive/|
^image_tag/|
^microsoft_drive_account/|
diff --git a/.pylintrc b/.pylintrc
index 16996cb36f..f3d017a8f5 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -23,21 +23,12 @@ disable=all
# config as a blocking check.
enable=anomalous-backslash-in-string,
- api-one-deprecated,
- api-one-multi-together,
assignment-from-none,
attribute-deprecated,
- class-camelcase,
dangerous-default-value,
- dangerous-view-replace-wo-priority,
development-status-allowed,
- duplicate-id-csv,
duplicate-key,
- duplicate-xml-fields,
- duplicate-xml-record-id,
- eval-referenced,
eval-used,
- incoherent-interpreter-exec-perm,
license-allowed,
manifest-author-string,
manifest-deprecated-key,
@@ -48,56 +39,33 @@ enable=anomalous-backslash-in-string,
method-inverse,
method-required-super,
method-search,
- openerp-exception-warning,
pointless-statement,
pointless-string-statement,
print-used,
redundant-keyword-arg,
- redundant-modulename-xml,
reimported,
- relative-import,
return-in-init,
- rst-syntax-error,
sql-injection,
too-few-format-args,
translation-field,
translation-required,
unreachable,
use-vim-comment,
- wrong-tabs-instead-of-spaces,
- xml-syntax-error,
attribute-string-redundant,
- character-not-valid-in-resource-link,
consider-merging-classes-inherited,
context-overridden,
- create-user-wo-reset-password,
- dangerous-filter-wo-user,
- dangerous-qweb-replace-wo-priority,
- deprecated-data-xml-node,
- deprecated-openerp-xml-node,
- duplicate-po-message-definition,
except-pass,
- file-not-used,
invalid-commit,
manifest-maintainers-list,
- missing-newline-extrafiles,
missing-readme,
missing-return,
odoo-addons-relative-import,
- old-api7-method-defined,
- po-msgstr-variables,
- po-syntax-error,
renamed-field-parameter,
resource-not-exist,
- str-format-used,
test-folder-imported,
translation-contains-variable,
translation-positional-used,
- unnecessary-utf8-coding-comment,
website-manifest-key-not-valid-uri,
- xml-attribute-translatable,
- xml-deprecated-qweb-directive,
- xml-deprecated-tree-attribute,
external-request-timeout,
bad-builtin-groupby,
category-allowed,
diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory
index dc9b71ed30..80567de1e7 100644
--- a/.pylintrc-mandatory
+++ b/.pylintrc-mandatory
@@ -15,21 +15,12 @@ valid-odoo-versions=19.0
disable=all
enable=anomalous-backslash-in-string,
- api-one-deprecated,
- api-one-multi-together,
assignment-from-none,
attribute-deprecated,
- class-camelcase,
dangerous-default-value,
- dangerous-view-replace-wo-priority,
development-status-allowed,
- duplicate-id-csv,
duplicate-key,
- duplicate-xml-fields,
- duplicate-xml-record-id,
- eval-referenced,
eval-used,
- incoherent-interpreter-exec-perm,
license-allowed,
manifest-author-string,
manifest-deprecated-key,
@@ -40,56 +31,33 @@ enable=anomalous-backslash-in-string,
method-inverse,
method-required-super,
method-search,
- openerp-exception-warning,
pointless-statement,
pointless-string-statement,
print-used,
redundant-keyword-arg,
- redundant-modulename-xml,
reimported,
- relative-import,
return-in-init,
- rst-syntax-error,
sql-injection,
too-few-format-args,
translation-field,
translation-required,
unreachable,
use-vim-comment,
- wrong-tabs-instead-of-spaces,
- xml-syntax-error,
attribute-string-redundant,
- character-not-valid-in-resource-link,
consider-merging-classes-inherited,
context-overridden,
- create-user-wo-reset-password,
- dangerous-filter-wo-user,
- dangerous-qweb-replace-wo-priority,
- deprecated-data-xml-node,
- deprecated-openerp-xml-node,
- duplicate-po-message-definition,
except-pass,
- file-not-used,
invalid-commit,
manifest-maintainers-list,
- missing-newline-extrafiles,
missing-readme,
missing-return,
odoo-addons-relative-import,
- old-api7-method-defined,
- po-msgstr-variables,
- po-syntax-error,
renamed-field-parameter,
resource-not-exist,
- str-format-used,
test-folder-imported,
translation-contains-variable,
translation-positional-used,
- unnecessary-utf8-coding-comment,
website-manifest-key-not-valid-uri,
- xml-attribute-translatable,
- xml-deprecated-qweb-directive,
- xml-deprecated-tree-attribute,
external-request-timeout,
bad-builtin-groupby,
category-allowed,
diff --git a/fs_storage/README.rst b/fs_storage/README.rst
index 95bbcb6801..35ebd9f687 100644
--- a/fs_storage/README.rst
+++ b/fs_storage/README.rst
@@ -21,13 +21,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/18.0/fs_storage
+ :target: https://github.com/OCA/storage/tree/19.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-18-0/storage-18-0-fs_storage
+ :target: https://translation.odoo-community.org/projects/storage-19-0/storage-19-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=18.0
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=19.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -287,7 +287,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.
@@ -305,6 +305,7 @@ Contributors
- Laurent Mignon
- Sébastien BEAU
- Marie Lejeune
+- Julien Coux
Maintainers
-----------
@@ -319,6 +320,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/__manifest__.py b/fs_storage/__manifest__.py
index 401e5748eb..d6bb9bf5f4 100644
--- a/fs_storage/__manifest__.py
+++ b/fs_storage/__manifest__.py
@@ -5,19 +5,18 @@
{
"name": "Filesystem Storage Backend",
"summary": "Implement the concept of Storage with amazon S3, sftp...",
- "version": "18.0.2.0.1",
+ "version": "19.0.1.0.0",
"category": "FS Storage",
"website": "https://github.com/OCA/storage",
"author": " ACSONE SA/NV, Odoo Community Association (OCA)",
"license": "LGPL-3",
"development_status": "Beta",
- "installable": False,
"depends": ["base", "base_sparse_field", "server_environment"],
"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"]},
+ "installable": True,
}
diff --git a/fs_storage/demo/fs_storage_demo.xml b/fs_storage/demo/fs_storage_demo.xml
deleted file mode 100644
index 0917d06221..0000000000
--- a/fs_storage/demo/fs_storage_demo.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
- Odoo Filesystem Backend
- odoofs
- odoofs
-
-
diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py
index 14941c540b..3e516be4f7 100644
--- a/fs_storage/models/fs_storage.py
+++ b/fs_storage/models/fs_storage.py
@@ -14,7 +14,7 @@
import fsspec
-from odoo import _, api, fields, models, tools
+from odoo import api, fields, models, tools
from odoo.exceptions import ValidationError
from odoo.addons.base_sparse_field.models.fields import Serialized
@@ -189,13 +189,10 @@ def __init__(self, env, ids=(), prefetch_ids=()):
"* List File : List all files from root directory",
)
- _sql_constraints = [
- (
- "code_uniq",
- "unique(code)",
- "The code must be unique",
- ),
- ]
+ _uniq_code = models.Constraint(
+ "unique(code)",
+ "The code must be unique",
+ )
_server_env_section_name_field = "code"
@@ -210,7 +207,7 @@ def _check_model_xmlid_storage_unique(self):
xmlids = rec.model_xmlids.split(",")
for xmlid in xmlids:
other_storages = (
- self.env["fs.storage"]
+ self.env["fs.storage"] # pylint: disable=no-search-all
.search([])
.filtered_domain(
[
@@ -221,11 +218,12 @@ def _check_model_xmlid_storage_unique(self):
)
if other_storages:
raise ValidationError(
- _(
+ self.env._(
"Model %(model)s already stored in another "
- "FS storage ('%(other_storage)s')"
+ "FS storage ('%(other_storage)s')",
+ model=xmlid,
+ other_storage=other_storages[0].name,
)
- % {"model": xmlid, "other_storage": other_storages[0].name}
)
@api.constrains("field_xmlids")
@@ -239,7 +237,7 @@ def _check_field_xmlid_storage_unique(self):
xmlids = rec.field_xmlids.split(",")
for xmlid in xmlids:
other_storages = (
- self.env["fs.storage"]
+ self.env["fs.storage"] # pylint: disable=no-search-all
.search([])
.filtered_domain(
[
@@ -250,18 +248,19 @@ def _check_field_xmlid_storage_unique(self):
)
if other_storages:
raise ValidationError(
- _(
+ self.env._(
"Field %(field)s already stored in another "
- "FS storage ('%(other_storage)s')"
+ "FS storage ('%(other_storage)s')",
+ field=xmlid,
+ other_storage=other_storages[0].name,
)
- % {"field": xmlid, "other_storage": other_storages[0].name}
)
@api.model
def _get_check_connection_method_selection(self):
return [
- ("marker_file", _("Create Marker file")),
- ("ls", _("List File")),
+ ("marker_file", self.env._("Create Marker file")),
+ ("ls", self.env._("List File")),
]
@property
@@ -338,7 +337,7 @@ def get_storage_code_by_model_field(self, model_name, field_name=None):
)
if field:
storage = (
- self.env["fs.storage"]
+ self.env["fs.storage"] # pylint: disable=no-search-all
.sudo()
.search([])
.filtered_domain([("field_ids", "in", [field.id])])
@@ -353,7 +352,7 @@ def get_storage_code_by_model_field(self, model_name, field_name=None):
)
if model:
storage = (
- self.env["fs.storage"]
+ self.env["fs.storage"] # pylint: disable=no-search-all
.sudo()
.search([])
.filtered_domain([("model_ids", "in", [model.id])])
@@ -399,7 +398,9 @@ def _check_options(self) -> None:
try:
json.loads(rec.options or "{}")
except Exception as e:
- raise ValidationError(_("The options must be a valid JSON")) from e
+ raise ValidationError(
+ self.env._("The options must be a valid JSON")
+ ) from e
@api.depends("options")
def _compute_json_options(self) -> None:
@@ -703,11 +704,11 @@ def action_test_config(self):
def _test_config(self, connection_method):
try:
self._check_connection(self.fs, connection_method)
- title = _("Connection Test Succeeded!")
- message = _("Everything seems properly set up!")
+ title = self.env._("Connection Test Succeeded!")
+ message = self.env._("Everything seems properly set up!")
msg_type = "success"
except Exception as err:
- title = _("Connection Test Failed!")
+ title = self.env._("Connection Test Failed!")
message = str(err)
msg_type = "danger"
return {
diff --git a/fs_storage/readme/CONTRIBUTORS.md b/fs_storage/readme/CONTRIBUTORS.md
index 139cad9973..0ec48212d3 100644
--- a/fs_storage/readme/CONTRIBUTORS.md
+++ b/fs_storage/readme/CONTRIBUTORS.md
@@ -1,3 +1,4 @@
- Laurent Mignon \<\>
- Sébastien BEAU \<\>
- Marie Lejeune \<\>
+- Julien Coux \<\>
diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html
index 13eba13760..d72205ab97 100644
--- a/fs_storage/static/description/index.html
+++ b/fs_storage/static/description/index.html
@@ -374,7 +374,7 @@ Filesystem Storage Backend
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:bef82e0e40abd3cfd18d50b3c781d338527ee3bb71f926647c1b5ceeab1fc988
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

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.
@@ -644,7 +644,7 @@
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.
@@ -672,7 +673,7 @@
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/tests/common.py b/fs_storage/tests/common.py
index 03dd68762f..76e73eb8f8 100644
--- a/fs_storage/tests/common.py
+++ b/fs_storage/tests/common.py
@@ -6,6 +6,7 @@
import tempfile
from unittest import mock
+from odoo.fields import Command
from odoo.tests.common import TransactionCase
from ..models.fs_storage import FSStorage
@@ -16,12 +17,31 @@ 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.fs_storage_demo")
+ cls.backend: FSStorage = cls.env["fs.storage"].create(
+ {
+ "name": "Odoo Filesystem Backend",
+ "protocol": "odoofs",
+ "code": "odoofs",
+ }
+ )
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")
+ cls.demo_user = (
+ cls.env["res.users"]
+ .with_context(no_reset_password=True)
+ .create(
+ {
+ "name": "Test User",
+ "login": "demo",
+ "password": "demo",
+ "email": "test@yourcompany.com",
+ "company_id": cls.env.ref("base.main_company").id,
+ "group_ids": [Command.link(cls.env.ref("base.group_user").id)],
+ }
+ )
+ )
cls.temp_dir = tempfile.mkdtemp()
def setUp(self):
diff --git a/fs_storage/tests/test_fs_storage.py b/fs_storage/tests/test_fs_storage.py
index 3d23512a4c..7ef6859a97 100644
--- a/fs_storage/tests/test_fs_storage.py
+++ b/fs_storage/tests/test_fs_storage.py
@@ -82,7 +82,12 @@ def test_ensure_one_fs_by_record(self):
for i in range(4):
backend_ids.append(
self.backend.create(
- {"name": f"name{i}", "directory_path": f"{i}", "code": f"code{i}"}
+ {
+ "name": f"name{i}",
+ "directory_path": f"{i}",
+ "code": f"code{i}",
+ "protocol": "odoofs",
+ }
).id
)
records = self.backend.browse(backend_ids)
@@ -227,7 +232,6 @@ def test_constraint_unique_storage_model(self):
A given model can be linked to a unique storage
"""
self.backend.model_xmlids = "base.model_res_partner,base.model_ir_attachment"
- self.env.ref("fs_storage.fs_storage_demo")
with self.assertRaises(ValidationError):
self.copy_backend.model_xmlids = "base.model_res_partner"
diff --git a/requirements.txt b/requirements.txt
index aeccb5304f..0905f9449e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,10 +1,2 @@
# generated from manifests external_dependencies
-boto3
fsspec>=2024.5.0
-fsspec>=2025.0.0
-fsspec>=2025.3.0
-fsspec[s3]
-msgraphfs
-paramiko
-pyftpdlib
-python_slugify