jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/841471 )
Change subject: [doc] Refer APISite.categorymembers for Category.articles parameters ......................................................................
[doc] Refer APISite.categorymembers for Category.articles parameters
- Only allow keyword arguments with Category.articles() - use **kwargs to pass parameters to the underlying APISite.categorymembers() - refer to categorymembers for parameter documentation - raise TypeError instead of pywikibot.Error in categorymembers() if category is not a Category page. - update documentation
Bug: T320455 Change-Id: I83468a5cd3c062214c82542d6371a0daa84260d3 --- M pywikibot/page/_category.py M pywikibot/site/_generators.py 2 files changed, 75 insertions(+), 75 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/page/_category.py b/pywikibot/page/_category.py index 398cd3c..4a7e718 100644 --- a/pywikibot/page/_category.py +++ b/pywikibot/page/_category.py @@ -5,10 +5,10 @@ # Distributed under the terms of the MIT license. # from collections import defaultdict -from typing import Optional, Union +from typing import Any, Optional, Union
import pywikibot -from pywikibot.backports import Generator, List +from pywikibot.backports import Generator, Iterable from pywikibot.page._page import Page
@@ -119,61 +119,52 @@ if total == 0: return
- def articles(self, + def articles(self, *, recurse: Union[int, bool] = False, total: Optional[int] = None, - content: bool = False, - namespaces: Union[int, List[int]] = None, - sortby: Optional[str] = None, - reverse: bool = False, - starttime=None, endtime=None, - startprefix: Optional[str] = None, - endprefix: Optional[str] = None): + **kwargs: Any) -> Iterable[Page]: """ Yield all articles in the current category.
- By default, yields all *pages* in the category that are not - subcategories! + By default, yields all pages in the category that are not + subcategories. + + **Usage:** + + >>> site = pywikibot.Site('wikipedia:test') + >>> cat = pywikibot.Category(site, 'Pywikibot') + >>> list(cat.articles()) + [Page('Pywikibot nobots test')] + >>> for p in cat.articles(recurse=1, namespaces=2, total=3): + ... print(p.depth) + ... + 2 + 3 + 4 + + .. versionchanged:: 8.0.0 + all parameters are keyword arguments only.
:param recurse: if not False or 0, also iterate articles in subcategories. If an int, limit recursion to this number of - levels. (Example: recurse=1 will iterate articles in first-level - subcats, but no deeper.) + levels. (Example: ``recurse=1`` will iterate articles in + first-level subcats, but no deeper.) :param total: iterate no more than this number of pages in total (at all levels) - :param namespaces: only yield pages in the specified namespaces - :param content: if True, retrieve the content of the current version - of each page (default False) - :param sortby: determines the order in which results are generated, - valid values are "sortkey" (default, results ordered by category - sort key) or "timestamp" (results ordered by time page was - added to the category). This applies recursively. - :param reverse: if True, generate results in reverse order - (default False) - :param starttime: if provided, only generate pages added after this - time; not valid unless sortby="timestamp" - :type starttime: pywikibot.Timestamp - :param endtime: if provided, only generate pages added before this - time; not valid unless sortby="timestamp" - :type endtime: pywikibot.Timestamp - :param startprefix: if provided, only generate pages >= this title - lexically; not valid if sortby="timestamp" - :param endprefix: if provided, only generate pages < this title - lexically; not valid if sortby="timestamp" - :rtype: typing.Iterable[pywikibot.Page] + :param kwargs: Additional parameters. Refer + :meth:`APISite.categorymembers() + <pywikibot.site._generators.GeneratorsMixin.categorymembers>` + for them except of *member_type*. """ + if kwargs.pop('member_type', False): + raise TypeError( + "articles() got an unexpected keyword argument 'member_type'") + seen = set() for member in self.site.categorymembers(self, - namespaces=namespaces, total=total, - content=content, - sortby=sortby, - reverse=reverse, - starttime=starttime, - endtime=endtime, - startprefix=startprefix, - endprefix=endprefix, - member_type=['page', 'file']): + member_type=['page', 'file'], + **kwargs): if recurse: seen.add(hash(member)) yield member @@ -188,14 +179,7 @@ for subcat in self.subcategories(): for article in subcat.articles(recurse=recurse, total=total, - content=content, - namespaces=namespaces, - sortby=sortby, - reverse=reverse, - starttime=starttime, - endtime=endtime, - startprefix=startprefix, - endprefix=endprefix): + **kwargs): hash_value = hash(article) if hash_value in seen: continue diff --git a/pywikibot/site/_generators.py b/pywikibot/site/_generators.py index b3d6621..25f205f 100644 --- a/pywikibot/site/_generators.py +++ b/pywikibot/site/_generators.py @@ -461,19 +461,33 @@ titles=tltitle, namespaces=namespaces, total=total, g_content=content)
- def categorymembers(self, category, *, - namespaces=None, - sortby: Optional[str] = None, - reverse: bool = False, - starttime=None, - endtime=None, - total: Optional[int] = None, - content: bool = False, - member_type=None, - startprefix: Optional[str] = None, - endprefix: Optional[str] = None): + def categorymembers( + self, + category: 'pywikibot.Category', *, + namespaces=None, + sortby: Optional[str] = None, + reverse: bool = False, + starttime: Optional[pywikibot.time.Timestamp] = None, + endtime: Optional[pywikibot.time.Timestamp] = None, + total: Optional[int] = None, + startprefix: Optional[str] = None, + endprefix: Optional[str] = None, + content: bool = False, + member_type: Union[str, Iterable[str], None] = None + ) -> Iterable['pywikibot.Page']: """Iterate members of specified category.
+ You should not use this method directly; instead use one of the + following: + + - :meth:`pywikibot.Category.articles` + - :meth:`pywikibot.Category.members` + - :meth:`pywikibot.Category.subcategories` + + .. versionchanged:: 4.0.0 + parameters except *category* are keyword arguments only. + .. versionchanged:: 8.0.0 + raises TypeError instead of Error if no Category is specified .. seealso:: :api:`Categorymembers`
:param category: The Category to iterate. @@ -491,7 +505,6 @@ (default False) :param starttime: if provided, only generate pages added after this time; not valid unless sortby="timestamp" - :type starttime: time.Timestamp :param endtime: if provided, only generate pages added before this time; not valid unless sortby="timestamp" :param startprefix: if provided, only generate pages >= this title @@ -500,19 +513,20 @@ lexically; not valid if sortby="timestamp" :param content: if True, load the current content of each iterated page (default False) - :param member_type: member type; if member_type includes 'page' and is - used in conjunction with sortby="timestamp", the API may limit - results to only pages in the first 50 namespaces. - :type member_type: str or iterable of str; - values: page, subcat, file - :rtype: typing.Iterable[pywikibot.Page] + :param member_type: member type; values must be ``page``, + ``subcat``, ``file``. If member_type includes ``page`` and + is used in conjunction with sortby="timestamp", the API may + limit results to only pages in the first 50 namespaces. + :raises KeyError: a namespace identifier was not resolved :raises TypeError: a namespace identifier has an inappropriate type such as NoneType or bool + :raises TypeError: no Category is specified + :raises ValueError: invalid values given """ if category.namespace() != 14: - raise Error('categorymembers: non-Category page {!r} specified' - .format(category)) + raise TypeError( + f'categorymembers: non-Category page {category!r} specified')
cmtitle = category.title(with_section=False).encode(self.encoding()) cmargs = { @@ -524,12 +538,13 @@ if sortby in ['sortkey', 'timestamp']: cmargs['gcmsort'] = sortby elif sortby: - raise ValueError('categorymembers: invalid sortby value {!r}' - .format(sortby)) + raise ValueError( + f'categorymembers: invalid sortby value {sortby!r}')
if starttime and endtime and starttime > endtime: raise ValueError( 'categorymembers: starttime must be before endtime') + if startprefix and endprefix and startprefix > endprefix: raise ValueError( 'categorymembers: startprefix must be less than endprefix') @@ -543,6 +558,7 @@
if 'page' in member_type: excluded_namespaces = set() + if 'file' not in member_type: excluded_namespaces.add(6) if 'subcat' not in member_type: @@ -551,8 +567,8 @@ if namespaces: if excluded_namespaces.intersection(namespaces): raise ValueError( - 'incompatible namespaces {!r} and member_type {!r}' - .format(namespaces, member_type)) + f'incompatible namespaces {namespaces!r} and ' + f'member_type {member_type!r}') # All excluded namespaces are not present in `namespaces`. else: # If the number of namespaces is greater than permitted by