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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Available addons
----------------
addon | version | maintainers | summary
--- | --- | --- | ---
[attachment_unindex_content](attachment_unindex_content/) | 19.0.1.0.0 | <a href='https://github.com/moylop260'><img src='https://github.com/moylop260.png' width='32' height='32' style='border-radius:50%;' alt='moylop260'/></a> <a href='https://github.com/ebirbe'><img src='https://github.com/ebirbe.png' width='32' height='32' style='border-radius:50%;' alt='ebirbe'/></a> <a href='https://github.com/luisg123v'><img src='https://github.com/luisg123v.png' width='32' height='32' style='border-radius:50%;' alt='luisg123v'/></a> | Disable indexing of attachments
[attachment_unindex_content](attachment_unindex_content/) | 19.0.1.0.1 | <a href='https://github.com/moylop260'><img src='https://github.com/moylop260.png' width='32' height='32' style='border-radius:50%;' alt='moylop260'/></a> <a href='https://github.com/ebirbe'><img src='https://github.com/ebirbe.png' width='32' height='32' style='border-radius:50%;' alt='ebirbe'/></a> <a href='https://github.com/luisg123v'><img src='https://github.com/luisg123v.png' width='32' height='32' style='border-radius:50%;' alt='luisg123v'/></a> | Disable indexing of attachments
[auditlog](auditlog/) | 19.0.2.0.1 | | Audit Log
[auto_backup](auto_backup/) | 19.0.1.0.1 | | Backups database
[base_cron_exclusion](base_cron_exclusion/) | 19.0.1.0.0 | <a href='https://github.com/LoisRForgeFlow'><img src='https://github.com/LoisRForgeFlow.png' width='32' height='32' style='border-radius:50%;' alt='LoisRForgeFlow'/></a> | Allow you to select scheduled actions that should not run simultaneously.
Expand All @@ -32,7 +32,7 @@ addon | version | maintainers | summary
[base_search_fuzzy](base_search_fuzzy/) | 19.0.1.0.0 | | Fuzzy search with the PostgreSQL trigram extension
[base_technical_user](base_technical_user/) | 19.0.1.0.0 | | Add a technical user parameter on the company
[base_time_window](base_time_window/) | 19.0.1.0.0 | | Base model to handle time windows
[base_view_inheritance_extension](base_view_inheritance_extension/) | 19.0.1.0.0 | <a href='https://github.com/hbrunn'><img src='https://github.com/hbrunn.png' width='32' height='32' style='border-radius:50%;' alt='hbrunn'/></a> | Adds more operators for view inheritance
[base_view_inheritance_extension](base_view_inheritance_extension/) | 19.0.1.0.1 | <a href='https://github.com/hbrunn'><img src='https://github.com/hbrunn.png' width='32' height='32' style='border-radius:50%;' alt='hbrunn'/></a> | Adds more operators for view inheritance
[base_write_diff](base_write_diff/) | 19.0.1.0.0 | | Prevents updates on fields whose values won't change anyway
[bus_alt_connection](bus_alt_connection/) | 19.0.1.0.0 | | Needed when using PgBouncer as a connection pooler
[database_cleanup](database_cleanup/) | 19.0.1.0.6 | | Database cleanup
Expand All @@ -46,7 +46,7 @@ addon | version | maintainers | summary
[scheduler_error_mailer](scheduler_error_mailer/) | 19.0.1.0.0 | | Scheduler Error Mailer
[sentry](sentry/) | 19.0.1.0.1 | <a href='https://github.com/barsi'><img src='https://github.com/barsi.png' width='32' height='32' style='border-radius:50%;' alt='barsi'/></a> <a href='https://github.com/naglis'><img src='https://github.com/naglis.png' width='32' height='32' style='border-radius:50%;' alt='naglis'/></a> <a href='https://github.com/versada'><img src='https://github.com/versada.png' width='32' height='32' style='border-radius:50%;' alt='versada'/></a> <a href='https://github.com/moylop260'><img src='https://github.com/moylop260.png' width='32' height='32' style='border-radius:50%;' alt='moylop260'/></a> <a href='https://github.com/fernandahf'><img src='https://github.com/fernandahf.png' width='32' height='32' style='border-radius:50%;' alt='fernandahf'/></a> | Report Odoo errors to Sentry
[sequence_python](sequence_python/) | 19.0.1.0.0 | | Calculate a sequence number from a Python expression
[session_db](session_db/) | 19.0.1.0.0 | <a href='https://github.com/sbidoul'><img src='https://github.com/sbidoul.png' width='32' height='32' style='border-radius:50%;' alt='sbidoul'/></a> | Store sessions in DB
[session_db](session_db/) | 19.0.1.0.1 | <a href='https://github.com/sbidoul'><img src='https://github.com/sbidoul.png' width='32' height='32' style='border-radius:50%;' alt='sbidoul'/></a> | Store sessions in DB
[test_auditlog](test_auditlog/) | 19.0.2.0.0 | | Additional unit tests for Audit Log based on accounting models
[tracking_manager](tracking_manager/) | 19.0.1.0.1 | <a href='https://github.com/Kev-Roche'><img src='https://github.com/Kev-Roche.png' width='32' height='32' style='border-radius:50%;' alt='Kev-Roche'/></a> <a href='https://github.com/sebastienbeau'><img src='https://github.com/sebastienbeau.png' width='32' height='32' style='border-radius:50%;' alt='sebastienbeau'/></a> | This module tracks all fields of a model, including one2many and many2many ones.
[tracking_manager_domain](tracking_manager_domain/) | 19.0.1.0.0 | <a href='https://github.com/CRogos'><img src='https://github.com/CRogos.png' width='32' height='32' style='border-radius:50%;' alt='CRogos'/></a> | This module extends the tracking manager to allow to define a domain on fields to track changes only when certain conditions apply.
Expand Down
11 changes: 10 additions & 1 deletion attachment_unindex_content/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Attachment Unindex Content
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f84f73f35e674b364f6912293285a59b1a761c2cf472c767a474af77c1fe72db
!! source digest: sha256:e1db1411f492f69fbf8123a433f2487ed5b67aab4be06ca0dccea5d48e37e54d
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down Expand Up @@ -65,6 +65,15 @@ it at ``ir.attachment`` base.
Also, after the installation, the ``index_content`` field on attachments
already recorded in database will be cleared.

