This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-pycasbin.git


The following commit(s) were added to refs/heads/master by this push:
     new 98725bc  fix: notify the watcher when auto-save is disabled
98725bc is described below

commit 98725bc6f7ad63dd7b4fdb5d51ecbb9ae4203047
Author: Yang Luo <[email protected]>
AuthorDate: Wed Oct 7 11:21:02 2026 +0800

    fix: notify the watcher when auto-save is disabled
---
 casbin/async_internal_enforcer.py | 140 +++++++++++++++++++-------------------
 casbin/internal_enforcer.py       |  72 ++++++++++----------
 tests/test_watcher_ex.py          |  60 ++++++++++++++++
 3 files changed, 166 insertions(+), 106 deletions(-)

diff --git a/casbin/async_internal_enforcer.py 
b/casbin/async_internal_enforcer.py
index 275a0ae..063d9f7 100644
--- a/casbin/async_internal_enforcer.py
+++ b/casbin/async_internal_enforcer.py
@@ -133,18 +133,18 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                update_for_add_policy = getattr(self.watcher, 
"update_for_add_policy", None)
-                if callable(update_for_add_policy):
-                    if inspect.iscoroutinefunction(update_for_add_policy):
-                        await update_for_add_policy(sec, ptype, rule)
-                    else:
-                        update_for_add_policy(sec, ptype, rule)
+        if self.watcher and self.auto_notify_watcher:
+            update_for_add_policy = getattr(self.watcher, 
"update_for_add_policy", None)
+            if callable(update_for_add_policy):
+                if inspect.iscoroutinefunction(update_for_add_policy):
+                    await update_for_add_policy(sec, ptype, rule)
+                else:
+                    update_for_add_policy(sec, ptype, rule)
+            else:
+                if inspect.iscoroutinefunction(self.watcher.update):
+                    await self.watcher.update()
                 else:
-                    if inspect.iscoroutinefunction(self.watcher.update):
-                        await self.watcher.update()
-                    else:
-                        self.watcher.update()
+                    self.watcher.update()
 
         rule_added = self.model.add_policy(sec, ptype, rule)
 
@@ -164,18 +164,18 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                update_for_add_policies = getattr(self.watcher, 
"update_for_add_policies", None)
-                if callable(update_for_add_policies):
-                    if inspect.iscoroutinefunction(update_for_add_policies):
-                        await update_for_add_policies(sec, ptype, rules)
-                    else:
-                        update_for_add_policies(sec, ptype, rules)
+        if self.watcher and self.auto_notify_watcher:
+            update_for_add_policies = getattr(self.watcher, 
"update_for_add_policies", None)
+            if callable(update_for_add_policies):
+                if inspect.iscoroutinefunction(update_for_add_policies):
+                    await update_for_add_policies(sec, ptype, rules)
                 else:
-                    if inspect.iscoroutinefunction(self.watcher.update):
-                        await self.watcher.update()
-                    else:
-                        self.watcher.update()
+                    update_for_add_policies(sec, ptype, rules)
+            else:
+                if inspect.iscoroutinefunction(self.watcher.update):
+                    await self.watcher.update()
+                else:
+                    self.watcher.update()
 
         rules_added = self.model.add_policies(sec, ptype, rules)
 
@@ -193,11 +193,11 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if inspect.iscoroutinefunction(self.watcher.update):
-                    await self.watcher.update()
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if inspect.iscoroutinefunction(self.watcher.update):
+                await self.watcher.update()
+            else:
+                self.watcher.update()
 
         return rule_updated
 
@@ -213,11 +213,11 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if inspect.iscoroutinefunction(self.watcher.update):
-                    await self.watcher.update()
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if inspect.iscoroutinefunction(self.watcher.update):
+                await self.watcher.update()
+            else:
+                self.watcher.update()
 
         return rules_updated
 
@@ -262,18 +262,18 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                update_for_remove_policy = getattr(self.watcher, 
"update_for_remove_policy", None)
-                if callable(update_for_remove_policy):
-                    if inspect.iscoroutinefunction(update_for_remove_policy):
-                        await update_for_remove_policy(sec, ptype, rule)
-                    else:
-                        update_for_remove_policy(sec, ptype, rule)
+        if self.watcher and self.auto_notify_watcher:
+            update_for_remove_policy = getattr(self.watcher, 
"update_for_remove_policy", None)
+            if callable(update_for_remove_policy):
+                if inspect.iscoroutinefunction(update_for_remove_policy):
+                    await update_for_remove_policy(sec, ptype, rule)
                 else:
-                    if inspect.iscoroutinefunction(self.watcher.update):
-                        await self.watcher.update()
-                    else:
-                        self.watcher.update()
+                    update_for_remove_policy(sec, ptype, rule)
+            else:
+                if inspect.iscoroutinefunction(self.watcher.update):
+                    await self.watcher.update()
+                else:
+                    self.watcher.update()
 
         return rule_removed
 
