Skip to content

Commit

Permalink
[ADD] fs_image: wip....
Browse files Browse the repository at this point in the history
  • Loading branch information
lmignon committed Aug 25, 2023
1 parent 2c62923 commit 52728c1
Show file tree
Hide file tree
Showing 15 changed files with 514 additions and 62 deletions.
98 changes: 36 additions & 62 deletions fs_file/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ def name(self, value: str) -> None:
"yet stored"
)

@property
def is_new(self) -> bool:
return self._is_new

@property
def mimetype(self) -> str | None:
return self._attachment.mimetype if self._attachment else None
Expand Down Expand Up @@ -220,7 +224,7 @@ def read(self, records):
("res_id", "in", records.ids),
]
data = {
att.res_id: FSFileValue(attachment=att)
att.res_id: self._convert_attachment_to_cache(att)
for att in records.env["ir.attachment"].sudo().search(domain)
}
records.env.cache.insert_missing(records, self, map(data.get, records._ids))
Expand All @@ -230,33 +234,39 @@ def create(self, record_values):
return
env = record_values[0][0].env
with env.norecompute():
ir_attachment = (
env["ir.attachment"]
.sudo()
.with_context(
binary_field_real_user=env.user,
)
)
for record, value in record_values:
if value:
cache_value = self.convert_to_cache(value, record)
attachment = ir_attachment.create(
{
"name": cache_value.name,
"raw": cache_value.getvalue(),
"res_model": record._name,
"res_field": self.name,
"res_id": record.id,
"type": "binary",
}
)
attachment = self._create_attachment(record, cache_value)
cache_value = self._convert_attachment_to_cache(attachment)
record.env.cache.update(
record,
self,
[FSFileValue(attachment=attachment)],
[cache_value],
dirty=False,
)

def _create_attachment(self, record, cache_value: FSFileValue):
ir_attachment = (
record.env["ir.attachment"]
.sudo()
.with_context(
binary_field_real_user=record.env.user,
)
)
create_value = self._prepare_attachment_create_values(record, cache_value)
return ir_attachment.create(create_value)

def _prepare_attachment_create_values(self, record, cache_value: FSFileValue):
return {
"name": cache_value.name,
"raw": cache_value.getvalue(),
"res_model": record._name,
"res_field": self.name,
"res_id": record.id,
"type": "binary",
}

def write(self, records, value):
# the code is copied from the standard Odoo Binary field
# with the following changes:
Expand Down Expand Up @@ -304,29 +314,23 @@ def write(self, records, value):
# create the missing attachments
missing = real_records - atts_records
if missing:
create_vals = []
created = atts.browse()
for record in missing:
create_vals.append(
{
"name": filename,
"res_model": record._name,
"res_field": self.name,
"res_id": record.id,
"type": "binary",
"raw": content,
}
)
created = atts.create(create_vals)
created |= self._create_attachment(record, cache_value)
for att in created:
record = records.browse(att.res_id)
new_cache_value = self._convert_attachment_to_cache(att)
record.env.cache.update(
record, self, [FSFileValue(attachment=att)], dirty=False
record, self, [new_cache_value], dirty=False
)
else:
atts.unlink()

return records

def _convert_attachment_to_cache(self, attachment: IrAttachment) -> FSFileValue:
return FSFileValue(attachment=attachment)

def _get_filename(self, record):
return record.env.context.get("fs_filename", self.name)

Expand Down Expand Up @@ -356,36 +360,6 @@ def convert_to_cache(self, value, record, validate=True):
def convert_to_write(self, value, record):
return self.convert_to_cache(value, record)

def __convert_to_column(self, value, record, values=None, validate=True):
if value is None or value is False:
return None
if isinstance(value, IOBase):
if hasattr(value, "getvalue"):
value = value.getvalue()
else:
v = value.read()
value.seek(0)
value = v
return value
if isinstance(value, bytes):
return base64.b64decode(value)
raise ValueError(
"Invalid value for %s: %r\n"
"Should be base64 encoded bytes or a file-like object" % (self, value)
)

def __convert_to_record(self, value, record):
if value is None or value is False:
return None
if isinstance(value, IOBase):
return value
if isinstance(value, bytes):
return FSFileValue(value=value)
raise ValueError(
"Invalid value for %s: %r\n"
"Should be base64 encoded bytes or a file-like object" % (self, value)
)

def convert_to_read(self, value, record, use_name_get=True):
if value is None or value is False:
return None
Expand Down
35 changes: 35 additions & 0 deletions fs_image/README.rst
Original file line number Diff line number Diff line change
@@ -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 <https://pypi.org/project/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 <https://github.com/OCA/maintainer-tools>`_.
1 change: 1 addition & 0 deletions fs_image/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
17 changes: 17 additions & 0 deletions fs_image/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Fs Image",
"summary": """
Field to store images into filesystem storages""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/storage",
"depends": ["fs_file"],
"data": [],
"demo": [],
"maintainers": ["lmignon"],
"development_status": "Alpha",
}
Loading

0 comments on commit 52728c1

Please sign in to comment.