From f8a2811d9046bd0239ccab57e7b22c95513cd174 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 00:55:29 +0200 Subject: [PATCH 01/32] change hierarchy --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 82cfa4e9e2..cf86e4cdc5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ The HEAD of the "main" or "master" branch of InvenTree represents the current "l **No pushing to master:** New featues must be submitted as a pull request from a separate branch (one branch per feature). -#### Feature Branches +### Feature Branches Feature branches should be branched *from* the *master* branch. @@ -45,7 +45,7 @@ The HEAD of the "stable" branch represents the latest stable release code. - The bugfix *must* also be cherry picked into the *master* branch. ## Environment -#### Target version +### Target version We are currently targeting: | Name | Minimum version | |---|---| @@ -65,7 +65,7 @@ pyupgrade `find . -name "*.py"` django-upgrade --target-version 3.2 `find . -name "*.py"` ``` -### Credits +## Credits If you add any new dependencies / libraries, they need to be added to [the docs](https://github.com/inventree/inventree-docs/blob/master/docs/credits.md). Please try to do that as timely as possible. From 1c0c3f9a729ce8da321cc59d725c64d548580367 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 01:16:44 +0200 Subject: [PATCH 02/32] Add tags --- CONTRIBUTING.md | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf86e4cdc5..3786a01ab8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -124,4 +124,44 @@ HTML and javascript files are passed through the django templating engine. Trans {% load i18n %} {% trans "This string will be translated" %} - this string will not! -``` \ No newline at end of file +``` + +## Github use +### Tags +The tags describe issues and PRs in multiple areas: +| Area | Name | Description | +|---|---|---| +| Inventree Features | | | +| | feat: API | tbd | +| | feat: barcode | tbd | +| | feat: build | tbd | +| | feat: docker | tbd | +| | feat: importer | tbd | +| | feat: order | tbd | +| | feat: part | tbd | +| | feat: plugin | tbd | +| | feat: pricing | tbd | +| | feat: report | tbd | +| | feat: setup | tbd | +| | feat: stock | tbd | +| | feat: user interface | tbd | +| Type | | | +| | typ: bug | tbd | +| | typ: dependencies | tbd | +| | typ: enhancement | tbd | +| | typ: security | tbd | +| | typ: question | tbd | +| | typ: roadmap | tbd | +| State | | | +| | state: duplicate | tbd | +| | state: invalid | tbd | +| | state: no-activity | tbd | +| | state: duplicate | tbd | +| | state: wontfix | tbd | +| Ecosystem | | | +| | eco: app | tbd | +| | eco: CI | tbd | +| | eco: demo | tbd | +| Built in | | | +| | help wanted | tbd | +| | starter | tbd | From e10ee91109372b3381576171ada869227e8ea415 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 01:19:08 +0200 Subject: [PATCH 03/32] make names clearer --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3786a01ab8..145f50aa69 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -131,7 +131,7 @@ HTML and javascript files are passed through the django templating engine. Trans The tags describe issues and PRs in multiple areas: | Area | Name | Description | |---|---|---| -| Inventree Features | | | +| Feature | | | | | feat: API | tbd | | | feat: barcode | tbd | | | feat: build | tbd | @@ -162,6 +162,6 @@ The tags describe issues and PRs in multiple areas: | | eco: app | tbd | | | eco: CI | tbd | | | eco: demo | tbd | -| Built in | | | +| GH Built in | | | | | help wanted | tbd | | | starter | tbd | From 0900fe82dcbd71f41472292002ac8bc8a49fc0fa Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 20:11:41 +0200 Subject: [PATCH 04/32] ignore coverage on reverse conversion --- .../0064_purchaseorderextraline_salesorderextraline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/order/migrations/0064_purchaseorderextraline_salesorderextraline.py b/InvenTree/order/migrations/0064_purchaseorderextraline_salesorderextraline.py index 53bf0621ed..1c3d2ff743 100644 --- a/InvenTree/order/migrations/0064_purchaseorderextraline_salesorderextraline.py +++ b/InvenTree/order/migrations/0064_purchaseorderextraline_salesorderextraline.py @@ -35,7 +35,7 @@ def _convert_model(apps, line_item_ref, extra_line_ref, price_ref): print(f'Done converting line items - now at {OrderExtraLine.objects.all().count()} {extra_line_ref} / {OrderLineItem.objects.all().count()} {line_item_ref} instance(s)') -def _reconvert_model(apps, line_item_ref, extra_line_ref): +def _reconvert_model(apps, line_item_ref, extra_line_ref): # pragma: no cover """Convert ExtraLine instances back to OrderLineItem instances""" OrderLineItem = apps.get_model('order', line_item_ref) OrderExtraLine = apps.get_model('order', extra_line_ref) From 05d2d3664c75bc9e982a2aeb18219ffbe9b0848e Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 20:13:07 +0200 Subject: [PATCH 05/32] ignore defaults for coverage --- InvenTree/plugin/builtin/barcode/mixins.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/InvenTree/plugin/builtin/barcode/mixins.py b/InvenTree/plugin/builtin/barcode/mixins.py index 693df4b662..417ca04bcd 100644 --- a/InvenTree/plugin/builtin/barcode/mixins.py +++ b/InvenTree/plugin/builtin/barcode/mixins.py @@ -69,7 +69,7 @@ class BarcodeMixin: Default implementation returns None """ - return None + return None # pragma: no cover def getStockItemByHash(self): """ @@ -97,7 +97,7 @@ class BarcodeMixin: Default implementation returns None """ - return None + return None # pragma: no cover def renderStockLocation(self, loc): """ @@ -113,7 +113,7 @@ class BarcodeMixin: Default implementation returns None """ - return None + return None # pragma: no cover def renderPart(self, part): """ @@ -143,4 +143,4 @@ class BarcodeMixin: """ Default implementation returns False """ - return False + return False # pragma: no cover From 300558adb06994b6884ef919e7376c4c1593eca2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 20:26:49 +0200 Subject: [PATCH 06/32] increase coverage on owners model --- InvenTree/users/tests.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/InvenTree/users/tests.py b/InvenTree/users/tests.py index d9af560ed8..e6a4019481 100644 --- a/InvenTree/users/tests.py +++ b/InvenTree/users/tests.py @@ -197,6 +197,10 @@ class OwnerModelTest(TestCase): self.assertTrue(user_as_owner in related_owners) self.assertTrue(group_as_owner in related_owners) + # Check owner matching + owners = Owner.get_owners_matching_user(self.user) + self.assertEqual(owners, [user_as_owner, group_as_owner]) + # Delete user and verify owner was deleted too self.user.delete() user_as_owner = Owner.get_owner(self.user) From 5fa7b45d1dcb295a1d76fa0bf9c6994d656b76b7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 21:39:45 +0200 Subject: [PATCH 07/32] Add tests for scheduling Closes #2523 --- .../integration/test_scheduled_task.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 InvenTree/plugin/samples/integration/test_scheduled_task.py diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py new file mode 100644 index 0000000000..4df357df29 --- /dev/null +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -0,0 +1,29 @@ +""" Unit tests for scheduled tasks""" + +from django.test import TestCase + +from plugin import registry + + +class ScheduledTaskPluginTests(TestCase): + """ Tests for ScheduledTaskPlugin """ + + def test_function(self): + """check if the scheduling works""" + # The plugin should be defined + self.assertIn('schedule', registry.plugins) + plg = registry.plugins['schedule'] + self.assertTrue(plg) + + # check that the built-in function is running + plg.member_func() + + # check that the tasks are defined + self.assertEqual(plg.get_task_names(), ['plugin.schedule.member', 'plugin.schedule.hello', 'plugin.schedule.world']) + + # register + plg.register_tasks() + # check that schedule was registers + from django_q.models import Schedule + scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") + self.assertEqual(len(scheduled_plugin_tasks), 3) From 5ea6a325ee1e2f0c72f30f017eba8baf9d2c2454 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 21:48:49 +0200 Subject: [PATCH 08/32] fix smaple code --- InvenTree/plugin/samples/integration/scheduled_task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/samples/integration/scheduled_task.py b/InvenTree/plugin/samples/integration/scheduled_task.py index c8b1c4c5d0..579ad4effe 100644 --- a/InvenTree/plugin/samples/integration/scheduled_task.py +++ b/InvenTree/plugin/samples/integration/scheduled_task.py @@ -36,7 +36,7 @@ class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, IntegrationPluginBase): 'minutes': 45, }, 'world': { - 'func': 'plugin.samples.integration.scheduled_task.print_hello', + 'func': 'plugin.samples.integration.scheduled_task.print_world', 'schedule': 'H', }, } From 70b108d81305a261dd657735b53eed3886f6d01c Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 21:56:58 +0200 Subject: [PATCH 09/32] add check for call function --- InvenTree/plugin/samples/integration/test_scheduled_task.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index 4df357df29..a43356c36d 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -3,6 +3,7 @@ from django.test import TestCase from plugin import registry +from plugin.registry import call_function class ScheduledTaskPluginTests(TestCase): @@ -27,3 +28,7 @@ class ScheduledTaskPluginTests(TestCase): from django_q.models import Schedule scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") self.assertEqual(len(scheduled_plugin_tasks), 3) + + def test_calling(self): + """check if a function can be called without errors""" + call_function('schedule', 'member_func') From 7c437a3cf293e4d78e4fd1dd6a036ab9058e55db Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 21:59:17 +0200 Subject: [PATCH 10/32] adjust testing function to also check return --- InvenTree/plugin/samples/integration/scheduled_task.py | 1 + InvenTree/plugin/samples/integration/test_scheduled_task.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/InvenTree/plugin/samples/integration/scheduled_task.py b/InvenTree/plugin/samples/integration/scheduled_task.py index 579ad4effe..635bdfe90d 100644 --- a/InvenTree/plugin/samples/integration/scheduled_task.py +++ b/InvenTree/plugin/samples/integration/scheduled_task.py @@ -58,3 +58,4 @@ class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, IntegrationPluginBase): t_or_f = self.get_setting('T_OR_F') print(f"Called member_func - value is {t_or_f}") + return t_or_f diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index a43356c36d..4d41eea7c5 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -17,7 +17,7 @@ class ScheduledTaskPluginTests(TestCase): self.assertTrue(plg) # check that the built-in function is running - plg.member_func() + self.assertEqual(plg.member_func(), False) # check that the tasks are defined self.assertEqual(plg.get_task_names(), ['plugin.schedule.member', 'plugin.schedule.hello', 'plugin.schedule.world']) @@ -31,4 +31,4 @@ class ScheduledTaskPluginTests(TestCase): def test_calling(self): """check if a function can be called without errors""" - call_function('schedule', 'member_func') + self.assertEqual(call_function('schedule', 'member_func'), False) From 07a86a3883af719e843c1af1ad9725c0b1323f22 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:05:56 +0200 Subject: [PATCH 11/32] ognore catches in coverage --- InvenTree/users/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py index bda1074601..8f42268224 100644 --- a/InvenTree/users/models.py +++ b/InvenTree/users/models.py @@ -564,14 +564,14 @@ class Owner(models.Model): try: owners.append(cls.objects.get(owner_id=user.pk, owner_type=user_type)) - except: + except: # pragma: no cover pass for group in user.groups.all(): try: owner = cls.objects.get(owner_id=group.pk, owner_type=group_type) owners.append(owner) - except: + except: # pragma: no cover pass return owners From 58a5eac66a222981403c4825034f2c73917a3d9b Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:06:10 +0200 Subject: [PATCH 12/32] ignore outside sample code in coverage --- InvenTree/plugin/samples/integration/scheduled_task.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/plugin/samples/integration/scheduled_task.py b/InvenTree/plugin/samples/integration/scheduled_task.py index 635bdfe90d..9ec70e2795 100644 --- a/InvenTree/plugin/samples/integration/scheduled_task.py +++ b/InvenTree/plugin/samples/integration/scheduled_task.py @@ -8,11 +8,11 @@ from plugin.mixins import ScheduleMixin, SettingsMixin # Define some simple tasks to perform def print_hello(): - print("Hello") + print("Hello") # pragma: no cover def print_world(): - print("World") + print("World") # pragma: no cover class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, IntegrationPluginBase): From 4e5015e7420380ad6a6f58d37281f378a677510e Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:08:57 +0200 Subject: [PATCH 13/32] do not cover unready db --- InvenTree/plugin/builtin/integration/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index 62ce38a673..d37c8db58d 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -209,7 +209,7 @@ class ScheduleMixin: repeats=task.get('repeats', -1), ) - except (ProgrammingError, OperationalError): + except (ProgrammingError, OperationalError): # pragma: no cover # Database might not yet be ready logger.warning("register_tasks failed, database not ready") From 4663815cfa53799614200ebfcb2e998aa0c2db2e Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:09:20 +0200 Subject: [PATCH 14/32] this is just an extra safety check - should not trigger --- InvenTree/plugin/builtin/integration/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index d37c8db58d..9d043b7c91 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -171,7 +171,7 @@ class ScheduleMixin: if Schedule.objects.filter(name=task_name).exists(): # Scheduled task already exists - continue! - continue + continue # pragma: no cover logger.info(f"Adding scheduled task '{task_name}'") From 0a012c3c584e19d9de167fa9c348db93b47b5b24 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:09:58 +0200 Subject: [PATCH 15/32] only possible in test cases with plugin_tests off --- InvenTree/plugin/builtin/integration/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index 9d043b7c91..d17cebf283 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -56,7 +56,7 @@ class SettingsMixin: if not plugin: # Cannot find associated plugin model, return - return + return # pragma: no cover PluginSetting.set_setting(key, value, user, plugin=plugin) From b9cbc287f24911d026b8103348cb8cfc566c98d1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:10:26 +0200 Subject: [PATCH 16/32] empty mixin schaffold - no tests --- InvenTree/plugin/builtin/integration/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index d17cebf283..0e1dd3518e 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -408,7 +408,7 @@ class LabelPrintingMixin: """ MIXIN_NAME = 'Label printing' - def __init__(self): + def __init__(self): # pragma: no cover super().__init__() self.add_mixin('labels', True, __class__) From 08e278232b4b8b3c3d817f29866afcde065516cc Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:12:34 +0200 Subject: [PATCH 17/32] ignore db not ready in coverage --- InvenTree/plugin/builtin/integration/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index 0e1dd3518e..19ee04b77f 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -230,7 +230,7 @@ class ScheduleMixin: scheduled_task.delete() except Schedule.DoesNotExist: pass - except (ProgrammingError, OperationalError): + except (ProgrammingError, OperationalError): # pragma: no cover # Database might not yet be ready logger.warning("unregister_tasks failed, database not ready") From a357c4ef88ab4fc8674b6edb4cdaff307001ce2d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:13:29 +0200 Subject: [PATCH 18/32] also cover unregistering --- InvenTree/plugin/samples/integration/test_scheduled_task.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index 4d41eea7c5..00488bdb6a 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -29,6 +29,11 @@ class ScheduledTaskPluginTests(TestCase): scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") self.assertEqual(len(scheduled_plugin_tasks), 3) + # test unregistering + plg.unregister_tasks() + scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") + self.assertEqual(len(scheduled_plugin_tasks), 0) + def test_calling(self): """check if a function can be called without errors""" self.assertEqual(call_function('schedule', 'member_func'), False) From 626e3838aeea970cad6fd5d8eb9b0349bd631d99 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:15:24 +0200 Subject: [PATCH 19/32] also cover errors --- InvenTree/plugin/samples/integration/test_scheduled_task.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index 00488bdb6a..bbacad79d3 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -29,6 +29,11 @@ class ScheduledTaskPluginTests(TestCase): scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") self.assertEqual(len(scheduled_plugin_tasks), 3) + # delete middle task + # this is to check the system also deals with disappearing tasks + scheduled_plugin_tasks[1].delete() + self.assertEqual(len(scheduled_plugin_tasks), 2) + # test unregistering plg.unregister_tasks() scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") From 204b4fd527f1c7a1ebe34f03d2b5282e28987bfb Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:55:39 +0200 Subject: [PATCH 20/32] rename test --- InvenTree/plugin/samples/integration/test_scheduled_task.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index bbacad79d3..d0a9add49f 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -6,8 +6,8 @@ from plugin import registry from plugin.registry import call_function -class ScheduledTaskPluginTests(TestCase): - """ Tests for ScheduledTaskPlugin """ +class ExampleScheduledTaskPluginTests(TestCase): + """ Tests for provided ScheduledTaskPlugin """ def test_function(self): """check if the scheduling works""" From d49f74746aaf03a911516c0696c78576f619829e Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:56:28 +0200 Subject: [PATCH 21/32] test that MixinImplementationErrors raise --- .../integration/test_scheduled_task.py | 110 +++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index d0a9add49f..7a3e34ad53 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -2,8 +2,10 @@ from django.test import TestCase -from plugin import registry +from plugin import registry, IntegrationPluginBase +from plugin.helpers import MixinImplementationError from plugin.registry import call_function +from plugin.mixins import ScheduleMixin class ExampleScheduledTaskPluginTests(TestCase): @@ -42,3 +44,109 @@ class ExampleScheduledTaskPluginTests(TestCase): def test_calling(self): """check if a function can be called without errors""" self.assertEqual(call_function('schedule', 'member_func'), False) + + +class ScheduledTaskPluginTests(TestCase): + """ Tests for ScheduledTaskPluginTests mixin base """ + + def test_init(self): + """Check that all MixinImplementationErrors raise""" + class Base(ScheduleMixin, IntegrationPluginBase): + PLUGIN_NAME = 'APlugin' + + class NoSchedules(Base): + """Plugin without schedules""" + pass + + with self.assertRaises(MixinImplementationError): + NoSchedules() + + class WrongFuncSchedules(Base): + """ + Plugin with broken functions + + This plugin is missing a func + """ + + SCHEDULED_TASKS = { + 'test': { + 'schedule': 'I', + 'minutes': 30, + }, + } + + def test(self): + pass + + with self.assertRaises(MixinImplementationError): + WrongFuncSchedules() + + class WrongFuncSchedules1(WrongFuncSchedules): + """ + Plugin with broken functions + + This plugin is missing a schedule + """ + + SCHEDULED_TASKS = { + 'test': { + 'func': 'test', + 'minutes': 30, + }, + } + + with self.assertRaises(MixinImplementationError): + WrongFuncSchedules1() + + + class WrongFuncSchedules2(WrongFuncSchedules): + """ + Plugin with broken functions + + This plugin is missing a schedule + """ + + SCHEDULED_TASKS = { + 'test': { + 'func': 'test', + 'minutes': 30, + }, + } + + with self.assertRaises(MixinImplementationError): + WrongFuncSchedules2() + + class WrongFuncSchedules3(WrongFuncSchedules): + """ + Plugin with broken functions + + This plugin has a broken schedule + """ + + SCHEDULED_TASKS = { + 'test': { + 'func': 'test', + 'schedule': 'XX', + 'minutes': 30, + }, + } + + with self.assertRaises(MixinImplementationError): + WrongFuncSchedules3() + + class WrongFuncSchedules4(WrongFuncSchedules): + """ + Plugin with broken functions + + This plugin is missing a minute marker for its schedule + """ + + SCHEDULED_TASKS = { + 'test': { + 'func': 'test', + 'schedule': 'I', + }, + } + + with self.assertRaises(MixinImplementationError): + WrongFuncSchedules4() From 096c0c876cc99450a6b954cae20aa183d48bcd90 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 22:58:24 +0200 Subject: [PATCH 22/32] PEP fix --- .../plugin/samples/integration/test_scheduled_task.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index 7a3e34ad53..1909c9a80e 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -64,7 +64,7 @@ class ScheduledTaskPluginTests(TestCase): class WrongFuncSchedules(Base): """ Plugin with broken functions - + This plugin is missing a func """ @@ -84,7 +84,7 @@ class ScheduledTaskPluginTests(TestCase): class WrongFuncSchedules1(WrongFuncSchedules): """ Plugin with broken functions - + This plugin is missing a schedule """ @@ -98,11 +98,10 @@ class ScheduledTaskPluginTests(TestCase): with self.assertRaises(MixinImplementationError): WrongFuncSchedules1() - class WrongFuncSchedules2(WrongFuncSchedules): """ Plugin with broken functions - + This plugin is missing a schedule """ @@ -119,7 +118,7 @@ class ScheduledTaskPluginTests(TestCase): class WrongFuncSchedules3(WrongFuncSchedules): """ Plugin with broken functions - + This plugin has a broken schedule """ @@ -137,7 +136,7 @@ class ScheduledTaskPluginTests(TestCase): class WrongFuncSchedules4(WrongFuncSchedules): """ Plugin with broken functions - + This plugin is missing a minute marker for its schedule """ From 1522d330fa8a341867fb7cc6a186ccb248f694e1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:06:11 +0200 Subject: [PATCH 23/32] add test for is_sample --- InvenTree/plugin/test_integration.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/InvenTree/plugin/test_integration.py b/InvenTree/plugin/test_integration.py index 3e4c38f968..5b211e2d96 100644 --- a/InvenTree/plugin/test_integration.py +++ b/InvenTree/plugin/test_integration.py @@ -11,6 +11,8 @@ from plugin import IntegrationPluginBase from plugin.mixins import AppMixin, SettingsMixin, UrlsMixin, NavigationMixin, APICallMixin from plugin.urls import PLUGIN_BASE +from plugin.samples.integration.sample import SampleIntegrationPlugin + class BaseMixinDefinition: def test_mixin_name(self): @@ -238,6 +240,7 @@ class IntegrationPluginBaseTests(TestCase): LICENSE = 'MIT' self.plugin_name = NameIntegrationPluginBase() + self.plugin_sample = SampleIntegrationPlugin() def test_action_name(self): """check the name definition possibilities""" @@ -246,6 +249,10 @@ class IntegrationPluginBaseTests(TestCase): self.assertEqual(self.plugin_simple.plugin_name(), 'SimplePlugin') self.assertEqual(self.plugin_name.plugin_name(), 'Aplugin') + # is_sampe + self.assertEqual(self.plugin.is_sample, False) + self.assertEqual(self.plugin_sample.is_sample, True) + # slug self.assertEqual(self.plugin.slug, '') self.assertEqual(self.plugin_simple.slug, 'simpleplugin') From e95c3e09489c5ab6541dfadd656e0954d98951e1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:06:38 +0200 Subject: [PATCH 24/32] do not cover default returns --- InvenTree/plugin/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/plugin/helpers.py b/InvenTree/plugin/helpers.py index 7f9f2be740..05bd44d4f3 100644 --- a/InvenTree/plugin/helpers.py +++ b/InvenTree/plugin/helpers.py @@ -75,7 +75,7 @@ def handle_error(error, do_raise: bool = True, do_log: bool = True, log_name: st path_parts.remove('plugin') path_parts.pop(0) else: - path_parts.remove('plugins') + path_parts.remove('plugins') # pragma: no cover package_name = '.'.join(path_parts) @@ -135,7 +135,7 @@ def check_git_version(): except ValueError: # pragma: no cover pass - return False + return False # pragma: no cover class GitStatus: From c5acfaf541e5ae6dc89cdbcae5bad3f3f37fe183 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:06:57 +0200 Subject: [PATCH 25/32] do not coverage catch for load --- InvenTree/plugin/apps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/apps.py b/InvenTree/plugin/apps.py index 8de4cb9b6c..521d42b743 100644 --- a/InvenTree/plugin/apps.py +++ b/InvenTree/plugin/apps.py @@ -35,7 +35,7 @@ class PluginAppConfig(AppConfig): if InvenTreeSetting.get_setting('PLUGIN_ON_STARTUP', create=False): # make sure all plugins are installed registry.install_plugin_file() - except: + except: # pragma: no cover pass # get plugins and init them From 5e277130fa57a4362e60b016b597f22d1ca2aabc Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:07:16 +0200 Subject: [PATCH 26/32] do not cover not implemented Mixin --- InvenTree/plugin/builtin/integration/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/builtin/integration/mixins.py b/InvenTree/plugin/builtin/integration/mixins.py index 19ee04b77f..ebe3ebf553 100644 --- a/InvenTree/plugin/builtin/integration/mixins.py +++ b/InvenTree/plugin/builtin/integration/mixins.py @@ -426,7 +426,7 @@ class LabelPrintingMixin: """ # Unimplemented (to be implemented by the particular plugin class) - ... + ... # pragma: no cover class APICallMixin: From cf0cbff69af6ba6508a30e42632ff9d291f26b09 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:19:01 +0200 Subject: [PATCH 27/32] we are not covering packages right now --- InvenTree/plugin/integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/plugin/integration.py b/InvenTree/plugin/integration.py index cab3e81a8b..c622c0402c 100644 --- a/InvenTree/plugin/integration.py +++ b/InvenTree/plugin/integration.py @@ -191,7 +191,7 @@ class IntegrationPluginBase(MixinBase, plugin_base.InvenTreePluginBase): Path to the plugin """ if self._is_package: - return self.__module__ + return self.__module__ # pragma: no cover return pathlib.Path(self.def_path).relative_to(settings.BASE_DIR) @property From e1b395c9be802f3148c2060d4bb494595aed7441 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:19:51 +0200 Subject: [PATCH 28/32] test is_active --- InvenTree/plugin/test_plugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/InvenTree/plugin/test_plugin.py b/InvenTree/plugin/test_plugin.py index f88b6e6176..c0835c2fb3 100644 --- a/InvenTree/plugin/test_plugin.py +++ b/InvenTree/plugin/test_plugin.py @@ -31,6 +31,10 @@ class InvenTreePluginTests(TestCase): self.assertEqual(self.named_plugin.PLUGIN_NAME, 'abc123') self.assertEqual(self.named_plugin.plugin_name(), 'abc123') + def test_basic_is_active(self): + """check if a basic plugin is active""" + self.assertEqual(self.plugin.is_active(), False) + class PluginTagTests(TestCase): """ Tests for the plugin extras """ From 6504ef535a2b3f716ba2cdcb46eba165a5d544fb Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 3 May 2022 23:23:36 +0200 Subject: [PATCH 29/32] fix test - len needs to be recalculated --- InvenTree/plugin/samples/integration/test_scheduled_task.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index 1909c9a80e..1bcd2015f1 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -34,6 +34,8 @@ class ExampleScheduledTaskPluginTests(TestCase): # delete middle task # this is to check the system also deals with disappearing tasks scheduled_plugin_tasks[1].delete() + # there should be one less now + scheduled_plugin_tasks = Schedule.objects.filter(name__istartswith="plugin.") self.assertEqual(len(scheduled_plugin_tasks), 2) # test unregistering From 8038cff87481f621b5d8267b89a15cd81567963c Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 4 May 2022 00:43:49 +0200 Subject: [PATCH 30/32] ignore for coverage --- InvenTree/plugin/helpers.py | 2 +- InvenTree/plugin/registry.py | 6 +++--- InvenTree/plugin/samples/integration/test_scheduled_task.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/InvenTree/plugin/helpers.py b/InvenTree/plugin/helpers.py index 05bd44d4f3..f1753b1b45 100644 --- a/InvenTree/plugin/helpers.py +++ b/InvenTree/plugin/helpers.py @@ -88,7 +88,7 @@ def handle_error(error, do_raise: bool = True, do_log: bool = True, log_name: st if do_raise: # do a straight raise if we are playing with enviroment variables at execution time, ignore the broken sample if settings.TESTING_ENV and package_name != 'integration.broken_sample' and isinstance(error, IntegrityError): - raise error + raise error # pragma: no cover raise IntegrationPluginError(package_name, str(error)) # endregion diff --git a/InvenTree/plugin/registry.py b/InvenTree/plugin/registry.py index 304932f6f8..240bd3446b 100644 --- a/InvenTree/plugin/registry.py +++ b/InvenTree/plugin/registry.py @@ -283,7 +283,7 @@ class PluginsRegistry: if not settings.PLUGIN_TESTING: raise error # pragma: no cover plugin_db_setting = None - except (IntegrityError) as error: + except (IntegrityError) as error: # pragma: no cover logger.error(f"Error initializing plugin: {error}") # Always activate if testing @@ -322,7 +322,7 @@ class PluginsRegistry: self.plugins[plugin.slug] = plugin else: # save for later reference - self.plugins_inactive[plug_key] = plugin_db_setting + self.plugins_inactive[plug_key] = plugin_db_setting # pragma: no cover def _activate_plugins(self, force_reload=False): """ @@ -411,7 +411,7 @@ class PluginsRegistry: deleted_count += 1 if deleted_count > 0: - logger.info(f"Removed {deleted_count} old scheduled tasks") + logger.info(f"Removed {deleted_count} old scheduled tasks") # pragma: no cover except (ProgrammingError, OperationalError): # Database might not yet be ready logger.warning("activate_integration_schedule failed, database not ready") diff --git a/InvenTree/plugin/samples/integration/test_scheduled_task.py b/InvenTree/plugin/samples/integration/test_scheduled_task.py index 1bcd2015f1..314f3f3f1f 100644 --- a/InvenTree/plugin/samples/integration/test_scheduled_task.py +++ b/InvenTree/plugin/samples/integration/test_scheduled_task.py @@ -78,7 +78,7 @@ class ScheduledTaskPluginTests(TestCase): } def test(self): - pass + pass # pragma: no cover with self.assertRaises(MixinImplementationError): WrongFuncSchedules() From 75e24635b53cf6cc08cf3455ba081128423065a4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 May 2022 09:17:42 +1000 Subject: [PATCH 31/32] Fix speling errors in translated strings --- InvenTree/InvenTree/helpers.py | 2 +- InvenTree/build/models.py | 2 +- InvenTree/build/serializers.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index d9dfaa395d..36cd288232 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -537,7 +537,7 @@ def extract_serial_numbers(serials, expected_quantity, next_number: int): # The number of extracted serial numbers must match the expected quantity if not expected_quantity == len(numbers): - raise ValidationError([_("Number of unique serial number ({s}) must match quantity ({q})").format(s=len(numbers), q=expected_quantity)]) + raise ValidationError([_("Number of unique serial numbers ({s}) must match quantity ({q})").format(s=len(numbers), q=expected_quantity)]) return numbers diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 1fdf613b68..43bca0e238 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -1177,7 +1177,7 @@ class BuildItem(models.Model): a = normalize(self.stock_item.quantity) raise ValidationError({ - 'quantity': _(f'Allocated quantity ({q}) must not execed available stock quantity ({a})') + 'quantity': _(f'Allocated quantity ({q}) must not exceed available stock quantity ({a})') }) # Allocated quantity cannot cause the stock item to be over-allocated diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py index 07a0bcc29a..bed4b59203 100644 --- a/InvenTree/build/serializers.py +++ b/InvenTree/build/serializers.py @@ -387,7 +387,7 @@ class BuildOutputCompleteSerializer(serializers.Serializer): default=False, required=False, label=_('Accept Incomplete Allocation'), - help_text=_('Complete ouputs if stock has not been fully allocated'), + help_text=_('Complete outputs if stock has not been fully allocated'), ) notes = serializers.CharField( From dbc0023c57d5d2fa0522d8674aa2aa66958be980 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 4 May 2022 12:10:00 +1000 Subject: [PATCH 32/32] Update CONTRIBUTING.md Update labels a bit --- CONTRIBUTING.md | 65 +++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 145f50aa69..c36c11b62b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -131,37 +131,34 @@ HTML and javascript files are passed through the django templating engine. Trans The tags describe issues and PRs in multiple areas: | Area | Name | Description | |---|---|---| -| Feature | | | -| | feat: API | tbd | -| | feat: barcode | tbd | -| | feat: build | tbd | -| | feat: docker | tbd | -| | feat: importer | tbd | -| | feat: order | tbd | -| | feat: part | tbd | -| | feat: plugin | tbd | -| | feat: pricing | tbd | -| | feat: report | tbd | -| | feat: setup | tbd | -| | feat: stock | tbd | -| | feat: user interface | tbd | -| Type | | | -| | typ: bug | tbd | -| | typ: dependencies | tbd | -| | typ: enhancement | tbd | -| | typ: security | tbd | -| | typ: question | tbd | -| | typ: roadmap | tbd | -| State | | | -| | state: duplicate | tbd | -| | state: invalid | tbd | -| | state: no-activity | tbd | -| | state: duplicate | tbd | -| | state: wontfix | tbd | -| Ecosystem | | | -| | eco: app | tbd | -| | eco: CI | tbd | -| | eco: demo | tbd | -| GH Built in | | | -| | help wanted | tbd | -| | starter | tbd | +| Type Labels | | | +| | bug | Identifies a bug which needs to be addressed | +| | dependency | Relates to a project dependency | +| | duplicate | Duplicate of another issue or PR | +| | enhancement | This is an suggested enhancement or new feature | +| | help wanted | Assistance required | +| | invalid | This issue or PR is considered invalid | +| | inactive | Indicates lack of activity | +| | question | This is a question | +| | roadmap | This is a roadmap feature with no immediate plans for implementation | +| | security | Relates to a security issue | +| | starter | Good issue for a developer new to the project | +| | wontfix | No work will be done against this issue or PR | +| Feature Labels | | | +| | API | Relates to the API | +| | barcode | Barcode scanning and integration | +| | build | Build orders | +| | importer | Data importing and processing | +| | order | Purchase order and sales orders | +| | part | Parts | +| | plugin | Plugin ecosystem | +| | pricing | Pricing functionality | +| | report | Report generation | +| | stock | Stock item management | +| | user interface | User interface | +| Ecosystem Labels | | | +| | demo | Relates to the InvenTree demo server or dataset | +| | docker | Docker / docker-compose | +| | CI | CI / unit testing ecosystem | +| | setup | Relates to the InvenTree setup / installation process | +