@@ -291,18 +291,18 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                update_for_remove_policies = getattr(self.watcher, 
"update_for_remove_policies", None)
-                if callable(update_for_remove_policies):
-                    if inspect.iscoroutinefunction(update_for_remove_policies):
-                        await update_for_remove_policies(sec, ptype, rules)
-                    else:
-                        update_for_remove_policies(sec, ptype, rules)
+        if self.watcher and self.auto_notify_watcher:
+            update_for_remove_policies = getattr(self.watcher, 
"update_for_remove_policies", None)
+            if callable(update_for_remove_policies):
+                if inspect.iscoroutinefunction(update_for_remove_policies):
+                    await update_for_remove_policies(sec, ptype, rules)
                 else:
-                    if inspect.iscoroutinefunction(self.watcher.update):
-                        await self.watcher.update()
-                    else:
-                        self.watcher.update()
+                    update_for_remove_policies(sec, ptype, rules)
+            else:
+                if inspect.iscoroutinefunction(self.watcher.update):
+                    await self.watcher.update()
+                else:
+                    self.watcher.update()
 
         return rules_removed
 
@@ -317,18 +317,18 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                update_for_remove_filtered_policy = getattr(self.watcher, 
"update_for_remove_filtered_policy", None)
-                if callable(update_for_remove_filtered_policy):
-                    if 
inspect.iscoroutinefunction(update_for_remove_filtered_policy):
-                        await update_for_remove_filtered_policy(sec, ptype, 
field_index, *field_values)
-                    else:
-                        update_for_remove_filtered_policy(sec, ptype, 
field_index, *field_values)
+        if self.watcher and self.auto_notify_watcher:
+            update_for_remove_filtered_policy = getattr(self.watcher, 
"update_for_remove_filtered_policy", None)
+            if callable(update_for_remove_filtered_policy):
+                if 
inspect.iscoroutinefunction(update_for_remove_filtered_policy):
+                    await update_for_remove_filtered_policy(sec, ptype, 
field_index, *field_values)
                 else:
-                    if inspect.iscoroutinefunction(self.watcher.update):
-                        await self.watcher.update()
-                    else:
-                        self.watcher.update()
+                    update_for_remove_filtered_policy(sec, ptype, field_index, 
*field_values)
+            else:
+                if inspect.iscoroutinefunction(self.watcher.update):
+                    await self.watcher.update()
+                else:
+                    self.watcher.update()
 
         return rule_removed
 
@@ -343,11 +343,11 @@ class AsyncInternalEnforcer(CoreEnforcer):
             if result is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if inspect.iscoroutinefunction(self.watcher.update):
-                    await self.watcher.update()
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if inspect.iscoroutinefunction(self.watcher.update):
+                await self.watcher.update()
+            else:
+                self.watcher.update()
 
         return rule_removed
 
diff --git a/casbin/internal_enforcer.py b/casbin/internal_enforcer.py
index a6f7d3e..2762f06 100644
--- a/casbin/internal_enforcer.py
+++ b/casbin/internal_enforcer.py
@@ -29,11 +29,11 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.add_policy(sec, ptype, rule) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if callable(getattr(self.watcher, "update_for_add_policy", 
None)):
-                    self.watcher.update_for_add_policy(sec, ptype, rule)
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if callable(getattr(self.watcher, "update_for_add_policy", None)):
+                self.watcher.update_for_add_policy(sec, ptype, rule)
+            else:
+                self.watcher.update()
 
         rule_added = self.model.add_policy(sec, ptype, rule)
 
@@ -52,11 +52,11 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.add_policies(sec, ptype, rules) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if callable(getattr(self.watcher, "update_for_add_policies", 
None)):
-                    self.watcher.update_for_add_policies(sec, ptype, rules)
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if callable(getattr(self.watcher, "update_for_add_policies", 
None)):
+                self.watcher.update_for_add_policies(sec, ptype, rules)
+            else:
+                self.watcher.update()
 
         rules_added = self.model.add_policies(sec, ptype, rules)
 
@@ -71,11 +71,11 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.add_policies_ex(sec, ptype, rules) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if callable(getattr(self.watcher, 
"update_for_add_policies_ex", None)):
-                    self.watcher.update_for_add_policies_ex(sec, ptype, rules)
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if callable(getattr(self.watcher, "update_for_add_policies_ex", 
None)):
+                self.watcher.update_for_add_policies_ex(sec, ptype, rules)
+            else:
+                self.watcher.update()
 
         rules_added = self.model.add_policies_ex(sec, ptype, rules)
 
@@ -92,8 +92,8 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.update_policy(sec, ptype, old_rule, new_rule) is 
False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            self.watcher.update()
 
         return rule_updated
 
@@ -108,8 +108,8 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.update_policies(sec, ptype, old_rules, new_rules) 
is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            self.watcher.update()
 
         return rules_updated
 
@@ -148,11 +148,11 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.remove_policy(sec, ptype, rule) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if callable(getattr(self.watcher, "update_for_remove_policy", 
None)):
-                    self.watcher.update_for_remove_policy(sec, ptype, rule)
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if callable(getattr(self.watcher, "update_for_remove_policy", 
None)):
+                self.watcher.update_for_remove_policy(sec, ptype, rule)
+            else:
+                self.watcher.update()
 
         return rule_removed
 
@@ -169,11 +169,11 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.remove_policies(sec, ptype, rules) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if callable(getattr(self.watcher, 
"update_for_remove_policies", None)):
-                    self.watcher.update_for_remove_policies(sec, ptype, rules)
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if callable(getattr(self.watcher, "update_for_remove_policies", 
None)):
+                self.watcher.update_for_remove_policies(sec, ptype, rules)
+            else:
+                self.watcher.update()
 
         return rules_removed
 
@@ -187,11 +187,11 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.remove_filtered_policy(sec, ptype, field_index, 
*field_values) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                if callable(getattr(self.watcher, 
"update_for_remove_filtered_policy", None)):
-                    self.watcher.update_for_remove_filtered_policy(sec, ptype, 
field_index, *field_values)
-                else:
-                    self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            if callable(getattr(self.watcher, 
"update_for_remove_filtered_policy", None)):
+                self.watcher.update_for_remove_filtered_policy(sec, ptype, 
field_index, *field_values)
+            else:
+                self.watcher.update()
 
         return rule_removed
 
@@ -205,8 +205,8 @@ class InternalEnforcer(CoreEnforcer):
             if self.adapter.remove_filtered_policy(sec, ptype, field_index, 
*field_values) is False:
                 return False
 
-            if self.watcher and self.auto_notify_watcher:
-                self.watcher.update()
+        if self.watcher and self.auto_notify_watcher:
+            self.watcher.update()
 
         return rule_removed
 
diff --git a/tests/test_watcher_ex.py b/tests/test_watcher_ex.py
index deb8347..72491dc 100644
--- a/tests/test_watcher_ex.py
+++ b/tests/test_watcher_ex.py
@@ -286,6 +286,35 @@ class TestWatcherEx(TestCaseBase):
         e.remove_policies(rules)
         self.assertEqual(w.notify_message, None)
 
+    def test_auto_notify_with_auto_save_disabled(self):
+        e = self.get_enforcer(
+            get_examples("basic_model.conf"),
+            get_examples_copy("basic_policy.csv"),
+        )
+        w = SampleWatcher()
+        e.set_watcher(w)
+        e.enable_auto_save(False)
+        e.enable_auto_notify_watcher(True)
+
+        e.add_policy("admin", "data1", "read")
+        self.assertEqual(w.notify_message, "called add policy")
+
+        e.remove_policy("admin", "data1", "read")
+        self.assertEqual(w.notify_message, "called remove policy")
+
+        e.remove_filtered_policy(1, "data1")
+        self.assertEqual(w.notify_message, "called remove filtered policy")
+
+        rules = [
+            ["jack", "data4", "read"],
+            ["katy", "data4", "write"],
+        ]
+        e.add_policies(rules)
+        self.assertEqual(w.notify_message, "called add policies")
+
+        e.remove_policies(rules)
+        self.assertEqual(w.notify_message, "called remove policies")
+
 
 class AsyncMinimalWatcher:
     """A minimal async watcher that only implements async update() method."""
@@ -384,6 +413,37 @@ class TestAsyncWatcherEx(IsolatedAsyncioTestCase):
         await e.remove_policies(rules)
         self.assertEqual(w.notify_message, None)
 
+    async def test_auto_notify_with_auto_save_disabled(self):
+        e = self.get_enforcer(
+            get_examples("basic_model.conf"),
+            get_examples_copy("basic_policy.csv"),
+        )
+        await e.load_policy()
+
+        w = AsyncSampleWatcher()
+        e.set_watcher(w)
+        e.enable_auto_save(False)
+        e.enable_auto_notify_watcher(True)
+
+        await e.add_policy("admin", "data1", "read")
+        self.assertEqual(w.notify_message, "called add policy")
+
+        await e.remove_policy("admin", "data1", "read")
+        self.assertEqual(w.notify_message, "called remove policy")
+
+        await e.remove_filtered_policy(1, "data1")
+        self.assertEqual(w.notify_message, "called remove filtered policy")
+
+        rules = [
+            ["jack", "data4", "read"],
+            ["katy", "data4", "write"],
+        ]
+        await e.add_policies(rules)
+        self.assertEqual(w.notify_message, "called add policies")
+
+        await e.remove_policies(rules)
+        self.assertEqual(w.notify_message, "called remove policies")
+
     async def test_async_minimal_watcher(self):
         """Test that a watcher with only async update() method works 
properly."""
         e = self.get_enforcer(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to