Nothing is stored, but the field is still readable: when the database
has no content for an attachment, reading ``index_content`` indexes the
file at that moment and puts the result in the cache only. Code that
reads the field, as the website does to find a color in the CSS bundle,
keeps working with no copy of the content in the database. The cost is
reading the file of every attachment whose ``index_content`` is
requested. Searching on the field still finds nothing, because the
column stays empty.

.. |SQL Query result showing indexed content| image:: https://user-images.githubusercontent.com/442938/67894113-45d27a80-fb2e-11e9-9a22-ba43d8b444c5.png
:target: https://user-images.githubusercontent.com/442938/67894113-45d27a80-fb2e-11e9-9a22-ba43d8b444c5.png

Expand Down
2 changes: 1 addition & 1 deletion attachment_unindex_content/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"name": "Attachment Unindex Content",
"summary": "Disable indexing of attachments",
"version": "19.0.1.0.0",
"version": "19.0.1.0.1",
"author": "Vauxoo, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/server-tools",
"maintainers": [
Expand Down
28 changes: 28 additions & 0 deletions attachment_unindex_content/models/ir_attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,31 @@ class IrAttachment(models.Model):
@api.model
def _index(self, *args, **kwargs):
return False

def _fetch_query(self, query, fields):
"""Give ``index_content`` the content of the file when the database has none.

The content is not stored, so the column is empty, but whoever reads the field
still needs its value: core reads it to look a color up in the CSS bundle of the
website. Read it from the file, as the indexation would have stored it, and only
put it in the cache: nothing is written to the database.
"""
fetched = super()._fetch_query(query, fields)
field = self._fields["index_content"]
if fetched and field in fields:
cache = field._get_cache(self.env)
for attachment in fetched:
if cache.get(attachment.id):
continue
content = self._index_content_from_file(attachment)
if content:
field._update_cache(attachment, content)
return fetched

def _index_content_from_file(self, attachment):
"""Return what the indexation would have stored for ``attachment``."""
raw = attachment.raw
if not raw:
return False
# Skip this class: it is the one that disables the indexation
return super()._index(raw, attachment.mimetype, checksum=attachment.checksum)
8 changes: 8 additions & 0 deletions attachment_unindex_content/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@ it at `ir.attachment` base.

Also, after the installation, the `index_content` field on attachments
already recorded in database will be cleared.

Nothing is stored, but the field is still readable: when the database has
no content for an attachment, reading `index_content` indexes the file at
that moment and puts the result in the cache only. Code that reads the
field, as the website does to find a color in the CSS bundle, keeps working
with no copy of the content in the database. The cost is reading the file
of every attachment whose `index_content` is requested. Searching on the
field still finds nothing, because the column stays empty.
12 changes: 10 additions & 2 deletions attachment_unindex_content/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>Attachment Unindex Content</title>
<style type="text/css">

/*
Expand Down Expand Up @@ -372,7 +372,7 @@ <h1>Attachment Unindex Content</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f84f73f35e674b364f6912293285a59b1a761c2cf472c767a474af77c1fe72db
!! source digest: sha256:e1db1411f492f69fbf8123a433f2487ed5b67aab4be06ca0dccea5d48e37e54d
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/server-tools/tree/19.0/attachment_unindex_content"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-tools-19-0/server-tools-19-0-attachment_unindex_content"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/server-tools&amp;target_branch=19.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module disables the indexation of attachments content.</p>
Expand Down Expand Up @@ -402,6 +402,14 @@ <h1>Attachment Unindex Content</h1>
it at <tt class="docutils literal">ir.attachment</tt> base.</p>
<p>Also, after the installation, the <tt class="docutils literal">index_content</tt> field on attachments
already recorded in database will be cleared.</p>
<p>Nothing is stored, but the field is still readable: when the database
has no content for an attachment, reading <tt class="docutils literal">index_content</tt> indexes the
file at that moment and puts the result in the cache only. Code that
reads the field, as the website does to find a color in the CSS bundle,
keeps working with no copy of the content in the database. The cost is
reading the file of every attachment whose <tt class="docutils literal">index_content</tt> is
requested. Searching on the field still finds nothing, because the
column stays empty.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
Expand Down
77 changes: 73 additions & 4 deletions attachment_unindex_content/tests/test_attachment_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ def setUpClass(cls):
cls.test_text_content = b"This is a test file content for indexing verification"
cls.test_text_b64 = base64.b64encode(cls.test_text_content)

def _stored_index_content(self, attachment):
"""Return the ``index_content`` stored, not the one the field reads."""
attachment.flush_recordset()
self.env.cr.execute(
"SELECT index_content FROM ir_attachment WHERE id = %s", (attachment.id,)
)
return self.env.cr.fetchone()[0]

def test_attachment_index_content_disabled(self):
"""Test that index_content is not populated when creating attachment.

Expand All @@ -39,7 +47,7 @@ def test_attachment_index_content_disabled(self):
)

self.assertFalse(
attachment.index_content,
self._stored_index_content(attachment),
"index_content should be False (empty) when creating attachment "
"because the module disables content indexation",
)
Expand Down Expand Up @@ -118,7 +126,7 @@ def test_multiple_attachments_no_indexing(self):
# Verify that none of the attachments have index_content populated
for attachment in attachments:
self.assertFalse(
attachment.index_content,
self._stored_index_content(attachment),
f"Attachment {attachment.name} should not have indexed content",
)

Expand Down Expand Up @@ -151,7 +159,7 @@ def test_different_file_types_no_indexing(self):
)

self.assertFalse(
attachment.index_content,
self._stored_index_content(attachment),
f"Attachment {name} with mimetype {mimetype} should not be indexed",
)

Expand All @@ -174,4 +182,65 @@ def test_attachment_search_without_index(self):
"Should find attachment by name even without content indexing",
)
self.assertEqual(found.id, attachment.id)
self.assertFalse(found.index_content, "Found attachment should not be indexed")
self.assertFalse(
self._stored_index_content(found), "Found attachment should not be indexed"
)

def test_index_content_is_read_from_the_file(self):
"""The field reads the content of the file, which is not stored."""
attachment = self.Attachment.create(
{
"name": "readable.txt",
"datas": self.test_text_b64,
"mimetype": "text/plain",
}
)
attachment.invalidate_recordset()
self.assertEqual(
attachment.index_content, self.test_text_content.decode(), "Read the file"
)
self.assertFalse(
self._stored_index_content(attachment), "Nothing is stored in the database"
)

def test_index_content_is_read_from_the_file_for_several_records(self):
attachments = self.Attachment.create(
[
{
"name": f"readable_{i}.txt",
"raw": f"content number {i}".encode(),
"mimetype": "text/plain",
}
for i in range(3)
]
)
attachments.invalidate_recordset()
self.assertEqual(
attachments.mapped("index_content"),
[f"content number {i}" for i in range(3)],
)
self.assertEqual(
[row["index_content"] for row in attachments.read(["index_content"])],
[f"content number {i}" for i in range(3)],
)

def test_index_content_of_an_attachment_without_file_is_empty(self):
attachment = self.Attachment.create(
{
"name": "link",
"type": "url",
"url": "https://example.com",
"mimetype": "text/plain",
}
)
attachment.invalidate_recordset()
self.assertFalse(attachment.index_content)

def test_index_content_written_by_hand_is_kept(self):
attachment = self.Attachment.create(
{"name": "ocr.txt", "raw": b"from the file", "mimetype": "text/plain"}
)
attachment.index_content = "from the ocr"
attachment.flush_recordset()
attachment.invalidate_recordset()
self.assertEqual(attachment.index_content, "from the ocr")
11 changes: 6 additions & 5 deletions base_kanban_stage/i18n/sl.po
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-12-01 02:10+0000\n"
"PO-Revision-Date: 2017-12-01 02:10+0000\n"
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2017\n"
"PO-Revision-Date: 2026-10-24 14:46+0000\n"
"Last-Translator: Matjaz Mozetic <matjaz@luxim.si>\n"
"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
"%100==4 ? 2 : 3);\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
"n%100==4 ? 2 : 3;\n"
"X-Generator: Weblate 5.15.2\n"

#. module: base_kanban_stage
#: model:ir.model.fields,help:base_kanban_stage.field_base_kanban_abstract__kanban_status
Expand Down Expand Up @@ -85,7 +86,7 @@ msgstr ""
#. module: base_kanban_stage
#: model:ir.model.fields,field_description:base_kanban_stage.field_base_kanban_stage__display_name
msgid "Display Name"
msgstr "Prikazni naziv"
msgstr "Prikazani naziv"

#. module: base_kanban_stage
#: model:ir.model.fields,help:base_kanban_stage.field_base_kanban_stage__name
Expand Down
2 changes: 1 addition & 1 deletion base_view_inheritance_extension/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Extended view inheritance
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:9089555b5aea01b23ff4a0350d6fd69589d63f1beb4e272ed5a96eebf05b2a81
!! source digest: sha256:9ed71530bde28eea51dc4bcbb711aed870efc9b5c3ef861adca68e3f129b3a62
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
Expand Down
2 changes: 1 addition & 1 deletion base_view_inheritance_extension/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
{
"name": "Extended view inheritance",
"version": "19.0.1.0.0",
"version": "19.0.1.0.1",
"development_status": "Mature",
"author": "Therp BV,Odoo Community Association (OCA)",
"license": "LGPL-3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ msgstr ""
msgid "Display Name"
msgstr ""

#. module: base_view_inheritance_extension
#. odoo-python
#: code:addons/base_view_inheritance_extension/models/ir_ui_view.py:0
msgid "Element '%s' cannot be located in parent view"
msgstr ""

#. module: base_view_inheritance_extension
#: model:ir.model.fields,field_description:base_view_inheritance_extension.field_ir_ui_view__id
msgid "ID"
Expand Down
6 changes: 6 additions & 0 deletions base_view_inheritance_extension/i18n/ca.po
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ msgstr ""
msgid "Display Name"
msgstr ""

#. module: base_view_inheritance_extension
#. odoo-python
#: code:addons/base_view_inheritance_extension/models/ir_ui_view.py:0
msgid "Element '%s' cannot be located in parent view"
msgstr ""

#. module: base_view_inheritance_extension
#: model:ir.model.fields,field_description:base_view_inheritance_extension.field_ir_ui_view__id
msgid "ID"
Expand Down
6 changes: 6 additions & 0 deletions base_view_inheritance_extension/i18n/de.po
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ msgstr ""
msgid "Display Name"
msgstr ""

#. module: base_view_inheritance_extension
#. odoo-python
#: code:addons/base_view_inheritance_extension/models/ir_ui_view.py:0
msgid "Element '%s' cannot be located in parent view"
msgstr ""

#. module: base_view_inheritance_extension
#: model:ir.model.fields,field_description:base_view_inheritance_extension.field_ir_ui_view__id
msgid "ID"
Expand Down
6 changes: 6 additions & 0 deletions base_view_inheritance_extension/i18n/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ msgstr ""
msgid "Display Name"
msgstr ""

#. module: base_view_inheritance_extension
#. odoo-python
#: code:addons/base_view_inheritance_extension/models/ir_ui_view.py:0
msgid "Element '%s' cannot be located in parent view"
msgstr ""

#. module: base_view_inheritance_extension
#: model:ir.model.fields,field_description:base_view_inheritance_extension.field_ir_ui_view__id
msgid "ID"
Expand Down
Loading
Loading