diff --git a/.ruff.toml b/.ruff.toml index 0240c75..0f1e35f 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -15,16 +15,16 @@ exclude = ["setup/*"] [format] exclude = ["setup/*"] -[per-file-ignores] +[lint.per-file-ignores] "__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py "__manifest__.py" = ["B018"] # useless expression -[isort] +[lint.isort] section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"] -[isort.sections] +[lint.isort.sections] "odoo" = ["odoo"] "odoo-addons" = ["odoo.addons"] -[mccabe] +[lint.mccabe] max-complexity = 16 diff --git a/automation_oca/models/automation_configuration.py b/automation_oca/models/automation_configuration.py index c6a405c..aae5f79 100644 --- a/automation_oca/models/automation_configuration.py +++ b/automation_oca/models/automation_configuration.py @@ -18,9 +18,16 @@ class AutomationConfiguration(models.Model): tag_ids = fields.Many2many("automation.tag") company_id = fields.Many2one("res.company") domain = fields.Char( - required=True, default="[]", help="Filter to apply", compute="_compute_domain" + required=True, + default="[]", + help="Filter to apply", + compute="_compute_domain", + ) + editable_domain = fields.Char( + required=True, + default="[]", + help="Filter to apply", ) - editable_domain = fields.Char(required=True, default="[]", help="Filter to apply") model_id = fields.Many2one( "ir.model", domain=[("is_mail_thread", "=", True)], @@ -185,7 +192,8 @@ def cron_automation(self): def _get_automation_records_to_create(self): """ - We will find all the records that fulfill the domain but don't have a record created. + We will find all the records that fulfill + the domain but don't have a record created. Also, we need to check by autencity field if defined. In order to do this, we will add some extra joins on the query of the domain @@ -230,10 +238,10 @@ def _get_automation_records_to_create(self): ", ".join([f'MIN("{next(iter(query._tables))}".id) as id']), from_clause, where_clause or "TRUE", - (" ORDER BY %s" % self.order) if query.order else "", - (" LIMIT %d" % self.limit) if query.limit else "", - (" OFFSET %d" % self.offset) if query.offset else "", - "%s.%s" % (Record._table, self.field_id.name), + (f" ORDER BY {self.order}") if query.order else "", + (f" LIMIT {self.limit}") if query.limit else "", + (f" OFFSET {self.offset}") if query.offset else "", + f"{Record._table}.{self.field_id.name}", ) else: query_str, params = query.select() diff --git a/automation_oca/models/automation_configuration_step.py b/automation_oca/models/automation_configuration_step.py index e9701b2..921cd4b 100644 --- a/automation_oca/models/automation_configuration_step.py +++ b/automation_oca/models/automation_configuration_step.py @@ -284,7 +284,8 @@ def _trigger_type_selection(self): @api.model def _trigger_types(self): """ - This function will return a dictionary that map trigger_types to its configurations. + This function will return a dictionary that map + trigger_types to its configurations. Each trigger_type can contain: - name (Required field) - step type: List of step types that succeed after this. diff --git a/automation_oca/models/automation_record.py b/automation_oca/models/automation_record.py index 3f29cb1..0534703 100644 --- a/automation_oca/models/automation_record.py +++ b/automation_oca/models/automation_record.py @@ -61,7 +61,7 @@ def _compute_state(self): def _compute_resource_ref(self): for record in self: if record.model and record.model in self.env: - record.resource_ref = "%s,%s" % (record.model, record.res_id or 0) + record.resource_ref = f"{record.model},{record.res_id or 0}" else: record.resource_ref = None diff --git a/automation_oca/models/automation_record_step.py b/automation_oca/models/automation_record_step.py index 752a8e1..308e629 100644 --- a/automation_oca/models/automation_record_step.py +++ b/automation_oca/models/automation_record_step.py @@ -222,8 +222,7 @@ def _get_mail_tracking_token(self): def _get_mail_tracking_url(self): return werkzeug.urls.url_join( self.get_base_url(), - "automation_oca/track/%s/%s/blank.gif" - % (self.id, self._get_mail_tracking_token()), + f"automation_oca/track/{self.id}/{self._get_mail_tracking_token()}/blank.gif", ) def _run_mail_context(self): diff --git a/automation_oca/models/mail_mail.py b/automation_oca/models/mail_mail.py index c1bd564..7e499d2 100644 --- a/automation_oca/models/mail_mail.py +++ b/automation_oca/models/mail_mail.py @@ -36,8 +36,7 @@ def _prepare_outgoing_body(self): if parsed.scheme.startswith("http") and parsed.path.startswith("/r/"): new_href = href.replace( url, - "%s/au/%s/%s" - % (url, str(self.automation_record_step_id.id), token), + f"{url}/au/{str(self.automation_record_step_id.id)}/{token}", ) body = body.replace( markupsafe.Markup(href), markupsafe.Markup(new_href) diff --git a/automation_oca/models/mail_thread.py b/automation_oca/models/mail_thread.py index b8cf835..8dc1142 100644 --- a/automation_oca/models/mail_thread.py +++ b/automation_oca/models/mail_thread.py @@ -10,9 +10,7 @@ class MailThread(models.AbstractModel): @api.model def _routing_handle_bounce(self, email_message, message_dict): """We want to mark the bounced email""" - result = super(MailThread, self)._routing_handle_bounce( - email_message, message_dict - ) + result = super()._routing_handle_bounce(email_message, message_dict) bounced_msg_ids = message_dict.get("bounced_msg_ids") if bounced_msg_ids: self.env["automation.record.step"].search( @@ -36,9 +34,7 @@ def _message_route_process(self, message, message_dict, routes): ) records._set_mail_open() records._set_mail_reply() - return super(MailThread, self)._message_route_process( - message, message_dict, routes - ) + return super()._message_route_process(message, message_dict, routes) @api.model def get_automation_access(self, doc_ids, operation, model_name=False): diff --git a/automation_oca/tests/common.py b/automation_oca/tests/common.py index de909ea..b89d4ef 100644 --- a/automation_oca/tests/common.py +++ b/automation_oca/tests/common.py @@ -32,7 +32,8 @@ def setUpClass(cls): "model_id": cls.env.ref("base.model_res_partner").id, "subject": "Subject", "partner_to": "{{ object.id }}", - "body_html": 'My template with link', + "body_html": 'My template \ + with link', } ) cls.partner_01 = cls.env["res.partner"].create( diff --git a/automation_oca/tests/test_automation_action.py b/automation_oca/tests/test_automation_action.py index 477add5..265adeb 100644 --- a/automation_oca/tests/test_automation_action.py +++ b/automation_oca/tests/test_automation_action.py @@ -40,9 +40,8 @@ def test_child_execution_filters(self): In this case, the task 1_1_1 will only be generated for partner 1 and task 1_2_1 for partner 2 """ - self.configuration.editable_domain = "[('id', 'in', [%s, %s])]" % ( - self.partner_01.id, - self.partner_02.id, + self.configuration.editable_domain = ( + f"[('id', 'in', [{self.partner_01.id}, {self.partner_02.id}])]" ) activity_1 = self.create_server_action() diff --git a/automation_oca/tests/test_automation_base.py b/automation_oca/tests/test_automation_base.py index 4888711..f6f21ff 100644 --- a/automation_oca/tests/test_automation_base.py +++ b/automation_oca/tests/test_automation_base.py @@ -497,7 +497,7 @@ def test_is_test_behavior(self): ) ) as f: self.assertTrue(f.resource_ref) - f.resource_ref = "%s,%s" % (self.partner_01._name, self.partner_01.id) + f.resource_ref = f"{self.partner_01._name},{self.partner_01.id}" wizard = f.save() wizard_action = wizard.test_record() record = self.env[wizard_action["res_model"]].browse(wizard_action["res_id"]) diff --git a/automation_oca/tests/test_automation_mail.py b/automation_oca/tests/test_automation_mail.py index 3b4f8ae..5df1bdd 100644 --- a/automation_oca/tests/test_automation_mail.py +++ b/automation_oca/tests/test_automation_mail.py @@ -40,7 +40,8 @@ =20 =20 - =20 + =20

I would gladly answer to your mass mailing !

@@ -284,7 +285,8 @@ def test_open_wrong_code(self): def test_no_open(self): """ - Now we will check the not open validation when it is not opened (should be executed) + Now we will check the not open validation when it is not opened + (should be executed) """ activity = self.create_mail_activity() child_activity = self.create_mail_activity( @@ -384,12 +386,7 @@ def test_click(self): ) self.assertTrue(tracker) self.url_open( - "/r/%s/au/%s/%s" - % ( - tracker.code, - record_activity.id, - record_activity._get_mail_tracking_token(), - ) + f"/r/{tracker.code}/au/{record_activity.id}/{record_activity._get_mail_tracking_token()}" ) self.assertEqual("open", record_activity.mail_status) self.assertEqual( @@ -414,12 +411,7 @@ def test_click(self): self.assertEqual(1, self.configuration.click_count) # Now we will check that a second click does not generate a second log self.url_open( - "/r/%s/au/%s/%s" - % ( - tracker.code, - record_activity.id, - record_activity._get_mail_tracking_token(), - ) + f"/r/{tracker.code}/au/{record_activity.id}/{record_activity._get_mail_tracking_token()}" ) self.assertEqual( 1, @@ -461,24 +453,13 @@ def test_click_wrong_url(self): [("url", "=", "https://www.twitter.com")] ) self.assertTrue(tracker) - self.url_open( - "/r/%s/au/%s/1234" - % ( - tracker.code, - record_activity.id, - ) - ) + self.url_open(f"/r/{tracker.code}/au/{record_activity.id}/1234") self.assertEqual("sent", record_activity.mail_status) self.assertFalse(record_child_activity.scheduled_date) # Now we check the case where the code is not found tracker.unlink() self.url_open( - "/r/%s/au/%s/%s" - % ( - tracker.code, - record_activity.id, - record_activity._get_mail_tracking_token(), - ) + f"/r/{tracker.code}/au/{record_activity.id}/{record_activity._get_mail_tracking_token()}" ) self.assertEqual("sent", record_activity.mail_status) self.assertFalse(record_child_activity.scheduled_date) @@ -491,7 +472,7 @@ def test_no_click(self): child_activity = self.create_mail_activity( parent_id=activity.id, trigger_type="mail_not_clicked" ) - self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id + self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]" self.configuration.start_automation() self.env["automation.configuration"].cron_automation() with self.mock_mail_gateway(): @@ -520,7 +501,7 @@ def test_no_click_rejected(self): child_activity = self.create_mail_activity( parent_id=activity.id, trigger_type="mail_not_clicked" ) - self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id + self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]" self.configuration.start_automation() self.env["automation.configuration"].cron_automation() with self.mock_mail_gateway(): @@ -542,12 +523,7 @@ def test_no_click_rejected(self): [("url", "=", "https://www.twitter.com")] ) self.url_open( - "/r/%s/au/%s/%s" - % ( - tracker.code, - record_activity.id, - record_activity._get_mail_tracking_token(), - ) + f"/r/{tracker.code}/au/{record_activity.id}/{record_activity._get_mail_tracking_token()}" ) self.env["automation.record.step"]._cron_automation_steps() self.assertEqual("rejected", record_child_activity.state) @@ -557,7 +533,7 @@ def test_is_test_behavior(self): We want to ensure that no mails are sent on tests """ self.create_mail_activity() - self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id + self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]" with Form( self.env["automation.configuration.test"].with_context( default_configuration_id=self.configuration.id, @@ -565,7 +541,7 @@ def test_is_test_behavior(self): ) ) as f: self.assertTrue(f.resource_ref) - f.resource_ref = "%s,%s" % (self.partner_01._name, self.partner_01.id) + f.resource_ref = f"{self.partner_01._name},{self.partner_01.id}" wizard = f.save() wizard_action = wizard.test_record() record = self.env[wizard_action["res_model"]].browse(wizard_action["res_id"]) diff --git a/automation_oca/wizards/automation_configuration_test.py b/automation_oca/wizards/automation_configuration_test.py index ea3d682..4461055 100644 --- a/automation_oca/wizards/automation_configuration_test.py +++ b/automation_oca/wizards/automation_configuration_test.py @@ -32,7 +32,7 @@ def _compute_resource_ref(self): for record in self: if record.model and record.model in self.env: res = self.env[record.model].search([], limit=1) - record.resource_ref = "%s,%s" % (record.model, res.id) + record.resource_ref = f"{record.model},{res.id}" else: record.resource_ref = None