jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1353297?usp=email )

Change subject: api: Cache constructor argument introspection per request class
......................................................................

api: Cache constructor argument introspection per request class

Request.clean_kwargs inspects constructor signatures on every call to
separate request options from MediaWiki API parameters. Cache the
argument names per class as a frozenset so repeated generator setup
reuses the result without sharing mutable state.

Keep the existing MRO traversal and argument classification.

Change-Id: Ia5a5177b83edae6aa548cd7d16a4c8682f1a325a
---
M pywikibot/data/api/_requests.py
M tests/dry_api_tests.py
2 files changed, 32 insertions(+), 9 deletions(-)

Approvals:
  Xqt: Looks good to me, approved
  jenkins-bot: Verified




diff --git a/pywikibot/data/api/_requests.py b/pywikibot/data/api/_requests.py
index 2c13277..c800e32 100644
--- a/pywikibot/data/api/_requests.py
+++ b/pywikibot/data/api/_requests.py
@@ -20,6 +20,7 @@
 from collections.abc import Callable, MutableMapping
 from contextlib import suppress
 from email.mime.nonmultipart import MIMENonMultipart
+from functools import cache
 from pathlib import Path
 from typing import Any, NoReturn
 from urllib.parse import unquote, urlencode
@@ -297,6 +298,20 @@
              '"parameters" parameter.', DeprecationWarning, 3)

     @classmethod
+    @cache
+    def _get_constructor_args(cls) -> frozenset[str]:
+        """Return cached constructor argument names for this request class."""
+        args = set()
+        for super_cls in inspect.getmro(cls):
+            if not super_cls.__name__.endswith('Request'):
+                break
+            args |= set(inspect.getfullargspec(super_cls.__init__).args)
+        else:
+            raise ValueError(f'Request was not a super class of {cls!r}')
+
+        return frozenset(args - {'self'})
+
+    @classmethod
     def clean_kwargs(cls, kwargs: dict) -> dict:
         """Convert keyword arguments into new parameters mode.

@@ -313,15 +328,7 @@
         if 'expiry' in kwargs and kwargs['expiry'] is None:
             del kwargs['expiry']

-        args = set()
-        for super_cls in inspect.getmro(cls):
-            if not super_cls.__name__.endswith('Request'):
-                break
-            args |= set(inspect.getfullargspec(super_cls.__init__).args)
-        else:
-            raise ValueError(f'Request was not a super class of {cls!r}')
-
-        args -= {'self'}
+        args = cls._get_constructor_args()
         old_kwargs = set(kwargs)
         # all kwargs defined above but not in args indicate 'kwargs' mode
         if old_kwargs - args:
diff --git a/tests/dry_api_tests.py b/tests/dry_api_tests.py
index 21eb37e..9e6b6a8 100755
--- a/tests/dry_api_tests.py
+++ b/tests/dry_api_tests.py
@@ -423,6 +423,22 @@

     dry = True

+    def test_cached_constructor_args(self) -> None:
+        """Reuse constructor arguments without sharing subclass results."""
+        kwargs = {'site': self.site, 'parameters': {'action': 'query'}}
+        cached_kwargs = dict(kwargs, expiry=1)
+        Request._get_constructor_args.cache_clear()
+        self.addCleanup(Request._get_constructor_args.cache_clear)
+        self.assertEqual(Request.clean_kwargs(kwargs), kwargs)
+        self.assertEqual(CachedRequest.clean_kwargs(cached_kwargs),
+                         cached_kwargs)
+
+        with patch('pywikibot.data.api._requests.inspect.getfullargspec',
+                   side_effect=AssertionError('Repeated introspection')):
+            self.assertEqual(Request.clean_kwargs(kwargs), kwargs)
+            self.assertEqual(CachedRequest.clean_kwargs(cached_kwargs),
+                             cached_kwargs)
+
     def test_query_constructor(self) -> None:
         """Test QueryGenerator constructor."""
         q_gen1 = QueryGenerator(

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1353297?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: Ia5a5177b83edae6aa548cd7d16a4c8682f1a325a
Gerrit-Change-Number: 1353297
Gerrit-PatchSet: 3
Gerrit-Owner: Mahveotm <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to