Xqt has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1246751?usp=email )
Change subject: site: raise NotImplementedError in BaseSite.__getattr__
......................................................................
site: raise NotImplementedError in BaseSite.__getattr__
- Change __getattr__ to raise NotImplementedError instead of AttributeError
- when a Family method/attribute exists but cannot be delegated.
- This improves clarity when delegated methods are missing or
- misconfigured in the family file.
- Update docstring to reflect the new behavior and move it to BaseSite
docstring to be visible in the Sphinx documentation.
Bug: T417961
Change-Id: I3d0585eb53e9ecc0a33edc93ef8dd599a3a3a4c7
---
M pywikibot/site/_basesite.py
1 file changed, 47 insertions(+), 27 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Verified; Looks good to me, approved
diff --git a/pywikibot/site/_basesite.py b/pywikibot/site/_basesite.py
index 55d54bc..19a34a5 100644
--- a/pywikibot/site/_basesite.py
+++ b/pywikibot/site/_basesite.py
@@ -33,7 +33,40 @@
class BaseSite(ComparableMixin):
- """Site methods that are independent of the communication interface."""
+ """Site methods that are independent of the communication interface.
+
+ .. hint::
+ :class:`BaseSite` delegates undefined method calls to the
+ corresponing :class:`family.Family` object by its
+ :meth:`__getattr__` method. The working method is described below.
+
+ Only public Family instance methods are delegated. A method is
+ considered delegatable if:
+
+ - it is a bound instance method of Family,
+ - it is public (name does not start with '_'),
+ - its first logical parameter is *code*.
+
+ .. note::
+ For performance reasons, the method signature is inspected
+ via the method's ``__code__`` object instead of
+ ``inspect.signature()``. This avoids expensive generic
+ introspection in this hot path and is safe because Family
+ methods are guaranteed to be pure Python.
+
+ .. versionchanged:: 9.0
+ Only delegate to public Family methods which have ``code`` as
+ first parameter.
+ .. versionchanged:: 11.0
+ Use direct ``__code__`` inspection instead of
+ ``inspect.signature()`` to significantly improve attribute
+ access performance.
+ .. versionchanged:: 11.1
+ :meth:`__getattr__` raises NotImplementedError instead of
+ AttributeError if a Family method or attribute exists but
+ cannot be delegated. This can happen if *name* is not a method
+ or the first parameter is not *code*.
+ """
def __init__(self, code: str, fam=None, user: str | None = None) -> None:
"""Initializer.
@@ -181,32 +214,14 @@
return self._username
def __getattr__(self, name: str):
- """Delegate undefined methods calls to the Family object.
-
- Only public :class:`Family instance methods are delegated.
-
- A method is considered delegatable if:
- - it is a bound instance method of Family,
- - it is public (name does not start with '_'),
- - its first logical parameter is *code*.
-
- .. note::
- For performance reasons, the method signature is inspected
- via the method's ``__code__`` object instead of
- ``inspect.signature()``. This avoids expensive generic
- introspection in this hot path and is safe because Family
- methods are guaranteed to be pure Python.
-
- .. versionchanged:: 9.0
- Only delegate to public Family methods which have ``code`` as
- first parameter.
- .. versionchanged:: 11.0
- Use direct ``__code__`` inspection instead of
- ``inspect.signature()`` to significantly improve attribute
- access performance.
- """
+ """Delegate undefined methods calls to the Family object."""
+ # See description in BaseSite class documentation
+ msg = f'{type(self).__name__} instance has no attribute {name!r}'
if not name.startswith('_'):
obj = getattr(self.family, name, None)
+ if not obj:
+ raise AttributeError(msg) from None
+
if inspect.ismethod(obj):
code = obj.__code__
params = code.co_varnames[:code.co_argcount]
@@ -216,8 +231,13 @@
method.__doc__ = obj.__doc__
return method
- raise AttributeError(f'{type(self).__name__} instance has no '
- f'attribute {name!r}') from None
+ raise NotImplementedError(
+ f"'{name}()' method of {type(self).__name__} is not "
+ f'implemented. Maybe the {self.family}_family.py family file'
+ ' is malformed'
+ ) from None
+
+ raise AttributeError(msg) from None
def __str__(self) -> str:
"""Return string representing this Site's name and code."""
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1246751?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: I3d0585eb53e9ecc0a33edc93ef8dd599a3a3a4c7
Gerrit-Change-Number: 1246751
Gerrit-PatchSet: 4
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1246180?usp=email )
Change subject: FilePage.download: use read throttle with FilePage.download
......................................................................
FilePage.download: use read throttle with FilePage.download
This implementation is needed due to Wikitech robot policy
https://wikitech.wikimedia.org/wiki/Robot_policy#Media%20API%20rules
The delay is found by tests having config.mithrottle of 0.1 s
Bug: T418672
Change-Id: I2eb121ee59d574857fe0801b8a12c03287e66d0f
---
M pywikibot/page/_filepage.py
1 file changed, 6 insertions(+), 0 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page/_filepage.py b/pywikibot/page/_filepage.py
index 5239bbf..318cebf 100644
--- a/pywikibot/page/_filepage.py
+++ b/pywikibot/page/_filepage.py
@@ -413,6 +413,12 @@
path = path.with_suffix(Path(urlparse(url).path).suffix)
# adjust user path
path = path.expanduser()
+ # use read throttle per Wikitech robot policy for download (T418672)
+ # multiply minthrottle by 25 to get an functional delay
+ self.site.throttle.set_delays(delay=25 * self.site.throttle.delay)
+ self.site.throttle()
+ self.site.throttle.set_delays()
+
req = http.fetch(url, stream=True)
if req.status_code == HTTPStatus.OK:
with open(path, 'wb') as f:
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1246180?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: I2eb121ee59d574857fe0801b8a12c03287e66d0f
Gerrit-Change-Number: 1246180
Gerrit-PatchSet: 1
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot