Просмотр исходного кода

fix(extras): Use full_name for Script logger namespace (#22964)

Changes Script logger initialization to use `full_name` property instead
of reconstructing the namespace from `__module__` and
`__class__.__name__`.
Ensures dynamically loaded Scripts log to the correct public namespace.

Fixes #22953
Martin Hauser 2 дней назад
Родитель
Сommit
fb86029507
2 измененных файлов с 31 добавлено и 1 удалено
  1. 1 1
      netbox/extras/scripts.py
  2. 30 0
      netbox/extras/tests/test_scripts.py

+ 1 - 1
netbox/extras/scripts.py

@@ -326,7 +326,7 @@ class BaseScript:
         self._current_test = None  # Tracks the current test method being run (if any)
 
         # Initiate the log
-        self.logger = logging.getLogger(f"netbox.scripts.{self.__module__}.{self.__class__.__name__}")
+        self.logger = logging.getLogger(f"netbox.scripts.{self.full_name}")
 
         # Declare the placeholder for the current request
         self.request = None

+ 30 - 0
netbox/extras/tests/test_scripts.py

@@ -439,3 +439,33 @@ class ScriptModuleLoadingTestCase(TestCase):
         # The real circuits app must be untouched and remain an importable package
         self.assertIs(sys.modules['circuits'], circuits)
         self.assertTrue(hasattr(circuits, '__path__'))
+
+    def test_script_logger_uses_public_module_name(self):
+        """
+        A dynamically loaded script logs to the public netbox.scripts.<module>.<class> namespace.
+        """
+        script_content = (
+            b"from extras.scripts import Script\n\n\n"
+            b"class TestScript(Script):\n    pass\n"
+        )
+
+        class _Storage:
+            def open(self, name, mode='rb'):
+                return io.BytesIO(script_content)
+
+        module = ScriptModule(file_root='scripts', file_path='example.py')
+        namespaced_key = f'{SCRIPT_MODULE_NAME_PREFIX}example'
+        self.addCleanup(lambda: sys.modules.pop(namespaced_key, None))
+
+        with patch('extras.models.mixins.storages') as mock_storages:
+            mock_storages.__getitem__.return_value = _Storage()
+            script_class = module.get_module().TestScript
+
+        # This is the name runscript and ScriptJob attach their handlers to
+        logger_name = f'netbox.scripts.{script_class.full_name}'
+        script = script_class()
+        self.assertEqual(script.logger.name, logger_name)
+
+        with self.assertLogs(logger_name, 'INFO') as captured:
+            script.log_success('Start')
+        self.assertIn('Start', captured.output[0])