From c4a2b6718db137753c47329838e9333b48d0539d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 20 Nov 2020 15:39:01 +0100 Subject: [PATCH 1/4] [IMP] : black, isort, prettier --- .pre-commit-config.yaml | 2 - queue_job/__manifest__.py | 6 +- queue_job/job.py | 2 +- queue_job/models/base.py | 2 +- queue_job/models/queue_job.py | 9 +- queue_job/static/description/icon.svg | 238 +++++++++--------- queue_job_cron/__manifest__.py | 2 +- queue_job_subscribe/__manifest__.py | 2 +- requirements.txt | 2 + setup/queue_job/odoo/addons/queue_job | 1 + setup/queue_job/setup.py | 6 + .../test_queue_job/odoo/addons/test_queue_job | 1 + setup/test_queue_job/setup.py | 6 + test_queue_job/__manifest__.py | 4 +- test_queue_job/models/test_models.py | 4 +- test_queue_job/tests/test_job.py | 6 +- 16 files changed, 162 insertions(+), 131 deletions(-) create mode 100644 requirements.txt create mode 120000 setup/queue_job/odoo/addons/queue_job create mode 100644 setup/queue_job/setup.py create mode 120000 setup/test_queue_job/odoo/addons/test_queue_job create mode 100644 setup/test_queue_job/setup.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 39468209d6..3b2487c16b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,11 +3,9 @@ exclude: | # NOT INSTALLABLE ADDONS ^base_export_async/| ^base_import_async/| - ^queue_job/| ^queue_job_cron/| ^queue_job_subscribe/| ^test_base_import_async/| - ^test_queue_job/| # END NOT INSTALLABLE ADDONS # Files and folders generated by bots, to avoid loops ^setup/|/static/description/index\.html$| diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 0b1d16e56e..74e70419f7 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -3,9 +3,9 @@ { "name": "Job Queue", - "version": "13.0.3.2.0", + "version": "14.0.1.0.0", "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", - "website": "https://github.com/OCA/queue/queue_job", + "website": "https://github.com/OCA/queue", "license": "LGPL-3", "category": "Generic Modules", "depends": ["mail"], @@ -17,7 +17,7 @@ "data/queue_data.xml", "data/queue_job_function_data.xml", ], - "installable": False, + "installable": True, "development_status": "Mature", "maintainers": ["guewen"], "post_init_hook": "post_init_hook", diff --git a/queue_job/job.py b/queue_job/job.py index 568808c002..36c2645520 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -392,7 +392,7 @@ def __init__( channel=None, identity_key=None, ): - """ Create a Job + """Create a Job :param func: function to execute :type func: function diff --git a/queue_job/models/base.py b/queue_job/models/base.py index 3bb4d78361..961f266cf5 100644 --- a/queue_job/models/base.py +++ b/queue_job/models/base.py @@ -44,7 +44,7 @@ def with_delay( channel=None, identity_key=None, ): - """ Return a ``DelayableRecordset`` + """Return a ``DelayableRecordset`` The returned instance allows to enqueue any method of the recordset's Model. diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index 1da0eaf86d..a758f58df0 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -69,7 +69,9 @@ class QueueJob(models.Model): # actions), can be removed (replaced by "records") in 14.0 record_ids = JobSerialized(compute="_compute_record_ids", base_type=list) records = JobSerialized( - string="Record(s)", readonly=True, base_type=models.BaseModel, + string="Record(s)", + readonly=True, + base_type=models.BaseModel, ) args = JobSerialized(readonly=True, base_type=tuple) kwargs = JobSerialized(readonly=True, base_type=dict) @@ -522,7 +524,10 @@ def _default_channel(self): return self.env.ref("queue_job.channel_root") name = fields.Char( - compute="_compute_name", inverse="_inverse_name", index=True, store=True, + compute="_compute_name", + inverse="_inverse_name", + index=True, + store=True, ) # model and method should be required, but the required flag doesn't diff --git a/queue_job/static/description/icon.svg b/queue_job/static/description/icon.svg index a5fbb71bb6..fd5da3366b 100644 --- a/queue_job/static/description/icon.svg +++ b/queue_job/static/description/icon.svg @@ -1,138 +1,150 @@ - + - - + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg2" + version="1.1" + inkscape:version="0.92.4 (f8dce91, 2019-08-02)" + width="60" + height="60" + viewBox="0 0 60 60" + sodipodi:docname="icon.svg" + inkscape:export-filename="./icon.png" + inkscape:export-xdpi="192" + inkscape:export-ydpi="192" +> + - + image/svg+xml - + - + + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1052" + id="namedview4" + showgrid="false" + inkscape:zoom="8" + inkscape:cx="20.921984" + inkscape:cy="9.7064211" + inkscape:window-x="1920" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" + showguides="true" + inkscape:guide-bbox="true" + > + position="4.140625,50.300781" + orientation="-0.70710678,0.70710678" + id="guide3348" + inkscape:locked="false" + /> + position="56.476562,43.945312" + orientation="-0.70710678,0.70710678" + id="guide3350" + inkscape:locked="false" + /> + position="0,41.75" + orientation="1,0" + id="guide3360" + inkscape:locked="false" + /> + position="60,60.074219" + orientation="1,0" + id="guide3362" + inkscape:locked="false" + /> + position="0.17578125,60" + orientation="0,1" + id="guide3364" + inkscape:locked="false" + /> + position="58.71196,-0.0055242717" + orientation="0,1" + id="guide3366" + inkscape:locked="false" + /> + position="15.558594,50.5" + orientation="-0.70710678,0.70710678" + id="guide3345" + inkscape:locked="false" + /> + position="56.101563,32.363281" + orientation="-0.70710678,0.70710678" + id="guide3347" + inkscape:locked="false" + /> + position="55.972656,21.027344" + orientation="-0.70710678,0.70710678" + id="guide3349" + inkscape:locked="false" + /> + position="55.863281,9.6914063" + orientation="-0.70710678,0.70710678" + id="guide3351" + inkscape:locked="false" + /> + style="opacity:1;fill:#e74c3c;fill-opacity:1" + id="rect4147" + width="60" + height="60" + x="0" + y="0" + ry="3.5" + /> + style="opacity:1;fill:#000000;fill-opacity:0.39215686" + d="M 4.1318557,9.7144566 0.0078125,13.824141 4.2297534e-4,57.5 c 0,0 0.66042738466,1.160638 1.24957702466,1.75 0.6775221,0.677766 1.6249999,0.750548 1.6249999,0.750548 l 43.2963011,0.0083 9.791208,-9.800508 -4.088791,-7.131947 4.086426,-4.114418 -4.058547,-7.106958 4.016339,-4.017997 -4.036551,-7.171615 4.058726,-4.069362 -40.612885,-6.8632798 -4.011838,4.0145788 z" + id="rect4171" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccscccccccccccc" + /> + id="g4169" + transform="matrix(0.3061173,0,0,0.3061173,-1.0360053,-1.0457906)" + style="fill:#ffffff;stroke:none" + /> + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:FontAwesome;-inkscape-font-specification:FontAwesome;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="3.8388314" + y="50.558071" + id="text3352" + > diff --git a/queue_job_cron/__manifest__.py b/queue_job_cron/__manifest__.py index 4379e830f6..24f7e3233f 100644 --- a/queue_job_cron/__manifest__.py +++ b/queue_job_cron/__manifest__.py @@ -5,7 +5,7 @@ "name": "Scheduled Actions as Queue Jobs", "version": "13.0.2.1.0", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", - "website": "https://github.com/OCA/queue/tree/12.0/queue_job_cron", + "website": "https://github.com/OCA/queue", "license": "AGPL-3", "category": "Generic Modules", "depends": ["queue_job"], diff --git a/queue_job_subscribe/__manifest__.py b/queue_job_subscribe/__manifest__.py index 7223a50293..7b6453f193 100644 --- a/queue_job_subscribe/__manifest__.py +++ b/queue_job_subscribe/__manifest__.py @@ -4,7 +4,7 @@ "name": "Queue Job Subscribe", "version": "13.0.1.0.0", "author": "Acsone SA/NV, Odoo Community Association (OCA)", - "website": "https://github.com/OCA/queue_job", + "website": "https://github.com/OCA/queue", "summary": "Control which users are subscribed to queue job notifications", "license": "AGPL-3", "category": "Generic Modules", diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..b4d39fb9e0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# generated from manifests external_dependencies +requests diff --git a/setup/queue_job/odoo/addons/queue_job b/setup/queue_job/odoo/addons/queue_job new file mode 120000 index 0000000000..ac796aaa1c --- /dev/null +++ b/setup/queue_job/odoo/addons/queue_job @@ -0,0 +1 @@ +../../../../queue_job \ No newline at end of file diff --git a/setup/queue_job/setup.py b/setup/queue_job/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/queue_job/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/test_queue_job/odoo/addons/test_queue_job b/setup/test_queue_job/odoo/addons/test_queue_job new file mode 120000 index 0000000000..0473d5583c --- /dev/null +++ b/setup/test_queue_job/odoo/addons/test_queue_job @@ -0,0 +1 @@ +../../../../test_queue_job \ No newline at end of file diff --git a/setup/test_queue_job/setup.py b/setup/test_queue_job/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/test_queue_job/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/test_queue_job/__manifest__.py b/test_queue_job/__manifest__.py index a09c89b07f..6b4dfa89e5 100644 --- a/test_queue_job/__manifest__.py +++ b/test_queue_job/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Queue Job Tests", - "version": "13.0.2.1.0", + "version": "14.0.1.0.0", "author": "Camptocamp,Odoo Community Association (OCA)", "license": "LGPL-3", "category": "Generic Modules", @@ -14,5 +14,5 @@ "data/queue_job_function_data.xml", "security/ir.model.access.csv", ], - "installable": False, + "installable": True, } diff --git a/test_queue_job/models/test_models.py b/test_queue_job/models/test_models.py index 36fdb1c6f9..9d5e4fc457 100644 --- a/test_queue_job/models/test_models.py +++ b/test_queue_job/models/test_models.py @@ -34,7 +34,7 @@ class TestQueueJob(models.Model): name = fields.Char() def testing_method(self, *args, **kwargs): - """ Method used for tests + """Method used for tests Return always the arguments and keyword arguments received """ @@ -79,7 +79,7 @@ def job_sub_channel(self): # TODO deprecated by :job-no-decorator: @property def dummy_property(self): - """ Return foo + """Return foo Only there to check that properties are compatible with the automatic registration of job methods diff --git a/test_queue_job/tests/test_job.py b/test_queue_job/tests/test_job.py index f9b679cc27..83222f1af8 100644 --- a/test_queue_job/tests/test_job.py +++ b/test_queue_job/tests/test_job.py @@ -327,7 +327,7 @@ class TestJobs(JobCommonCase): """ Test jobs on other methods or with different job configuration """ def test_description(self): - """ If no description is given to the job, it + """If no description is given to the job, it should be computed from the function """ # if a docstring is defined for the function @@ -610,8 +610,8 @@ def test_job_default_company_id(self): ) def test_job_no_company_id(self): - """ if we put an empty company_id in the context - jobs are created without company_id + """if we put an empty company_id in the context + jobs are created without company_id """ env = self.env(context={"company_id": None}) stored = self._create_job(env) From 1dbfc1184fb25920c046eb6715b83e53623eef01 Mon Sep 17 00:00:00 2001 From: Eric Antones Date: Fri, 16 Oct 2020 18:53:22 +0200 Subject: [PATCH 2/4] [MIG] queue_job: Migration to 14.0 --- .../13.0.1.2.0/post-migrate-queue-job.py | 19 ------------------- queue_job/models/ir_model_fields.py | 5 ++++- queue_job/readme/CONTRIBUTORS.rst | 1 + queue_job/security/ir.model.access.csv | 2 ++ 4 files changed, 7 insertions(+), 20 deletions(-) delete mode 100644 queue_job/migrations/13.0.1.2.0/post-migrate-queue-job.py diff --git a/queue_job/migrations/13.0.1.2.0/post-migrate-queue-job.py b/queue_job/migrations/13.0.1.2.0/post-migrate-queue-job.py deleted file mode 100644 index 11ddf11737..0000000000 --- a/queue_job/migrations/13.0.1.2.0/post-migrate-queue-job.py +++ /dev/null @@ -1,19 +0,0 @@ -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) - -from odoo import SUPERUSER_ID, api - - -def migrate(cr, version): - with api.Environment.manage(): - env = api.Environment(cr, SUPERUSER_ID, {}) - rule = env.ref("queue_job.queue_job_comp_rule", raise_if_not_found=False) - if rule: - domain = """[ - '|', - ('company_id', '=', False), - ('company_id', 'in', company_ids) - ]""" - values = { - "domain_force": domain, - } - rule.write(values) diff --git a/queue_job/models/ir_model_fields.py b/queue_job/models/ir_model_fields.py index 30d48dc236..5a31fcdc5f 100644 --- a/queue_job/models/ir_model_fields.py +++ b/queue_job/models/ir_model_fields.py @@ -7,4 +7,7 @@ class IrModelFields(models.Model): _inherit = "ir.model.fields" - ttype = fields.Selection(selection_add=[("job_serialized", "Job Serialized")]) + ttype = fields.Selection( + selection_add=[("job_serialized", "Job Serialized")], + ondelete={"job_serialized": "cascade"}, + ) diff --git a/queue_job/readme/CONTRIBUTORS.rst b/queue_job/readme/CONTRIBUTORS.rst index 9694c9654a..0f8bb1a3b2 100644 --- a/queue_job/readme/CONTRIBUTORS.rst +++ b/queue_job/readme/CONTRIBUTORS.rst @@ -8,3 +8,4 @@ * Cédric Pigeon * Tatiana Deribina * Souheil Bejaoui +* Eric Antones diff --git a/queue_job/security/ir.model.access.csv b/queue_job/security/ir.model.access.csv index e90eee9ae4..9242305158 100644 --- a/queue_job/security/ir.model.access.csv +++ b/queue_job/security/ir.model.access.csv @@ -2,3 +2,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_queue_job_manager,queue job manager,queue_job.model_queue_job,queue_job.group_queue_job_manager,1,1,1,1 access_queue_job_function_manager,queue job functions manager,queue_job.model_queue_job_function,queue_job.group_queue_job_manager,1,1,1,1 access_queue_job_channel_manager,queue job channel manager,queue_job.model_queue_job_channel,queue_job.group_queue_job_manager,1,1,1,1 +access_queue_requeue_job,queue requeue job manager,queue_job.model_queue_requeue_job,queue_job.group_queue_job_manager,1,1,1,1 +access_queue_jobs_to_done,queue jobs to done manager,queue_job.model_queue_jobs_to_done,queue_job.group_queue_job_manager,1,1,1,1 From 19214c3148a3e82ff2db6b4445cfaf9101ac10c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 20 Nov 2020 15:58:04 +0100 Subject: [PATCH 3/4] [REF] remove deprecated feature --- queue_job/job.py | 252 ---------------------- queue_job/models/base.py | 15 -- queue_job/models/queue_job.py | 29 --- queue_job/readme/HISTORY.rst | 22 +- test_queue_job/models/test_models.py | 11 - test_queue_job/tests/common.py | 3 - test_queue_job/tests/test_job_channels.py | 13 +- 7 files changed, 2 insertions(+), 343 deletions(-) diff --git a/queue_job/job.py b/queue_job/job.py index 36c2645520..06eb6c0516 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -1,7 +1,6 @@ # Copyright 2013-2020 Camptocamp # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) -import functools import hashlib import inspect import logging @@ -684,9 +683,6 @@ def __repr__(self): def _get_retry_seconds(self, seconds=None): retry_pattern = self.job_config.retry_pattern - if not retry_pattern: - # TODO deprecated by :job-no-decorator: - retry_pattern = getattr(self.func, "retry_pattern", None) if not seconds and retry_pattern: # ordered from higher to lower count of retries patt = sorted(retry_pattern.items(), key=lambda t: t[0]) @@ -719,13 +715,6 @@ def related_action(self): return None funcname = self.job_config.related_action_func_name - if not funcname and hasattr(self.func, "related_action"): - # TODO deprecated by :job-no-decorator: - funcname = self.func.related_action - # decorator is set but empty: disable the default one - if not funcname: - return None - if not funcname: funcname = record._default_related_action if not isinstance(funcname, str): @@ -735,9 +724,6 @@ def related_action(self): ) action = getattr(record, funcname) action_kwargs = self.job_config.related_action_kwargs - if not action_kwargs: - # TODO deprecated by :job-no-decorator: - action_kwargs = getattr(self.func, "kwargs", {}) return action(**action_kwargs) @@ -745,241 +731,3 @@ def _is_model_method(func): return inspect.ismethod(func) and isinstance( func.__self__.__class__, odoo.models.MetaModel ) - - -# TODO deprecated by :job-no-decorator: -def job(func=None, default_channel="root", retry_pattern=None): - """Decorator for job methods. - - Deprecated. Use ``queue.job.function`` XML records (details in - ``readme/USAGE.rst``). - - It enables the possibility to use a Model's method as a job function. - - Optional argument: - - :param default_channel: the channel wherein the job will be assigned. This - channel is set at the installation of the module - and can be manually changed later using the views. - :param retry_pattern: The retry pattern to use for postponing a job. - If a job is postponed and there is no eta - specified, the eta will be determined from the - dict in retry_pattern. When no retry pattern - is provided, jobs will be retried after - :const:`RETRY_INTERVAL` seconds. - :type retry_pattern: dict(retry_count,retry_eta_seconds) - - Indicates that a method of a Model can be delayed in the Job Queue. - - When a method has the ``@job`` decorator, its calls can then be delayed - with:: - - recordset.with_delay(priority=10).the_method(args, **kwargs) - - Where ``the_method`` is the method decorated with ``@job``. Its arguments - and keyword arguments will be kept in the Job Queue for its asynchronous - execution. - - ``default_channel`` indicates in which channel the job must be executed - - ``retry_pattern`` is a dict where keys are the count of retries and the - values are the delay to postpone a job. - - Example: - - .. code-block:: python - - class ProductProduct(models.Model): - _inherit = 'product.product' - - @job - def export_one_thing(self, one_thing): - # work - # export one_thing - - # [...] - - env['a.model'].export_one_thing(the_thing_to_export) - # => normal and synchronous function call - - env['a.model'].with_delay().export_one_thing(the_thing_to_export) - # => the job will be executed as soon as possible - - delayable = env['a.model'].with_delay(priority=30, eta=60*60*5) - delayable.export_one_thing(the_thing_to_export) - # => the job will be executed with a low priority and not before a - # delay of 5 hours from now - - @job(default_channel='root.subchannel') - def export_one_thing(one_thing): - # work - # export one_thing - - @job(retry_pattern={1: 10 * 60, - 5: 20 * 60, - 10: 30 * 60, - 15: 12 * 60 * 60}) - def retryable_example(): - # 5 first retries postponed 10 minutes later - # retries 5 to 10 postponed 20 minutes later - # retries 10 to 15 postponed 30 minutes later - # all subsequent retries postponed 12 hours later - raise RetryableJobError('Must be retried later') - - env['a.model'].with_delay().retryable_example() - - - See also: :py:func:`related_action` a related action can be attached - to a job - """ - if func is None: - return functools.partial( - job, default_channel=default_channel, retry_pattern=retry_pattern - ) - - xml_fields = [ - ' \n' - ' _test_job\n' - ] - if default_channel: - xml_fields.append(' ') - if retry_pattern: - xml_fields.append(' {retry_pattern}') - - _logger.info( - "@job is deprecated and no longer needed (on %s), it is advised to use an " - "XML record (activate DEBUG log for snippet)", - func.__name__, - ) - if _logger.isEnabledFor(logging.DEBUG): - xml_record = ( - '\n' + "\n".join(xml_fields) + "\n" - ).format(**{"method": func.__name__, "retry_pattern": retry_pattern}) - _logger.debug( - "XML snippet (to complete) for replacing @job on %s:\n%s", - func.__name__, - xml_record, - ) - - def delay_from_model(*args, **kwargs): - raise AttributeError( - "method.delay() can no longer be used, the general form is " - "env['res.users'].with_delay().method()" - ) - - assert default_channel == "root" or default_channel.startswith( - "root." - ), "The channel path must start by 'root'" - assert retry_pattern is None or isinstance( - retry_pattern, dict - ), "retry_pattern must be a dict" - - delay_func = delay_from_model - - func.delayable = True - func.delay = delay_func - func.retry_pattern = retry_pattern - func.default_channel = default_channel - return func - - -# TODO deprecated by :job-no-decorator: -def related_action(action=None, **kwargs): - """Attach a *Related Action* to a job (decorator) - - Deprecated. Use ``queue.job.function`` XML records (details in - ``readme/USAGE.rst``). - - A *Related Action* will appear as a button on the Odoo view. - The button will execute the action, usually it will open the - form view of the record related to the job. - - The ``action`` must be a method on the `queue.job` model. - - Example usage: - - .. code-block:: python - - class QueueJob(models.Model): - _inherit = 'queue.job' - - def related_action_partner(self): - self.ensure_one() - model = self.model_name - partner = self.records - # possibly get the real ID if partner_id is a binding ID - action = { - 'name': _("Partner"), - 'type': 'ir.actions.act_window', - 'res_model': model, - 'view_type': 'form', - 'view_mode': 'form', - 'res_id': partner.id, - } - return action - - class ResPartner(models.Model): - _inherit = 'res.partner' - - @job - @related_action(action='related_action_partner') - def export_partner(self): - # ... - - The kwargs are transmitted to the action: - - .. code-block:: python - - class QueueJob(models.Model): - _inherit = 'queue.job' - - def related_action_product(self, extra_arg=1): - assert extra_arg == 2 - model = self.model_name - ... - - class ProductProduct(models.Model): - _inherit = 'product.product' - - @job - @related_action(action='related_action_product', extra_arg=2) - def export_product(self): - # ... - - """ - - def decorate(func): - related_action_dict = { - "func_name": action, - } - if kwargs: - related_action_dict["kwargs"] = kwargs - - xml_fields = ( - ' \n' - ' _test_job\n' - ' {related_action}' - ) - - _logger.info( - "@related_action is deprecated and no longer needed (on %s)," - " it is advised to use an XML record (activate DEBUG log for snippet)", - func.__name__, - ) - if _logger.isEnabledFor(logging.DEBUG): - xml_record = ( - '\n' + xml_fields + "\n" - ).format(**{"method": func.__name__, "related_action": action}) - _logger.debug( - "XML snippet (to complete) for replacing @related_action on %s:\n%s", - func.__name__, - xml_record, - ) - - func.related_action = action - func.kwargs = kwargs - return func - - return decorate diff --git a/queue_job/models/base.py b/queue_job/models/base.py index 961f266cf5..a05da489b3 100644 --- a/queue_job/models/base.py +++ b/queue_job/models/base.py @@ -1,7 +1,6 @@ # Copyright 2016 Camptocamp # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) -import inspect import logging import os @@ -21,20 +20,6 @@ class Base(models.AbstractModel): _inherit = "base" - # TODO deprecated by :job-no-decorator: - def _register_hook(self): - """Register marked jobs""" - super(Base, self)._register_hook() - job_methods = [ - method - for __, method in inspect.getmembers( - self.__class__, predicate=inspect.isfunction - ) - if getattr(method, "delayable", None) - ] - for job_method in job_methods: - self.env["queue.job.function"]._register_job(self, job_method) - def with_delay( self, priority=None, diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index a758f58df0..9d2f3caab4 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -613,28 +613,6 @@ def _inverse_edit_related_action(self): def job_function_name(model_name, method_name): return "<{}>.{}".format(model_name, method_name) - # TODO deprecated by :job-no-decorator: - def _find_or_create_channel(self, channel_path): - channel_model = self.env["queue.job.channel"] - parts = channel_path.split(".") - parts.reverse() - channel_name = parts.pop() - assert channel_name == "root", "A channel path starts with 'root'" - # get the root channel - channel = channel_model.search([("name", "=", channel_name)]) - while parts: - channel_name = parts.pop() - parent_channel = channel - channel = channel_model.search( - [("name", "=", channel_name), ("parent_id", "=", parent_channel.id)], - limit=1, - ) - if not channel: - channel = channel_model.create( - {"name": channel_name, "parent_id": parent_channel.id} - ) - return channel - def job_default_config(self): return self.JobConfig( channel="root", @@ -752,10 +730,3 @@ def unlink(self): res = super().unlink() self.clear_caches() return res - - # TODO deprecated by :job-no-decorator: - def _register_job(self, model, job_method): - func_name = self.job_function_name(model._name, job_method.__name__) - if not self.search_count([("name", "=", func_name)]): - channel = self._find_or_create_channel(job_method.default_channel) - self.create({"name": func_name, "channel_id": channel.id}) diff --git a/queue_job/readme/HISTORY.rst b/queue_job/readme/HISTORY.rst index 072e87fd31..ef19313c45 100644 --- a/queue_job/readme/HISTORY.rst +++ b/queue_job/readme/HISTORY.rst @@ -15,24 +15,4 @@ Next process (when running with --workers > 0) * [REF] ``@job`` and ``@related_action`` deprecated, any method can be delayed, and configured using ``queue.job.function`` records - - -13.0.1.2.0 (2020-03-10) -~~~~~~~~~~~~~~~~~~~~~~~ - -* Fix Multi-company access rules - - -13.0.1.1.0 (2019-11-01) -~~~~~~~~~~~~~~~~~~~~~~~ - -Important: the license has been changed from AGPL3 to LGPL3. - -* Remove deprecated default company method - (details on `#180 `_) - - -13.0.1.0.0 (2019-10-14) -~~~~~~~~~~~~~~~~~~~~~~~ - -* [MIGRATION] from 12.0 branched at rev. 0138cd0 +* [MIGRATION] from 13.0 branched at rev. e24ff4b diff --git a/test_queue_job/models/test_models.py b/test_queue_job/models/test_models.py index 9d5e4fc457..5a93fa0b4f 100644 --- a/test_queue_job/models/test_models.py +++ b/test_queue_job/models/test_models.py @@ -76,17 +76,6 @@ def job_b(self): def job_sub_channel(self): return - # TODO deprecated by :job-no-decorator: - @property - def dummy_property(self): - """Return foo - - Only there to check that properties are compatible - with the automatic registration of job methods - and their default channels. - """ - return "foo" - class TestRelatedAction(models.Model): diff --git a/test_queue_job/tests/common.py b/test_queue_job/tests/common.py index 3a67dea4da..63ca8cca48 100644 --- a/test_queue_job/tests/common.py +++ b/test_queue_job/tests/common.py @@ -12,9 +12,6 @@ def setUp(self): self.queue_job = self.env["queue.job"] self.user = self.env["res.users"] self.method = self.env["test.queue.job"].testing_method - self.env["queue.job.function"]._register_job( - self.env["test.queue.job"], self.method - ) def _create_job(self): test_job = Job(self.method) diff --git a/test_queue_job/tests/test_job_channels.py b/test_queue_job/tests/test_job_channels.py index 01173e0dd9..e8585b01e8 100644 --- a/test_queue_job/tests/test_job_channels.py +++ b/test_queue_job/tests/test_job_channels.py @@ -4,7 +4,7 @@ import odoo.tests.common as common from odoo import exceptions -from odoo.addons.queue_job.job import Job, job +from odoo.addons.queue_job.job import Job class TestJobChannels(common.TransactionCase): @@ -85,17 +85,6 @@ def test_set_channel_from_record(self): self.assertEquals(channel.parent_id.parent_id.name, "root") self.assertEquals(job_func.channel, "root.sub.subsub") - # TODO deprecated by :job-no-decorator: - def test_job_decorator(self): - """ Test the job decorator """ - default_channel = "channel" - retry_pattern = {1: 5} - partial = job( - None, default_channel=default_channel, retry_pattern=retry_pattern - ) - self.assertEquals(partial.keywords.get("default_channel"), default_channel) - self.assertEquals(partial.keywords.get("retry_pattern"), retry_pattern) - def test_default_removal_interval(self): channel = self.channel_model.create( {"name": "number", "parent_id": self.root_channel.id} From e795c607ac1bd7a7d8fc71d90e6261150a954a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 20 Nov 2020 16:08:47 +0100 Subject: [PATCH 4/4] [MIG] finish migration --- queue_job/models/queue_job.py | 2 +- test_queue_job/tests/test_job_channels.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index 9d2f3caab4..f7e1d0d0bd 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -250,7 +250,7 @@ def _message_post_on_failure(self): for record in self: msg = record._message_failed_job() if msg: - record.message_post(body=msg, subtype="queue_job.mt_job_failed") + record.message_post(body=msg, subtype_xmlid="queue_job.mt_job_failed") def _subscribe_users_domain(self): """Subscribe all users having the 'Queue Job Manager' group""" diff --git a/test_queue_job/tests/test_job_channels.py b/test_queue_job/tests/test_job_channels.py index e8585b01e8..16c942603b 100644 --- a/test_queue_job/tests/test_job_channels.py +++ b/test_queue_job/tests/test_job_channels.py @@ -30,9 +30,9 @@ def test_channel_tree(self): self.channel_model.create({"name": "sub"}) def test_channel_root(self): - with self.assertRaises(exceptions.Warning): + with self.assertRaises(exceptions.UserError): self.root_channel.unlink() - with self.assertRaises(exceptions.Warning): + with self.assertRaises(exceptions.UserError): self.root_channel.name = "leaf" def test_channel_on_job(self):